Ce que couvre ce guide
Ce guide concerne l'application réelle livrée dans orbite-app.zip : un serveur Django, une base PostgreSQL et une seule adresse web pour les trois profils. Les fichiers de maquettes (orbite-ba.html, orbite-superviseur.html, orbite-console-manager.html) ne se déploient pas : ils servent aux démonstrations.
| Conteneur | Rôle |
|---|---|
db | Base PostgreSQL 16, volume orbite_db |
web | Application, derrière Traefik en HTTPS ; photos dans orbite_media, sauvegardes dans orbite_backups |
scheduler | Tâches planifiées : escalades et contre-visites toutes les 5 minutes ; sauvegarde, test de restauration et purge chaque nuit |
Prérequis
- Un VPS Linux avec Docker et Docker Compose (commande
docker compose). - Un Traefik déjà en service sur ce VPS, relié à un réseau Docker externe, avec un résolveur de certificats Let's Encrypt.
- Un sous-domaine (par exemple
orbite.tstdigitalproducts.com) dont l'enregistrement DNS de type A pointe vers l'adresse IP du VPS. - L'archive
orbite-app.zip. Elle ne contient ni fichier.env, ni base, ni photos. - Un coffre-fort ou un gestionnaire de mots de passe, hors du serveur, pour garder les clés de chiffrement.
Installer
- Copier l'archive sur le VPS, depuis le PC Windows (PowerShell) :
scp .\orbite-app.zip root@<ip-du-vps>:/opt/ - Décompresser sur le VPS :
ssh root@<ip-du-vps> cd /opt && unzip orbite-app.zip && cd orbite-appSi
unzipmanque :apt install -y unzip. - Préparer le fichier de configuration :
cp .env.example .env openssl rand -base64 48 # à coller dans ORBITE_SECRET_KEY openssl rand -base64 32 # à coller dans ORBITE_MEDIA_KEY openssl rand -base64 32 # à coller dans ORBITE_BACKUP_KEY (clé différente) nano .envLe détail de chaque variable est dans la section suivante.
- Trouver le nom du réseau Traefik et le reporter dans
TRAEFIK_NETWORK:docker network ls - Construire et démarrer :
docker compose up -d --build docker compose psdb,webetschedulerdoivent apparaître « healthy » ou « running ». La base est créée et mise à niveau au démarrage. - Créer le premier manager : voir la section dédiée.
Le fichier .env
Sans les valeurs obligatoires, l'application refuse de démarrer. Ce fichier ne se partage pas et ne se versionne jamais.
| Variable | Contenu |
|---|---|
ORBITE_DOMAIN | Le sous-domaine, sans https : orbite.tstdigitalproducts.com |
ORBITE_HOSTS | Le même nom (plusieurs noms séparés par des virgules) |
ORBITE_CSRF_ORIGINS | L'adresse complète avec https : https://orbite.tstdigitalproducts.com |
ORBITE_DEBUG | 0 en production, toujours |
ORBITE_SECRET_KEY | Clé Django, 40 caractères au moins |
ORBITE_MEDIA_KEY | Chiffrement des photos et selfies au repos |
ORBITE_BACKUP_KEY | Chiffrement des sauvegardes, différente de la précédente |
ORBITE_DB_PASSWORD | Mot de passe PostgreSQL, long et aléatoire |
TRAEFIK_NETWORK | Réseau Docker de Traefik (traefik par défaut) |
TRAEFIK_ENTRYPOINT | Point d'entrée HTTPS de Traefik (websecure par défaut) |
TRAEFIK_CERTRESOLVER | Résolveur de certificats (letsencrypt par défaut) |
Variables facultatives
| Variable | Effet |
|---|---|
ORBITE_ALERT_WEBHOOK | Adresse d'un webhook (n8n, Slack…) qui reçoit chaque erreur technique, y compris un test de restauration raté |
ORBITE_BACKUP_HOUR | Heure de la sauvegarde nocturne (2 h par défaut) |
ORBITE_BACKUP_KEEP | Nombre de sauvegardes conservées (14 par défaut) |
ORBITE_ADMIN | 1 rouvre l'administration Django. À laisser absent en temps normal |
ORBITE_MEDIA_KEY et ORBITE_BACKUP_KEY hors du serveur, dès maintenant. Sans elles, les photos et les sauvegardes sont définitivement illisibles, même pour TST.Premier compte manager
docker compose exec web python manage.py create_manager <identifiant> <Prénom> <Nom>
Exemple : create_manager marie.ngoma Marie Ngoma. Utiliser le vrai nom du manager : la documentation d'origine prenait « awa.mabiala Awa Mabiala » comme exemple. Noter le mot de passe défini ou affiché par la commande.
À sa première connexion, le manager active la double authentification : ORBITE affiche un code à scanner avec une application d'authentification (Google Authenticator, Microsoft Authenticator), puis huit codes de secours à garder en lieu sûr. Ensuite, chaque connexion demande le code à 6 chiffres de l'application.
Créer au moins deux managers. Avec deux managers actifs, les changements de paramètres et les confirmations de fraude exigent la validation du second, et un manager peut débloquer l'autre s'il perd son téléphone.
Recette technique
À dérouler après l'installation, puis après chaque mise à jour.
docker compose ps: les trois conteneurs sont « healthy » ou « running ».- L'adresse
https://<domaine>/connexion/s'ouvre avec un cadenas valide. - Le manager se connecte et active sa double authentification.
- Un BA de test se connecte sur un vrai téléphone Android : le navigateur demande la position et la caméra, puis la prise de service fonctionne.
- Une visite de test apparaît au journal d'audit avec la bonne heure. Si l'heure est décalée par rapport à Brazzaville, le signaler avant le pilote : les compteurs « jour en cours » en dépendent.
- Le lendemain matin :
docker compose exec web ls /data/backupsmontre la sauvegarde de la nuit, et le journal d'audit indique « Test de restauration réussi ».
Installation actuelle : points à vérifier
ORBITE tourne déjà sur le VPS. Avant les tests terrain :
- Comptes de démonstration : les identifiants qui se terminent par
.demo(mot de passeorbite2026) viennent du jeu de démonstration. S'ils existent en production, les suspendre depuis « Équipes et utilisateurs ». - Nom d'exemple : si le compte « Awa Mabiala » a été créé en suivant l'exemple de la documentation, créer les comptes des vrais managers, puis suspendre celui-ci.
- Clés : vérifier que
ORBITE_MEDIA_KEYetORBITE_BACKUP_KEYsont copiées hors du serveur. - Sauvegardes : vérifier qu'une sauvegarde existe et qu'une copie part hors du serveur (voir plus bas).
- Webhook : renseigner
ORBITE_ALERT_WEBHOOKpour être prévenu d'une panne sans attendre un appel du terrain.
Préparer le pilote
- Équipes et comptes (Manager, « Équipes et utilisateurs ») : créer les équipes, puis les superviseurs, puis les BAs. Le mot de passe provisoire et le code d'activation ne s'affichent qu'une fois : les remettre en main propre.
- Points marchands (Manager, « Points et QR ») : importer un fichier CSV en UTF-8, séparateur
;ou,. Utiliser d'abord « Simuler », qui n'écrit rien, puis « Importer ».code;nom;msisdn;segment;zone;equipe;ba;lat;lon;adresse PT-00001;Boutique Mama Nzola;055123456;A;Poto-Poto;Poto-Poto;grace.m;-4.2690;15.2780;avenue de la Paix PT-00002;Kiosque Mampassi;55987654;B;Poto-Poto;Poto-Poto;grace.m;;;marché TotalLe numéro doit être un numéro Airtel (04 ou 05) ; un numéro à 8 chiffres est complété par le 0 initial. Sans coordonnées, le point est recensé au premier passage.
baest l'identifiant du BA qui a le point en portefeuille. - QR : imprimer la planche de chaque équipe sur étiquettes autocollantes et les poser chez les marchands. Imprimer aussi des QR neufs pour les créations de points.
- Tournées : rien à faire. Elles se génèrent à la première ouverture de l'application par le BA, chaque jour.
- Paramètres : vérifier périmètre, précisions GPS, seuils du score, délai d'escalade, taux de contre-visite et taille des tournées.
Exploitation et sauvegardes
Ce qui tourne seul
- Toutes les 5 minutes : escalade des alertes en retard, alertes d'inactivité, tirage des contre-visites, expiration des validations en attente.
- Chaque nuit (2 h par défaut) : sauvegarde chiffrée de la base et des photos, test de restauration dans une base jetable, purge des durées de conservation (positions 90 jours, selfies 30 jours, photos 13 mois).
Aucune crontab n'est à créer sur le VPS : le conteneur scheduler s'en charge.
Sauvegardes à la demande
docker compose exec web python manage.py backup_orbite --check # sauvegarde immédiate, vérifiée
docker compose exec web python manage.py restore_check # re-tester la dernière sauvegarde
docker compose exec web ls /data/backups # lister les sauvegardes
Copier les sauvegardes hors du serveur
Une sauvegarde restée sur le VPS ne protège pas contre la perte du VPS. Les fichiers sont chiffrés : on peut les copier sans risque, à condition de garder les clés ailleurs.
cd /opt/orbite-app && docker compose cp web:/data/backups /root/orbite-backups
# puis, depuis le PC Windows (PowerShell) :
scp -r root@<ip-du-vps>:/root/orbite-backups .
À automatiser chaque nuit vers un autre serveur ou un stockage de l'entreprise.
Journaux
docker compose logs --tail=100 web
docker compose logs web | grep <référence> # référence affichée à l'utilisateur en cas d'erreur
Mettre à jour
Hors des heures de terrain, quand aucun BA n'envoie de visites.
- Sauvegarder et vérifier :
cd /opt/orbite-app docker compose exec web python manage.py backup_orbite --check - Garder une copie du code actuel :
cd /opt && cp -a orbite-app orbite-app.avant-$(date +%F) - Décompresser la nouvelle version dans le même dossier. Le fichier
.envn'est pas dans l'archive : il est conservé.unzip -o orbite-app.zip -d /opt - Reconstruire et vérifier :
cd /opt/orbite-app docker compose up -d --build docker compose exec web python manage.py migrate docker compose ps docker compose logs --tail=50 web - Dérouler la recette technique.
/opt/orbite-app2 créerait une base, des photos et des sauvegardes vides : l'application repartirait de zéro.Cas particuliers
- Version installée antérieure au durcissement de sécurité : chaque téléphone déjà lié doit recevoir un nouveau code d'activation (« Changer de téléphone »).
- Version installée antérieure au chiffrement des photos : lancer une fois
docker compose exec web python manage.py encrypt_media.
Retour arrière
cd /opt && mv orbite-app orbite-app.echec && mv orbite-app.avant-AAAA-MM-JJ orbite-app
cd orbite-app && docker compose up -d --build
Si la nouvelle version a modifié la base, l'ancien code peut ne plus fonctionner avec elle : passer alors par la restauration de la sauvegarde prise à l'étape 1.
Restaurer après incident
Sur un serveur neuf, ou sur une installation dont la base est vide :
- Installer ORBITE comme ci-dessus avec le même
.env, donc les mêmes clés. - Copier la sauvegarde dans le conteneur :
docker compose cp orbite-AAAAMMJJ-HHMMSS.obak web:/data/backups/ - Restaurer :
docker compose exec web python manage.py restore_orbite /data/backups/orbite-AAAAMMJJ-HHMMSS.obak
La restauration est refusée si la base contient déjà des points ou des visites. L'option --force passe outre : ne l'utiliser qu'en sachant exactement ce qui sera écrasé.
Commandes de référence
Toutes se lancent depuis /opt/orbite-app, préfixées par docker compose exec web python manage.py.
| Commande | Usage |
|---|---|
create_manager id Prénom Nom | Créer un compte manager |
reset_2fa id | Réinitialiser la double authentification d'un manager, si aucun autre manager ne peut le faire |
backup_orbite [--check] | Sauvegarde chiffrée, avec test de restauration si --check |
restore_check [fichier] | Tester une sauvegarde dans une base jetable, sans toucher à la production |
restore_orbite fichier | Restauration réelle, base vide exigée |
encrypt_media | Chiffrer les photos encore stockées en clair |
purge_retention | Appliquer les durées de conservation (déjà faite chaque nuit) |
seed_demo | Jeu de démonstration. Jamais en production |
Dépannage
| Symptôme | Que faire |
|---|---|
| Un conteneur n'est pas « healthy » | docker compose logs --tail=100 web. Le plus souvent, une valeur obligatoire manque dans .env. |
| Page inaccessible ou sans cadenas | Vérifier le DNS du sous-domaine, puis TRAEFIK_NETWORK, TRAEFIK_ENTRYPOINT et TRAEFIK_CERTRESOLVER. |
| GPS ou caméra refusés sur le téléphone | Vérifier le HTTPS, puis les autorisations du site dans le navigateur. |
| Message d'erreur avec une référence | docker compose logs web | grep <référence> |
| Manager bloqué par la double authentification | Un autre manager la réinitialise depuis la console, avec un motif. Sinon : reset_2fa identifiant. |
| Compte bloqué après des erreurs de mot de passe | Blocage automatique de 15 minutes après 5 échecs. Attendre. |
| Besoin de l'administration Django | Elle est fermée en production, car elle contourne la double authentification. ORBITE_ADMIN=1 puis docker compose up -d la rouvre ; retirer la ligne juste après. |
| Photos illisibles après restauration | ORBITE_MEDIA_KEY n'est pas celle de l'ancien serveur. |