4.5 KiB
Deploiement continu (CD) — Wakdo
Ce document decrit le deploiement automatique vers la production et la mise en place
a faire une seule fois cote serveur. Il complete scripts/deploy.sh et
.forgejo/workflows/deploy.yml.
Topologie
| Hote | Role |
|---|---|
Thanos (git.acadenice.com) |
Forge : depot Git + Forgejo Actions |
| Stark | Environnement de dev ; heberge le runner Forgejo |
| Vision | Production : la stack Wakdo y tourne, cible du deploiement |
Le runner (sur Stark) n'a pas acces au socket Docker, par choix de securite : un job CI ne peut pas piloter Docker sur son hote. Le deploiement vers Vision se fait donc par SSH — ce qui correspond au schema normal d'un deploiement vers un hote distant.
Flux
merge dev -> main (release, deja passee par la CI sur la PR)
│
▼
Forgejo Actions: workflow Deploy (.forgejo/workflows/deploy.yml)
│ ssh deploy@vision (sans commande : forced command cote Vision)
▼
Vision: scripts/deploy.sh (git ff-only -> VERSION + deploy.log -> compose build/up)
│
▼
GET /api/health renvoie le nouveau SHA ← preuve du deploiement
Ce qui est automatise (dans le depot)
.forgejo/workflows/deploy.yml: sur pushmain, ouvre la session SSH vers Vision.scripts/deploy.sh: recuperemain(fast-forward), ecrit le marqueur de version (src/VERSION) et une ligne dansdeploy.log, reconstruit et recree la stack. Mode non-interactif viaDEPLOY_YES=1.GET /api/healthexposeversion(SHA) etdeployed_at(date), lus depuissrc/VERSION.
Mise en place cote Vision (une fois)
Prerequis : Docker + docker compose, le depot clone (ex. /srv/wakdo).
Le compose et le .env de prod ne sont pas versionnes (propres a l'hote) ; ils se
derivent des modeles fournis dans le depot :
cp docker-compose.prod.yml.example docker-compose.prod.yml
cp .env.prod.example .env # puis renseigner domaines + mots de passe + reseau Traefik
docker compose -f docker-compose.prod.yml up -d --build
Le compose est entierement pilote par le .env : le meme fichier marche sur tout hote.
- Creer un utilisateur dedie au deploiement, membre du groupe
docker:sudo useradd -m -G docker deploy - Lui donner le depot (ou ajuster les droits du clone existant) :
sudo chown -R deploy:deploy /srv/wakdo - Autoriser la cle CI avec une forced command : la cle ne peut lancer que le
deploiement, aucune autre commande. Dans
~deploy/.ssh/authorized_keys:command="cd /srv/wakdo && DEPLOY_YES=1 scripts/deploy.sh main",no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAA...CLE_PUBLIQUE... deploy@wakdo-cideploy.shne lit pas$SSH_ORIGINAL_COMMAND: meme si un appel SSH tentait de passer une autre commande, elle serait ignoree.
Generer la cle et la connaitre cote forge
Sur un poste de confiance :
ssh-keygen -t ed25519 -f wakdo-deploy -C "deploy@wakdo-ci" -N ""
# wakdo-deploy -> cle PRIVEE (secret de la forge, ci-dessous)
# wakdo-deploy.pub -> cle PUBLIQUE (authorized_keys de Vision, etape 3)
ssh-keyscan -t ed25519 <hote-vision> # -> contenu du secret DEPLOY_KNOWN_HOSTS
Secrets et variables a creer sur la forge
Depot -> Settings -> Actions -> Secrets / Variables :
| Type | Nom | Valeur |
|---|---|---|
| Secret | DEPLOY_SSH_KEY |
contenu de la cle privee wakdo-deploy |
| Secret | DEPLOY_KNOWN_HOSTS |
sortie de ssh-keyscan (cle d'hote de Vision) |
| Secret | DEPLOY_HOST |
nom/IP de Vision |
| Variable | DEPLOY_USER |
deploy |
Verification
- Faire une release (
dev -> main). - Suivre le workflow Deploy dans l'interface de la forge (il se declenche au push
sur
main). - Interroger la sonde et lire la version deployee :
Lecurl -s https://<fqdn-admin-prod>/api/health # { ... "version": "<sha>", "deployed_at": "<date>" }versioncorrespond au HEAD demainapres la release — preuve que Vision a ete mise a jour sans intervention manuelle.
Notes de securite
- Cle SSH dediee au seul deploiement, forced command + options
no-*qui retirent shell, tunnels et forwarding. - Cle d'hote epinglee (
DEPLOY_KNOWN_HOSTS,StrictHostKeyChecking=yes) : pas de confiance a la premiere connexion. - Secrets stockes cote forge, hors du depot.
.envetdocker-compose.prod.ymlrestent gitignores. - Le runner n'a pas le socket Docker : un job ne peut pas agir sur Docker localement.