Aller au contenu
Culture DevOps medium
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

Intégrer GARM avec Gitea Actions : runners LXD à la demande

11 min de lecture

GARM est installé et son service tourne. Cette étape connecte GARM à votre instance Gitea : vous allez créer un PAT (Personal Access Token), déclarer un endpoint Gitea dans GARM, configurer un pool LXD, et déclencher votre premier job Actions sur un runner éphémère.

Prérequis : GARM v0.2.0 installé et l’API accessible. Voir Installer GARM.

Étape 1 — Mettre à jour les URLs du contrôleur

Section intitulée « Étape 1 — Mettre à jour les URLs du contrôleur »

Après l’installation, les URLs du contrôleur pointent vers localhost. Gitea (et vos runners) doivent pouvoir les joindre. Mettez à jour avec l’IP réelle de la VM.

Fenêtre de terminal
garm-cli controller update \
--metadata-url "http://192.168.122.52:9997/api/v1/metadata" \
--callback-url "http://192.168.122.52:9997/api/v1/callbacks" \
--webhook-url "http://192.168.122.52:9997/webhooks" \
--agent-url "http://192.168.122.52:9997/agent"
# Vérifier
garm-cli controller show

GARM a besoin d’un token Gitea pour interroger les repos, gérer les runners et répondre aux webhooks. Créez un PAT (Personal Access Token) via l’API Gitea.

Fenêtre de terminal
# Créer le PAT via l'API Gitea
# (adapter l'utilisateur et le mot de passe à votre installation)
curl -X POST \
-u 'giteaadmin:Admin1234!' \
-H 'Content-Type: application/json' \
-d '{
"name": "garm-token",
"scopes": ["write:repository", "write:organization", "read:user"]
}' \
'http://localhost:3000/api/v1/users/giteaadmin/tokens'

La réponse contient le token (champ sha1) — notez-le, il ne sera affiché qu’une fois :

{
"id": 1,
"name": "garm-token",
"sha1": "d86697b5ee780c927a4c25dcee8dd327760a111c",
...
}

Étape 3 — Déclarer l’endpoint Gitea dans GARM

Section intitulée « Étape 3 — Déclarer l’endpoint Gitea dans GARM »

Un endpoint dans GARM représente une instance Gitea (ou GitHub). Il contient l’URL de base et l’URL de l’API.

Fenêtre de terminal
garm-cli gitea endpoint create \
--name "local-gitea" \
--description "Gitea local lab" \
--base-url "http://192.168.122.52:3000" \
--api-base-url "http://192.168.122.52:3000"
# Vérifier
garm-cli gitea endpoint list

Les credentials associent un endpoint à un token d’authentification. Utilisez le PAT créé à l’étape 2.

Fenêtre de terminal
garm-cli gitea credentials add \
--endpoint "local-gitea" \
--auth-type "pat" \
--pat-oauth-token "d86697b5ee780c927a4c25dcee8dd327760a111c" \
--name "gitea-creds" \
--description "PAT garm-token"
# Vérifier
garm-cli gitea credentials list

Pour tester GARM, vous avez besoin d’un repo Gitea avec Gitea Actions activé.

Fenêtre de terminal
# Créer le repo
curl -X POST \
-u 'giteaadmin:Admin1234!' \
-H 'Content-Type: application/json' \
-d '{
"name": "garm-test",
"description": "Repo de test pour GARM runners",
"private": false,
"auto_init": true,
"default_branch": "main"
}' \
'http://localhost:3000/api/v1/user/repos'
Fenêtre de terminal
garm-cli repository add \
--credentials "gitea-creds" \
--owner "giteaadmin" \
--name "garm-test" \
--webhook-secret "garm-webhook-secret-lab2026"

Attendez quelques secondes que le pool manager démarre, puis vérifiez :

Fenêtre de terminal
garm-cli repository list
# → POOL MGR RUNNING doit être "true"

Un pool définit comment les runners seront créés. Il associe un repo, un provider LXD, une image Ubuntu et des limites (max de runners simultanés).

