Aller au contenu

Déploiement

Cible : un VPS Linux (Ubuntu 22.04 ou plus) avec Docker. Architecture :

Internet ─▶ Nginx (port 80/443) ─▶ Gunicorn + workers Uvicorn (ASGI, web:8000) ─▶ PostgreSQL (db)
│ └─▶ Redis (cache)
└─ sert /static/ et /media/ directement
Fenêtre de terminal
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER

Pointer le domaine (enregistrement DNS A) vers l’adresse IP du serveur.

Fenêtre de terminal
git clone https://github.com/Aziguy/fleaMarketOnline.git /opt/mfoundi
cd /opt/mfoundi
cp .env.example .env

Éditer .env : SECRET_KEY, ALLOWED_HOSTS, CSRF_TRUSTED_ORIGINS, mots de passe PostgreSQL (identiques dans POSTGRES_PASSWORD et DATABASE_URL), SMTP, ADMINS, et pour la sécurité des comptes MFA_ENCRYPTION_KEY, WEBAUTHN_RP_ID et TRUSTED_PROXY_COUNT. Voir Configuration.

Générer les deux clés secrètes :

Fenêtre de terminal
python3 -c "import secrets; print(secrets.token_urlsafe(50))"

Conservez MFA_ENCRYPTION_KEY avec vos sauvegardes : sans elle, les applications d’authentification des utilisateurs ne fonctionnent plus (ils doivent alors passer par leurs codes de secours).

Fenêtre de terminal
docker compose -f docker-compose.prod.yml up -d --build

Le conteneur web sert l’application en ASGI (Gunicorn avec workers Uvicorn), indispensable au flux temps réel des commerçants. Nginx transmet /espace-boutique/flux/ sans tampon (voir docker/nginx/default.conf) ; tout reverse proxy placé devant doit faire de même (proxy_buffering off, délai de lecture ≥ 6 minutes).

Au démarrage, le conteneur web applique les migrations puis collecte les fichiers statiques (désactivable avec RUN_MIGRATIONS=0 / COLLECTSTATIC=0).

Créer le compte administrateur du mall :

Fenêtre de terminal
docker compose -f docker-compose.prod.yml exec web python manage.py createsuperuser

Connectez-vous ensuite sur le site, ouvrez Sécurité du compte et activez une application d’authentification ou une clé d’accès : c’est obligatoire pour accéder à /admin/. Notez les codes de secours affichés.

Le plus simple : placer un reverse proxy TLS devant Nginx (Caddy, Traefik) ou utiliser Certbot sur l’hôte. Exemple avec Certbot et Nginx sur l’hôte : faire écouter le conteneur Nginx en local uniquement (HTTP_PORT=127.0.0.1:8080 dans .env), puis :

Fenêtre de terminal
sudo apt install nginx certbot python3-certbot-nginx
sudo certbot --nginx -d mfoundimall.cm -d www.mfoundimall.cm

avec un bloc location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }.

Avec ce proxy supplémentaire devant le conteneur Nginx, définir TRUSTED_PROXY_COUNT=2 : l’application lit ainsi la vraie adresse des visiteurs (limitation des essais de connexion, liste des appareils). Une valeur trop faible fait partager un même compteur à tous les visiteurs ; une valeur trop forte permet à un visiteur de falsifier son adresse.

Une fois HTTPS validé, définir SECURE_HSTS_SECONDS=31536000.

Fenêtre de terminal
cd /opt/mfoundi
git pull
docker compose -f docker-compose.prod.yml up -d --build

La reconstruction installe les nouvelles dépendances et le démarrage applique les migrations. Comparez .env avec .env.example après chaque mise à jour : de nouvelles variables peuvent y apparaître.

Base de données :

Fenêtre de terminal
docker compose -f docker-compose.prod.yml exec -T db pg_dump -U mfoundi mfoundi | gzip > backup-$(date +%F).sql.gz

Fichiers envoyés (volume media) :

Fenêtre de terminal
docker run --rm -v mfoundi_media:/data -v $PWD:/backup alpine tar czf /backup/media-$(date +%F).tar.gz -C /data .

Restauration de la base :

Fenêtre de terminal
gunzip -c backup-AAAA-MM-JJ.sql.gz | docker compose -f docker-compose.prod.yml exec -T db psql -U mfoundi mfoundi

Planifier ces commandes (cron) et copier les archives hors du serveur.

https://votre-domaine/healthz renvoie l’état de la base et du cache (200 ou 503) : branchez-y votre outil de supervision (UptimeRobot, Uptime Kuma…). Docker utilise python manage.py healthcheck pour l’état du conteneur.

Les logs sont au format JSON, une ligne par requête avec son request_id : un identifiant fourni par un utilisateur (en-tête X-Request-ID d’une réponse) permet de retrouver tous les logs de sa requête.

Fenêtre de terminal
docker compose -f docker-compose.prod.yml logs -f web
Fenêtre de terminal
docker compose -f docker-compose.prod.yml ps

Les erreurs 500 sont envoyées par e-mail aux ADMINS si le SMTP est configuré.

  • SECRET_KEY unique et secrète, .env non versionné
  • ALLOWED_HOSTS et CSRF_TRUSTED_ORIGINS renseignés
  • SMTP testé (mot de passe oublié)
  • HTTPS actif, puis HSTS
  • MFA_ENCRYPTION_KEY fixée et sauvegardée, WEBAUTHN_RP_ID égal au domaine public (les clés d’accès exigent HTTPS)
  • TRUSTED_PROXY_COUNT égal au nombre de proxys devant Django (1 par défaut, 2 avec un proxy HTTPS sur l’hôte)
  • Comptes administrateurs : double authentification activée (obligatoire pour ouvrir /admin/)
  • Sauvegardes planifiées et restauration testée
  • python manage.py check --deploy sans erreur