Configurer le runner CI distant¶
Guide d'usage du script qui provisionne une machine distante pour exécuter les pipelines CI/CD de gitrust via SSH + rsync + Dagger.
1. Rôle du script¶
deployment/setup-remote-ci.sh (disponible dans le dépôt source gitrust) prépare un serveur de build distant utilisé par le worker CI de gitrust. Il automatise 6 étapes :
- Vérifie la connectivité SSH vers le runner
- Installe Docker (
curl https://get.docker.com | sh) s'il est absent - Installe Dagger CLI (
curl https://dl.dagger.io/dagger/install.sh | sh) s'il est absent - Crée le répertoire de travail distant (
CI_REMOTE_PATH) - Synchronise le module
deployment/ci-engine/(mode CI Easy) viarsync -az --delete - Smoke test : affiche
docker --versionetdagger version
Le script est idempotent : rejoue sans dommage, skip ce qui existe déjà.
2. Quand l'utiliser¶
| Scénario | Besoin de setup-remote-ci.sh ? |
|---|---|
Dev local, CI sur la même machine que gitrust (CI_REMOTE_HOST=localhost) |
Non — Docker et Dagger déjà installés localement, le ci-engine/ est lu depuis deployment/ci-engine/ directement |
| Prod on-premise, un seul serveur (gitrust + CI colocalisés) | Non — idem, un simple curl get.docker.com \| sh suffit sur le serveur gitrust |
| Prod avec runner CI dédié (machine séparée) | OUI — c'est le cas cible de ce script |
| Prod avec plusieurs instances gitrust partageant un runner | OUI — le runner est provisionné une fois, chaque instance pointe dessus |
| CI dans Kubernetes / Nomad / runner managé cloud | Non — ce script est pensé pour une VM Debian/Ubuntu classique |
3. Architecture cible¶
+---------------------+ SSH + rsync +-----------------------+
| Gitrust (web+SSH) |---------------------------| CI Runner (distant) |
| <your-server-ip> | CI_REMOTE_HOST/USER/KEY | <ci-runner-ip> |
| | | |
| Worker CI Tokio | push .gitrust-ci.yml | /opt/gitrust-ci/ |
| (dans gitrust.bin) | + code source checkout | ├── ci-engine/ |
| | | └── workspaces/ |
| | dagger call ... | |
| | | Docker + Dagger CLI |
+---------------------+ +-----------------------+
Le worker CI de gitrust (tâche Tokio dans le binaire principal) ne fait pas tourner Docker localement — il délègue au runner via SSH. Cela permet d'isoler les workloads CPU/RAM gourmands (builds Rust, Node, Docker) du process web de gitrust.
4. Pré-requis¶
Sur la machine d'exécution (là où on lance le script)¶
| Outil | Rôle |
|---|---|
bash ≥ 4 |
Interpréteur |
ssh, rsync |
Transport et synchro |
ssh-agent chargé ou CI_REMOTE_SSH_KEY défini |
Auth SSH sans mot de passe interactif (BatchMode=yes) |
Fichier .env avec les variables CI_REMOTE_* |
Config (voir section 5) |
Sur le runner distant¶
| Pré-requis | Pourquoi |
|---|---|
| OS Linux récent (Debian 12+, Ubuntu 22.04+) | Docker install script compatible |
User avec sudo passwordless ou droits docker |
get.docker.com fait sudo en interne |
Clé SSH publique du user local dans ~/.ssh/authorized_keys |
Auth SSH non-interactive |
Réseau sortant autorisé vers get.docker.com et dl.dagger.io |
Installation des binaires |
Au minimum ~5 Go libres dans CI_REMOTE_PATH |
Images Docker + workspaces |
5. Variables d'environnement attendues (le .env)¶
Le script source un fichier .env dont le chemin est passé en argument, ou par défaut ../.env (relatif au script, donc <racine_projet>/.env).
Tableau des variables¶
| Variable | Obligatoire | Défaut | Description |
|---|---|---|---|
CI_REMOTE_HOST |
OUI | — | Hostname ou IP du runner (ex: ci-runner.internal) |
CI_REMOTE_USER |
non | $(whoami) (user courant) |
Compte SSH sur le runner |
CI_REMOTE_SSH_PORT |
non | 22 |
Port SSH du runner |
CI_REMOTE_PATH |
non | /opt/gitrust-ci |
Répertoire de travail distant (créé par le script) |
CI_REMOTE_SSH_KEY |
non | — (ssh-agent) | Chemin d'une clé privée SSH spécifique |
Ces variables sont les mêmes que celles lues par gitrust au runtime. Centraliser dans .env évite les divergences entre le provisionnement et le runtime.
Exemple minimal de .env (runner dédié)¶
# --- CI runner distant ---
CI_REMOTE_HOST=<ci-runner-ip>
CI_REMOTE_USER=ci-runner
CI_REMOTE_SSH_PORT=22
CI_REMOTE_PATH=/opt/gitrust-ci
CI_REMOTE_SSH_KEY=/home/gitrust/.ssh/ci_runner_ed25519
Exemple .env complet coexistant avec config gitrust¶
DATABASE_URL=postgres://...
JWT_SECRET=...
# ... (voir .env.example pour le reste)
# --- CI/CD (lu par gitrust ET par setup-remote-ci.sh) ---
CI_ENABLED=true
CI_MAX_CONCURRENT=4
CI_REMOTE_HOST=ci-runner.internal
CI_REMOTE_USER=ci-runner
CI_REMOTE_PATH=/opt/gitrust-ci
CI_REMOTE_SSH_KEY=/opt/gitrust/data/ci_runner_key
Cas « runner local » (pas besoin du script)¶
Dans ce cas, installer Docker et Dagger directement sur la machine gitrust, copier deployment/ci-engine/ vers CI_ENGINE_PATH (défaut /opt/gitrust/ci-engine) et passer à la suite. Ne pas exécuter setup-remote-ci.sh avec CI_REMOTE_HOST=localhost.
6. Usage¶
Depuis la racine du projet (par défaut)¶
Avec un .env explicite¶
./deployment/setup-remote-ci.sh /chemin/vers/mon.env
# Utile si vous avez .env.production, .env.staging, etc.
./deployment/setup-remote-ci.sh .env.production
Sortie attendue¶
==> Configuration :
Serveur : ci-runner@<ci-runner-ip>
Port SSH : 22
Chemin : /opt/gitrust-ci
==> [1/6] Vérification de la connectivité SSH...
SSH OK
OK
==> [2/6] Vérification de Docker...
Docker déjà installé
==> [3/6] Vérification de Dagger CLI...
Installation de Dagger CLI...
Dagger installé
==> [4/6] Création du répertoire distant...
/opt/gitrust-ci créé
==> [5/6] Synchronisation du ci-engine...
sending incremental file list
ci-engine/
ci-engine/profiles/
...
ci-engine synchronisé vers /opt/gitrust-ci/ci-engine/
==> [6/6] Smoke test...
Versions distantes :
Docker version 28.0.1, build abcd123
dagger v0.19.2 (linux/amd64)
==> Setup terminé. Le serveur ci-runner@<ci-runner-ip> est prêt pour l'exécution CI.
Pensez à configurer CI_EXECUTION_MODE=remote dans votre .env
7. Ce qui se retrouve sur le runner¶
Après exécution réussie :
/opt/gitrust-ci/ <- CI_REMOTE_PATH
└── ci-engine/ <- synchronisé depuis deployment/ci-engine/
├── README.md
└── profiles/ <- templates par stack (Python, Node, Rust, ...)
Plus, installés globalement :
- /usr/bin/docker (ou équivalent) + socket /var/run/docker.sock
- /usr/local/bin/dagger
Les workspaces de pipelines (checkouts temporaires) sont créés par le worker CI de gitrust au moment de l'exécution sous CI_WORKSPACE_PATH (défaut /tmp/gitrust-ci) — pas par ce script.
8. Vérifications post-setup¶
Depuis la machine gitrust¶
# Source le .env
set -a; source .env.production; set +a
# 1. SSH direct (doit passer sans prompt)
ssh -p ${CI_REMOTE_SSH_PORT:-22} \
${CI_REMOTE_SSH_KEY:+-i $CI_REMOTE_SSH_KEY} \
$CI_REMOTE_USER@$CI_REMOTE_HOST 'docker info && dagger version'
# 2. Rsync round-trip (lecture/écriture sur CI_REMOTE_PATH)
echo "test" | ssh $CI_REMOTE_USER@$CI_REMOTE_HOST \
"cat > $CI_REMOTE_PATH/.gitrust-test && cat $CI_REMOTE_PATH/.gitrust-test && rm $CI_REMOTE_PATH/.gitrust-test"
# Attendu : "test"
Pipeline de test via gitrust¶
Pousser un dépôt avec un .gitrust-ci.yml minimal :
Puis dans l'UI gitrust : onglet Pipelines → la pipeline doit passer au statut success.
9. Mise à jour après modification du ci-engine/¶
Le ci-engine/ synchronisé n'est pas « live-linké » : rejouer le script après modification côté source.
# Modifier deployment/ci-engine/profiles/*.py ou similaire
./deployment/setup-remote-ci.sh
# Les étapes 2-3 sont skip (déjà installés), seule l'étape 5 refait le rsync
rsync -az --delete supprime les fichiers côté runner qui n'existent plus localement — garantit la cohérence.
10. Dépannage¶
| Symptôme | Cause probable | Fix |
|---|---|---|
ERREUR: fichier .env introuvable |
.env absent ou chemin incorrect |
cp .env.example .env && $EDITOR .env ou passer le chemin : ./setup-remote-ci.sh /path/to/.env |
ERREUR: CI_REMOTE_HOST non défini |
Variable commentée ou absente | Décommenter CI_REMOTE_HOST=... dans le .env |
ERREUR: impossible de se connecter |
SSH bloqué, mauvais user, clé non autorisée | Tester manuellement : ssh -v -p X user@host ; vérifier ~/.ssh/authorized_keys sur le runner |
Permission denied (publickey) |
BatchMode=yes interdit les prompts, clé non chargée |
ssh-add ~/.ssh/ci_runner_ed25519 ou définir CI_REMOTE_SSH_KEY=/path/to/key |
sudo: a password is required pendant l'install Docker |
User sans NOPASSWD sudo |
Ajouter le user au sudoers : ci-runner ALL=(ALL) NOPASSWD:ALL (runner uniquement) |
curl: (7) Failed to connect to get.docker.com |
Réseau sortant du runner bloqué | Whitelist get.docker.com et dl.dagger.io, ou pré-installer Docker + Dagger manuellement |
ATTENTION: ... ci-engine introuvable |
Lancé hors du repo gitrust | cd dans la racine du projet avant de lancer |
Pipeline reste queued indéfiniment |
Worker CI ne trouve pas le runner | Vérifier CI_EXECUTION_MODE=remote dans .env gitrust + logs : journalctl -u gitrust \| grep -i 'ci\|dagger' |
dagger: command not found au smoke test |
$PATH du user SSH ne contient pas /usr/local/bin |
echo 'export PATH=$PATH:/usr/local/bin' >> ~/.bashrc sur le runner, ou CI_DAGGER_BIN=/usr/local/bin/dagger côté gitrust |
11. Sécurité¶
- Le runner CI exécute du code arbitraire venant des dépôts hébergés. Ne jamais le colocaliser avec des secrets sensibles (PG prod, clés de prod).
- Isoler réseau : bloquer l'accès sortant du runner vers le LAN privé (seul l'accès Internet pour
docker pullest nécessaire). - Limiter
sudo NOPASSWDau strict minimum sur le runner (idéalement : juste pour les commandesdockeretapt). - Rotation régulière de la clé SSH
CI_REMOTE_SSH_KEY. La révoquer dans~/.ssh/authorized_keyscôté runner en cas de suspicion. - Le runner ne doit pas pouvoir se connecter en SSH à la machine gitrust (unidirectionnel).