configurer-ci-runner-remote.md 11205 octets

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 :

  1. Vérifie la connectivité SSH vers le runner
  2. Installe Docker (curl https://get.docker.com | sh) s'il est absent
  3. Installe Dagger CLI (curl https://dl.dagger.io/dagger/install.sh | sh) s'il est absent
  4. Crée le répertoire de travail distant (CI_REMOTE_PATH)
  5. Synchronise le module deployment/ci-engine/ (mode CI Easy) via rsync -az --delete
  6. Smoke test : affiche docker --version et dagger version

Le script est idempotent : rejoue sans dommage, skip ce qui existe déjà.


2. Quand l'utiliser

ScénarioBesoin 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 runnerOUI — le runner est provisionné une fois, chaque instance pointe dessus
CI dans Kubernetes / Nomad / runner managé cloudNon — 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)

OutilRôle
bash ≥ 4Interpréteur
ssh, rsyncTransport et synchro
ssh-agent chargé ou CI_REMOTE_SSH_KEY définiAuth SSH sans mot de passe interactif (BatchMode=yes)
Fichier .env avec les variables CI_REMOTE_*Config (voir section 5)

Sur le runner distant

Pré-requisPourquoi
OS Linux récent (Debian 12+, Ubuntu 22.04+)Docker install script compatible
User avec sudo passwordless ou droits dockerget.docker.com fait sudo en interne
Clé SSH publique du user local dans ~/.ssh/authorized_keysAuth SSH non-interactive
Réseau sortant autorisé vers get.docker.com et dl.dagger.ioInstallation des binaires
Au minimum ~5 Go libres dans CI_REMOTE_PATHImages 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

VariableObligatoireDéfautDescription
CI_REMOTE_HOSTOUIHostname ou IP du runner (ex: ci-runner.internal)
CI_REMOTE_USERnon$(whoami) (user courant)Compte SSH sur le runner
CI_REMOTE_SSH_PORTnon22Port SSH du runner
CI_REMOTE_PATHnon/opt/gitrust-ciRépertoire de travail distant (créé par le script)
CI_REMOTE_SSH_KEYnon— (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)

CI_REMOTE_HOST=localhost
# Les autres CI_REMOTE_* sont ignorés

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)

cd /chemin/vers/gitrust

# .env a la racine (défaut) :
./deployment/setup-remote-ci.sh

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 :

# .gitrust-ci.yml
version: 1
pipeline:
  - name: smoke
    image: alpine:3
    run: echo "CI runner OK"

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ômeCause probableFix
ERREUR: fichier .env introuvable.env absent ou chemin incorrectcp .env.example .env && $EDITOR .env ou passer le chemin : ./setup-remote-ci.sh /path/to/.env
ERREUR: CI_REMOTE_HOST non définiVariable commentée ou absenteDécommenter CI_REMOTE_HOST=... dans le .env
ERREUR: impossible de se connecterSSH bloqué, mauvais user, clé non autoriséeTester 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éessh-add ~/.ssh/ci_runner_ed25519 ou définir CI_REMOTE_SSH_KEY=/path/to/key
sudo: a password is required pendant l'install DockerUser sans NOPASSWD sudoAjouter le user au sudoers : ci-runner ALL=(ALL) NOPASSWD:ALL (runner uniquement)
curl: (7) Failed to connect to get.docker.comRéseau sortant du runner bloquéWhitelist get.docker.com et dl.dagger.io, ou pré-installer Docker + Dagger manuellement
ATTENTION: ... ci-engine introuvableLancé hors du repo gitrustcd dans la racine du projet avant de lancer
Pipeline reste queued indéfinimentWorker CI ne trouve pas le runnerVé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/binecho '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 pull est nécessaire).
  • Limiter sudo NOPASSWD au strict minimum sur le runner (idéalement : juste pour les commandes docker et apt).
  • Rotation régulière de la clé SSH CI_REMOTE_SSH_KEY. La révoquer dans ~/.ssh/authorized_keys côté runner en cas de suspicion.
  • Le runner ne doit pas pouvoir se connecter en SSH à la machine gitrust (unidirectionnel).