Fenêtre de terminal
# Récupérer l'ID du repo
REPO_ID=$(garm-cli repository list --format json | \
python3 -c "import sys,json; repos=json.load(sys.stdin); \
print([r['id'] for r in repos if r['name']=='garm-test'][0])")
echo "Repo ID: ${REPO_ID}"
# Créer le pool LXD
garm-cli pool add \
--repo "${REPO_ID}" \
--provider-name "lxd_local" \
--image "ubuntu:24.04" \
--flavor "default" \
--os-type "linux" \
--os-arch "amd64" \
--max-runners 3 \
--min-idle-runners 0 \
--tags "ubuntu,lxd" \
--runner-prefix "garm" \
--enabled
# Vérifier
garm-cli pool list --repo "${REPO_ID}"

Gitea doit notifier GARM quand un job Actions est mis en file d’attente. Cette notification s’appelle un webhook workflow_job. L’URL cible est fournie par GARM (Controller Webhook URL).

  1. Récupérer l’URL du webhook contrôleur :

    9997/webhooks/f3737450-c29c-4180-a18b-e2298f8d327f
    garm-cli controller show | grep "Controller Webhook URL"
  2. Créer le webhook sur le repo :

    Fenêtre de terminal
    curl -X POST \
    -u 'giteaadmin:Admin1234!' \
    -H 'Content-Type: application/json' \
    -d '{
    "type": "gitea",
    "config": {
    "url": "http://192.168.122.52:9997/webhooks/f3737450-c29c-4180-a18b-e2298f8d327f",
    "content_type": "json",
    "secret": "garm-webhook-secret-lab2026"
    },
    "events": ["workflow_job"],
    "active": true
    }' \
    'http://localhost:3000/api/v1/repos/giteaadmin/garm-test/hooks'
  3. Vérifier le webhook :

    Fenêtre de terminal
    curl -s \
    -u 'giteaadmin:Admin1234!' \
    'http://localhost:3000/api/v1/repos/giteaadmin/garm-test/hooks' | \
    python3 -c "import sys,json; [print(h['id'], h['active'], h['events']) for h in json.load(sys.stdin)]"
    # → 1 True ['workflow_job']

Créez un workflow qui demande un runner avec le label lxd (celui assigné au pool) :

.gitea/workflows/test-garm.yml
name: Test GARM Runner
on: [push]
jobs:
test:
runs-on: ["self-hosted", "lxd"]
steps:
- name: Infos runner
run: |
echo "Hostname: $(hostname)"
echo "Kernel: $(uname -r)"
echo "Distro: $(cat /etc/os-release | grep PRETTY_NAME)"
echo "User: $(whoami)"
- name: Test réseau
run: curl -sf https://gitea.com/api/swagger | head -5

Poussez ce fichier dans votre repo et observez dans une autre fenêtre :

Fenêtre de terminal
# Surveiller les runners créés par GARM
watch garm-cli runner list --pool "$(garm-cli pool list --repo ${REPO_ID} --format json | \
python3 -c 'import sys,json; pools=json.load(sys.stdin); print(pools[0]["id"])')"
# Suivre les logs GARM
sudo journalctl -u garm -f --no-pager
Fenêtre de terminal
# État du contrôleur
garm-cli controller show
# Providers
garm-cli provider list
# Endpoints Gitea
garm-cli gitea endpoint list
# Credentials
garm-cli gitea credentials list
# Repos gérés
garm-cli repository list
# Pools
garm-cli pool list --all
# Runners actifs
garm-cli runner list --all
SymptômeCause probableAction
Pool manager false après ajout repoPAT incorrect ou endpoint mal configuréjournalctl -u garm -n 30
Webhook not receivedMauvaise URL ou secret incorrectVérifier l’URL du Controller Webhook dans garm-cli controller show
Runner créé mais job ne s’assigne pasLabels du pool ne correspondent pas à runs-onPool avec tag lxd, workflow avec runs-on: ["self-hosted", "lxd"]
Container LXD timeoutImage ubuntu:24.04 non en cachePremier lancement long : attendre 2-3 min, augmenter runner-bootstrap-timeout
garm-cli: permission denied sur configConfig créée par rootsudo chown $USER ~/.local/share/garm-cli/config.toml
Token JWT expiréSession expiréegarm-cli profile login -u garmadmin -p "mot-de-passe"
  • GARM v0.2.0 gère les credentials Gitea via garm-cli gitea credentials add.
  • Le webhook workflow_job est l’événement déclencheur — sans lui, GARM ne crée aucun runner.
  • Le secret webhook doit correspondre entre le hook Gitea et garm-cli repository add.
  • Chaque runner est éphémère et associé à un seul job.
  • Les labels du pool (--tags) doivent correspondre aux runs-on du workflow.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn