# Déploiement production (Synology DS220+ / DSM 7.3) — Astro → Nginx statique > ✅ **CANONIQUE** — Procédure de référence “prod DS220+ / DSM 7.3”. > Toute modif de déploiement doit être faite **ici**, via PR sur Gitea/main (pas d’édition à la main en prod). > Périmètre : build Docker (Node→Nginx), blue/green 8081/8082, Reverse Proxy DSM, smoke, rollback. > Dépendances critiques : variables PUBLIC_GITEA_* (sinon “Proposer” part en 404/login loop). > Voir aussi : OPS-REFERENCE.md (index), OPS_COCKPIT.md (checklist), TROUBLESHOOTING.md (incidents). Dernière mise à jour : 2026-02-01 Ce document décrit une mise en place stable sur NAS : - build Astro dans une image (Node) - runtime Nginx statique - bascule blue/green via Reverse Proxy DSM - tests fonctionnels (dont “Proposer” → Gitea) --- ## 1) Arborescence recommandée Dossier racine “courant” : - `/volume2/docker/archicratie-web/current` (symlink vers la release active) Contenu attendu : - `Dockerfile` - `docker-compose.yml` - `nginx.conf` - `.env` - le code du site (package.json, src/, scripts/, etc.) - `ops/` (scripts de smoke, etc.) Releases : - `/volume2/docker/archicratie-web/releases//app` --- ## 2) Pré-requis DSM - DSM 7.3 avec accès SSH (admin) - Docker / Container Manager installé - Reverse Proxy DSM configuré (Portail des applications) - Sortie Internet OK depuis le NAS (résolution DNS + accès registry) --- ## 3) Sécurité réseau (important) On publie le site via **HTTPS 443** sur DSM Reverse Proxy. Les ports 8081/8082 : - bindés en **localhost uniquement** (`127.0.0.1:8081:80`, `127.0.0.1:8082:80`) - **n’ont PAS besoin d’être ouverts** dans le pare-feu WAN - servent uniquement à DSM Reverse Proxy (loopback) --- ## 4) Variables Gitea (FEATURE “Proposer”) Le site injecte des variables “publiques” au build : - `PUBLIC_GITEA_BASE` (URL gitea) - `PUBLIC_GITEA_OWNER` (**casse sensible**) - `PUBLIC_GITEA_REPO` Exemple dans `.env` : PUBLIC_GITEA_BASE=https://gitea.archicratie.trans-hands.synology.me PUBLIC_GITEA_OWNER=Archicratia PUBLIC_GITEA_REPO=archicratie-edition ### 4.1 Piège validé : mauvais owner/repo ⇒ 404/redirect Symptômes typiques : - nouvel onglet “Proposer” ouvre `/archicratia/archicratie-web/...` (mauvais) - Gitea renvoie 404 “page inexistante ou non autorisé” - ou 303 `/user/login` (si non loggé) Contrôle rapide : en sh for f in .env .env.local .env.production .env.production.local; do [ -f "$f" ] && echo "---- $f" && grep -nE '^PUBLIC_GITEA_(BASE|OWNER|REPO)=' "$f" || true done En cas d’échec : - 404 / login loop / mauvais repo → `docs/TROUBLESHOOTING.md#proposer-404` - double onglet → `docs/TROUBLESHOOTING.md#proposer-double-onglet` ## Diagnostic — “Proposer” (résumé) **Symptôme :** clic “Proposer” → 404 / login / mauvais repo **Cause la plus fréquente :** `PUBLIC_GITEA_OWNER` (casse sensible) ou `PUBLIC_GITEA_REPO` faux. ➡️ Procédure complète (pas-à-pas + commandes) : voir `docs/TROUBLESHOOTING.md#proposer-404`. ## 5) Reverse Proxy DSM (le point clé) ### DSM 7.3 : Panneau de configuration → Portail des applications → Proxy inversé Règle pour le site : Source : HTTPS / archicratie.trans-hands.synology.me / port 443 Destination : HTTP / 127.0.0.1 / port 8081 (BLUE) ou 8082 (GREEN) Certificat : Sécurité → Certificat : associer le bon certificat au nom de domaine. ## 6) Notes DS220+ “spécificités” ### 6.1 Build réseau (DNS/apt/npm) : mode robuste Sur DSM, il arrive que apt-get/npm aient des soucis réseau pendant docker build. Mesures robustes validées : build en --network host apt-get avec retries + ForceIPv4 Exemple (dans Dockerfile) : apt-get -o Acquire::Retries=5 -o Acquire::ForceIPv4=true ... ### 6.2 BuildKit / buildx / API Docker (DSM) Certains environnements DSM peuvent : exiger BuildKit pour --network=host au build avoir des incompatibilités d’API (client/daemon) Standard “chez nous” : activer BuildKit au build utiliser DOCKER_API_VERSION="$API" si requis sur la machine Remarque : la valeur de $API est celle validée localement sur le NAS. ### 6.3 Artefacts Mac (PaxHeader / ._ / DS_Store) Si tu transfères une archive depuis macOS, tu peux embarquer des fichiers parasites. Conséquence possible : Astro “voit” un faux contenu → erreurs de schema. Remède : .dockerignore robuste (voir docs anchors / ops) éviter les copies “tar” non nettoyées ## 7) Cycle blue/green (procédure protocolaire) ### 7.1 Identifier quel slot est actuellement “en prod” Comparer l’ETag/Last-Modified public avec 8081/8082 : curl -kI https://archicratie.trans-hands.synology.me/ | egrep -i 'etag:|last-modified:|server:' curl -fsSI http://127.0.0.1:8081/ | egrep -i 'etag:|last-modified:' curl -fsSI http://127.0.0.1:8082/ | egrep -i 'etag:|last-modified:' Le port qui “match” est le slot actif. ### 7.2 Déployer sur le slot inactif (ex: GREEN 8082) # Se placer sur le checkout courant : cd /volume2/docker/archicratie-web/current || exit 1 # Charger .env dans le shell (pour les build-args) : set -a . ./.env set +a # Rebuild image (exemple green) : sudo env DOCKER_BUILDKIT=1 DOCKER_API_VERSION="$API" docker build --no-cache --network host \ --build-arg PUBLIC_GITEA_BASE="$PUBLIC_GITEA_BASE" \ --build-arg PUBLIC_GITEA_OWNER="$PUBLIC_GITEA_OWNER" \ --build-arg PUBLIC_GITEA_REPO="$PUBLIC_GITEA_REPO" \ -t archicratie-web:green \ -f Dockerfile . # Recreate conteneur (important) : sudo docker compose up -d --force-recreate --no-build web_green # Smoke local : /volume2/docker/archicratie-web/ops/smoke.sh 8082 # Sanity check (fichiers clés) : curl -fsSI http://127.0.0.1:8082/ | head -n 20 curl -fsSI http://127.0.0.1:8082/favicon.ico | head -n 20 curl -fsSI http://127.0.0.1:8082/favicon.svg | head -n 20 # Contrôle “Proposer” (validation fonctionnelle) Ouvrir une page chapitre sur le domaine public (ou sur le slot direct si tu testes en local) Clic Proposer → choix 1 → choix 2 Attendus : un seul onglet URL sur .../Archicratia/archicratie-edition/issues/new?... formulaire visible (si loggé sur Gitea) issue créée et CI/runner OK (si configuré) ### 7.3 Bascule DSM Dans DSM Reverse Proxy : destination 8081 ↔ 8082 (BLUE ↔ GREEN) ### 7.4 Rollback (immédiat) repointer DSM sur l’ancien port (1 clic) analyser ensuite le slot inactif ## 8) Favicon (et faux positifs navigateur) ### 8.1 Symptom: Firefox affiche un 504 sur /favicon.ico Cause fréquemment observée : cache navigateur (Firefox). Diagnose : curl -kI https://.../favicon.ico renvoie 200 mais la console navigateur montre encore une erreur Fix : désactiver le cache dans l’onglet Réseau, puis reload ou vider le cache site ### 8.2 Permissions fichiers (si 403) Si /favicon.svg renvoie 403 : vérifier droits dans l’image nginx standard : fichiers 644, répertoires 755 (validé via RUN find ... chmod) ## 9) Exploitation : log driver “db” et erreur “database is locked” # Erreur observée : failed to initialize logging driver : database is locked # Contexte validé : docker info → Logging Driver: db # Remède validé : redémarrer Container Manager (centre de paquets DSM) # vérifier l’espace disque (df -h) et /tmp Commandes : sudo docker info 2>/dev/null | egrep -i 'Logging Driver|Docker Root Dir|Server Version' || true df -h df -i ## 10) Références Pour l’opérationnel minute par minute + tableau de bord : OPS_COCKPIT.md Pour la synchro Mac/Gitea/NAS : OPS-SYNC-TRIPLE-SOURCE.md Pour le workflow branches/PR/tags : WORKFLOW-GIT.md Pour l’ENV : CONFIG-ENV.md Pour les pannes connues : TROUBLESHOOTING.md ## Depuis quelle machine tu fais ça ? - **Édition des docs** : **Mac Studio** (éditeur confortable, git propre) - **Commit/push** : **Mac Studio** (idéal), NAS seulement en “urgence” - **Déploiement** : **NAS** (évidemment) - **Gitea docker** : juste l’UI/Actions, pas nécessaire pour écrire les fichiers. --- ## Et maintenant (ordre propre) 1) Sur Mac : crée/complète ce doc (ci-dessus) + les autres docs. 2) Commit “docs: ops runbooks (2026-02-01)” sur `main`. 3) Push → CI verte. 4) Sur NAS : `reset --hard origin/main` (via alpine/git si besoin). 5) Rebuild/deploy **uniquement si** tu as touché Dockerfile/nginx/src/public (pas si docs only).