From 0d79d1aa78e19359f711cf01f53b5186c1660661 Mon Sep 17 00:00:00 2001 From: Archicratia Date: Sun, 1 Feb 2026 13:31:10 +0100 Subject: [PATCH 1/4] chore(security): ignore env files, backups and macOS artifacts --- .gitignore | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.gitignore b/.gitignore index 926b6d0..dac0b1c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,20 @@ +# --- secrets / env --- +.env +.env.* +!.env.example + +# --- local backups --- +*.bak +*.bak.* +Dockerfile.bak.* +*.swp +*~ node_modules/ dist/ .astro/ /_release_out/ + +# --- macOS --- .DS_Store ._* -- 2.49.1 From 770dad30fbef579e5bb19bc5255fadada4ef269d Mon Sep 17 00:00:00 2001 From: Archicratia Date: Sun, 1 Feb 2026 13:31:27 +0100 Subject: [PATCH 2/4] docs(deploy): update DS220+ production guide (2026-02-01) --- docs/DEPLOY_PROD_SYNOLOGY_DS220.md | 219 +++++++++++++++++++++++++---- 1 file changed, 193 insertions(+), 26 deletions(-) diff --git a/docs/DEPLOY_PROD_SYNOLOGY_DS220.md b/docs/DEPLOY_PROD_SYNOLOGY_DS220.md index 903e768..921168b 100644 --- a/docs/DEPLOY_PROD_SYNOLOGY_DS220.md +++ b/docs/DEPLOY_PROD_SYNOLOGY_DS220.md @@ -1,18 +1,19 @@ # Déploiement production (Synology DS220+ / DSM 7.3) — Astro → Nginx statique -Dernière mise à jour : 2026-01-29 +Dernière mise à jour : 2026-02-01 -Ce document décrit la mise en place stable sur NAS : +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 : -- `/volume2/docker/archicratie-web/current` +Dossier racine “courant” : +- `/volume2/docker/archicratie-web/current` (symlink vers la release active) Contenu attendu : - `Dockerfile` @@ -20,6 +21,10 @@ Contenu attendu : - `nginx.conf` - `.env` - le code du site (package.json, src/, scripts/, etc.) +- `ops/` (scripts de smoke, etc.) + +Releases : +- `/volume2/docker/archicratie-web/releases//app` --- @@ -28,6 +33,7 @@ Contenu attendu : - 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) --- @@ -42,12 +48,12 @@ Les ports 8081/8082 : --- -## 4) Variables Gitea (Proposer) +## 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_OWNER` (**casse sensible**) - `PUBLIC_GITEA_REPO` Exemple dans `.env` : @@ -55,49 +61,210 @@ 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 + ## 5) Reverse Proxy DSM (le point clé) -DSM 7.3 : +### DSM 7.3 : Panneau de configuration → Portail des applications → Proxy inversé -# Règle pour le site : +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 : +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) +### 6.1 Build réseau (DNS/apt/npm) : mode robuste -Sur DSM, il arrive que apt-get ou des résolutions DNS échouent pendant docker build. -Solution : build avec réseau host (déjà prévu dans compose) : +Sur DSM, il arrive que apt-get/npm aient des soucis réseau pendant docker build. +Mesures robustes validées : -build: network: host +build en --network host -Et activer BuildKit : -export DOCKER_BUILDKIT=1 -export COMPOSE_DOCKER_CLI_BUILD=1 +apt-get avec retries + ForceIPv4 -### 6.2 Artefacts Mac (PaxHeader / ._ / DS_Store) +Exemple (dans Dockerfile) : -Si tu transfères une archive depuis macOS, tu peux embarquer des dossiers/fichiers parasites. -Conséquence possible : Astro “voit” un faux contenu (ex: PaxHeader/...mdx) → erreurs de schema. +apt-get -o Acquire::Retries=5 -o Acquire::ForceIPv4=true ... -Remède : .dockerignore robuste (voir anchors.md section “Artefacts Mac”). +### 6.2 BuildKit / buildx / API Docker (DSM) -## 7) Cycle blue/green (résumé) +Certains environnements DSM peuvent : -Tu rebuild le slot inactif (ex: GREEN) +exiger BuildKit pour --network=host au build -Tu valides en local (curl/smoke/health) +avoir des incompatibilités d’API (client/daemon) -Tu bascules DSM vers ce port +Standard “chez nous” : -Rollback immédiat : tu repasses DSM sur l’autre port +activer BuildKit au build -Pour l’opérationnel minute par minute, voir OPS_COCKPIT.md. +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). -- 2.49.1 From ccaa8029fbab4d3df7b5001f24889488cd9d37e2 Mon Sep 17 00:00:00 2001 From: Archicratia Date: Sun, 1 Feb 2026 13:31:43 +0100 Subject: [PATCH 3/4] docs(ops): add reference + env config + git workflow --- docs/CONFIG-ENV.md | 68 +++++++++++++++++++++++++++++++++++++++++ docs/OPS-REFERENCE.md | 30 ++++++++++++++++++ docs/WORKFLOW-GIT.md | 71 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 docs/CONFIG-ENV.md create mode 100644 docs/OPS-REFERENCE.md create mode 100644 docs/WORKFLOW-GIT.md diff --git a/docs/CONFIG-ENV.md b/docs/CONFIG-ENV.md new file mode 100644 index 0000000..f68018d --- /dev/null +++ b/docs/CONFIG-ENV.md @@ -0,0 +1,68 @@ +# `docs/CONFIG-ENV.md` + +```md +# CONFIG-ENV — variables, priorités, injection build + +## 0) Ce que la prod doit garantir +Le bouton “Proposer” doit ouvrir : +- `PUBLIC_GITEA_BASE` (domaine Gitea) +- `PUBLIC_GITEA_OWNER=Archicratia` +- `PUBLIC_GITEA_REPO=archicratie-edition` + +Si un seul de ces 3 paramètres est faux → on obtient : +- 404 / redirect login inattendu +- ou un repo/owner incorrect + +## 1) Variables utilisées (publique, côté build Astro) + +- `PUBLIC_GITEA_BASE` +- `PUBLIC_GITEA_OWNER` +- `PUBLIC_GITEA_REPO` + +Elles sont consommées via `import.meta.env.PUBLIC_*` dans `EditionLayout.astro`. + +## 2) Où elles vivent (en pratique) +Sur NAS, vous avez vu des divergences entre : +- `.env` +- `.env.local` +- `.env.production` + +Règle : +- **prod build docker** doit être piloté par **`.env`** (ou `.env.production` si vous standardisez ainsi), +- mais on évite que `.env.local` “corrige en douce” un `.env` faux. + +## 3) Vérification rapide (NAS) +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 + +## 4) Injection Docker (ce qui doit être vrai) + +Le build passe bien les build-args : + +--build-arg PUBLIC_GITEA_BASE=... + +--build-arg PUBLIC_GITEA_OWNER=... + +--build-arg PUBLIC_GITEA_REPO=... + +et le Dockerfile expose via ENV pour Astro build. + +## 5) Contrôle “résultat dans le HTML” + +Après build, vérifier que la page contient le bon chemin /issues/new vers le bon owner/repo : + +curl -fsS http://127.0.0.1:8082/archicratie/archicrat-ia/chapitre-4/ > /tmp/page.html +grep -nE 'issues/new|archicratie-edition|Archicratia' /tmp/page.html | head -n 40 + +## 6) Secrets (à ne pas committer) + +GITEA_TOKEN : jamais dans le repo. + +Le token peut être utilisé ponctuellement pour push non-interactif, mais doit rester dans l’environnement local/CI. + +## 7) Docker BuildKit / API (si besoin) + +Si BuildKit/buildx est instable sur la machine, vous avez déjà un protocole “fonctionnel”. +Ne documenter ici que le “standard validé” (voir DEPLOY_PROD). \ No newline at end of file diff --git a/docs/OPS-REFERENCE.md b/docs/OPS-REFERENCE.md new file mode 100644 index 0000000..274d7b9 --- /dev/null +++ b/docs/OPS-REFERENCE.md @@ -0,0 +1,30 @@ +# OPS-REFERENCE — Archicratie Édition + +Document “pivot” : liens, invariants, conventions, commandes réflexes. + +## 0) Invariants (à ne pas casser) + +- **Source de vérité Git** : `origin/main` sur :contentReference[oaicite:0]{index=0}. +- **Prod** : conteneur `archicratie-web-*` (nginx) derrière reverse proxy DSM. +- **Config “Proposer”** : dépend de `PUBLIC_GITEA_BASE`, `PUBLIC_GITEA_OWNER`, `PUBLIC_GITEA_REPO` injectés au build. +- **Branches** : `main` = travail ; `master` = legacy/compat (alignée mais protégée). +- **NAS** : shell sans `git` → usage standard : `alpine/git` en conteneur. + +## 1) Repères (chemins & objets) + +### NAS (DS220+) +- Checkout/release courant : `/volume2/docker/archicratie-web/current` (symlink vers releases/*/app) +- Releases : `/volume2/docker/archicratie-web/releases//app` +- Conteneur green (exemple) : `archicratie-web-green` → `127.0.0.1:8082->80` +- Conteneur blue (exemple) : `archicratie-web-blue` → `127.0.0.1:8081->80` +- Smoke : `/volume2/docker/archicratie-web/ops/smoke.sh ` + +### Mac Studio +- Repo de travail : `site/` (ou équivalent) +- Git natif : OK (branches, PR, tags, etc.) + +## 2) Commandes réflexes (diagnostic) + +### “Quelle version sert le domaine public ?” +```sh +curl -kI https://archicratie.trans-hands.synology.me/ | egrep -i 'etag:|last-modified:|server:' diff --git a/docs/WORKFLOW-GIT.md b/docs/WORKFLOW-GIT.md new file mode 100644 index 0000000..262da03 --- /dev/null +++ b/docs/WORKFLOW-GIT.md @@ -0,0 +1,71 @@ +# WORKFLOW-GIT — branches, PR, tags (standard “main”) + +## 0) Objectif +- Tout le monde (toi compris) suit un protocole unique. +- Zéro ambigüité entre “ce qui tourne” et “ce qui est versionné”. + +## 1) Branches : politique + +### main (branche de travail) +- Branche par défaut du repo. +- Tout changement passe idéalement par PR (même si tu es seul). + +### master (legacy/compat) +- Doit rester alignée sur main (si vous gardez master). +- Protégée contre push accidentel (pas de force-push, pas de push direct). +- N’est **pas** un axe de travail. + +### branches de feature +Conventions recommandées : +- `fix/` : correctif +- `feat/` : nouvelle fonction +- `ops/` : infra, déploiement, scripts, docs ops + +## 2) PR (même si tu es seul) +- Créer une PR → vérifier CI (Actions) → merge. +- Règle : “Prevent merge if checks fail” activée (bonne pratique). +- Approvals : 0 (si tu es seul). + +## 3) Tags +- Tags d’archives : `archive-master-` (déjà fait). +- Snapshots prod : `prod-snapshot-` si besoin. + +## 4) Commandes standard (Mac) + +### Se mettre parfaitement à jour +en sh : +git checkout main +git fetch origin --prune --tags +git reset --hard origin/main +git clean -fd # optionnel : supprime untracked + +### Publier un changement +git checkout -b fix/ +# edits... +git add -A +git commit -m "fix: " +git push -u origin HEAD +# PR via UI, merge + +## 5) Remote case-sensitive (piège déjà rencontré) + +Le repo peut exister avec Owner en casse différente (ex: Archicratia vs archicratia). +Standard : remote doit être : + +https://.../Archicratia/archicratie-edition.git + +Vérifier : +git remote -v + +## 6) NAS : pas de git natif + +Sur NAS, on n’installe pas forcément git dans le shell. +Standard : utiliser alpine/git en conteneur (cf. OPS-SYNC-TRIPLE-SOURCE). + +## 7) Interdits (pour éviter l’enfer) + +Éditer des fichiers du repo via FileStation “pour aller vite” (sauf hotfix d’urgence, puis backport immédiat Git). + +Pousser sur master (sauf opération contrôlée d’alignement). + +Force-push sur main. \ No newline at end of file -- 2.49.1 From 2f296f4fe40a7e187a26db7268be8970d7efa49e Mon Sep 17 00:00:00 2001 From: Archicratia Date: Sun, 1 Feb 2026 13:31:57 +0100 Subject: [PATCH 4/4] docs(runbook): add archicratie-web operations runbook --- docs/OPS-RUNBOOK-ARCHICRATIE-WEB.md | 69 +++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 docs/OPS-RUNBOOK-ARCHICRATIE-WEB.md diff --git a/docs/OPS-RUNBOOK-ARCHICRATIE-WEB.md b/docs/OPS-RUNBOOK-ARCHICRATIE-WEB.md new file mode 100644 index 0000000..0fb2808 --- /dev/null +++ b/docs/OPS-RUNBOOK-ARCHICRATIE-WEB.md @@ -0,0 +1,69 @@ +# OPS Runbook — Archicratie Web (NAS Synology DS220 + Gitea) + +## 0. Objectif +Ce document décrit la procédure **exacte** pour : +- maintenir un état cohérent entre **Local (Mac Studio)**, **Gitea**, **NAS (prod)** ; +- déployer proprement une release Docker (build, smoke, bascule) ; +- éviter les régressions (branches protégées, CI bloquante, rollback). + +## 1. Invariants (à ne jamais violer) +1) **La branche `main` sur Gitea = vérité canonique.** +2) La prod NAS doit être **rebuild** depuis `main` (pas de modifications “à la main” non versionnées). +3) Les variables `PUBLIC_GITEA_*` doivent pointer vers **le bon owner/repo** (sinon 404 / login loop). +4) En solo : PR requise OK, mais **0 approval** (sinon blocage). CI doit rester bloquante. +5) Interdiction : token/secret commité dans le repo. + +## 2. Topologie (NAS) +- Arborescence : + - `/volume2/docker/archicratie-web/releases//app` + - `/volume2/docker/archicratie-web/current` (symlink vers release active) +- Services : + - `web_green` → port local typique `127.0.0.1:8082` (smoke) + - (optionnel) `web_blue` → `127.0.0.1:8081` (ancienne) +- Script : + - `/volume2/docker/archicratie-web/ops/smoke.sh ` + +## 3. Standard Git (Gitea) +### 3.1 Branches +- `main` : branche de travail et de déploiement (par défaut) +- `master` : branche legacy (archivée / conservée pour compat si nécessaire) +- Stratégie : `master` est soit supprimée, soit alignée sur `main`, mais **pas** utilisée comme axe actif. + +### 3.2 Protection branches (solo recommandé) +- `main` : + - ✅ Exiger PR (Require pull request) + - ✅ 0 approval (solo) + - ✅ Bloquer merge si CI KO (Prevent merge if checks fail) + - ✅ Désactiver force-push + - (optionnel) désactiver push direct (selon UI Gitea) +- `master` : + - ✅ Interdire push direct + - ✅ Désactiver force-push + - ✅ Mention “legacy” (si UI le permet) + +## 4. Variables d’environnement (cause n°1 des 404) +### 4.1 Variables publiques injectées au build +- `PUBLIC_GITEA_BASE=https://gitea.archicratie.trans-hands.synology.me` +- `PUBLIC_GITEA_OWNER=Archicratia` +- `PUBLIC_GITEA_REPO=archicratie-edition` + +### 4.2 Règle d’or +- Le site génère des liens `...///issues/new?...` +- Si OWNER/REPO est faux (ex: `archicratia/archicratie-web`) : + - `/issues` peut marcher + - MAIS `/issues/new` finit en 404 / redirect login / droits + - => corriger `.env` et rebuild + +## 5. Déploiement NAS (procédure protocolaire) +### 5.1 Pré-check +Sur NAS : +- Vérifier qu’on est bien dans `/volume2/docker/archicratie-web/current` +- Charger `.env` (pour build args) + +Commandes : +```sh +cd /volume2/docker/archicratie-web/current || exit 1 +set -a +. ./.env +set +a +grep -nE '^PUBLIC_GITEA_(BASE|OWNER|REPO)=' .env -- 2.49.1