CaddyBinaries
Construction et publication automatiques d'un binaire Caddy personnalisé à l'aide de Gitea Actions.
Le workflow :
- vérifie chaque jour la dernière version stable de Caddy ;
- vérifie si cette version existe déjà dans les releases du dépôt Gitea ;
- compile Caddy avec les modules indiqués dans
modules.txt; - vérifie le binaire généré ;
- crée une release Gitea ;
- publie l'archive et son checksum SHA-256.
Modules inclus
Les modules sont configurés dans modules.txt :
github.com/relvacode/caddy-oidcgithub.com/porech/caddy-maxmind-geolocationgithub.com/mholt/caddy-l4github.com/caddy-dns/cloudflare
Installation du runner Gitea
Cette documentation correspond à l'installation suivante :
LXC Debian 13 dédié
├── Docker Engine
├── Node.js
├── Gitea Runner 2.2.0
└── runner global : gitea-builder-01
└── label : docker-builder:host
Le runner est exécuté directement sur l'hôte du LXC et en tant que root. Cette configuration est simple pour construire des images et lancer des conteneurs Docker, mais elle doit être réservée à des dépôts de confiance.
1. Préparer le LXC
Configuration conseillée :
| Ressource | Valeur conseillée |
|---|---|
| Distribution | Debian 13 |
| Type | LXC non privilégié |
| CPU | 4 vCPU |
| RAM | 4 à 6 Go |
| Disque | 60 à 80 Go |
| Swap | 1 Go |
Sur l'hôte Proxmox, activer les fonctionnalités nécessaires à Docker :
pct set <CTID> -features nesting=1,keyctl=1
pct restart <CTID>
Remplacer <CTID> par l'identifiant du conteneur LXC.
2. Installer les dépendances
Dans le LXC, en tant que root :
apt update && apt install -y \
ca-certificates \
curl \
git \
jq \
nodejs \
bash \
tar \
gzip
Node.js est requis pour les actions JavaScript telles que actions/checkout@v4.
Vérification :
node --version
git --version
curl --version
jq --version
3. Installer Docker
Installation rapide :
curl -fsSL https://get.docker.com | sh
Vérification :
systemctl enable --now docker
docker version
docker run --rm hello-world
docker buildx version
Le script
get.docker.comest pratique pour un LXC dédié de homelab. Pour un environnement de production administré strictement, utiliser de préférence le dépôt APT officiel de Docker.
4. Installer Gitea Runner
La version utilisée dans cette documentation est 2.2.0 pour Linux AMD64.
cd /tmp
RUNNER_VERSION="2.2.0"
RUNNER_FILE="gitea-runner-${RUNNER_VERSION}-linux-amd64"
RUNNER_URL="https://dl.gitea.com/gitea-runner/${RUNNER_VERSION}"
curl -fLO "${RUNNER_URL}/${RUNNER_FILE}"
curl -fLO "${RUNNER_URL}/${RUNNER_FILE}.sha256"
sha256sum -c "${RUNNER_FILE}.sha256"
install -m 0755 "${RUNNER_FILE}" /usr/local/bin/act_runner
Vérification :
/usr/local/bin/act_runner --version
Pour un LXC ARM64, remplacer linux-amd64 par linux-arm64 dans RUNNER_FILE.
5. Créer les répertoires
mkdir -p /opt/act_runner
cd /opt/act_runner
Générer la configuration :
/usr/local/bin/act_runner generate-config > /opt/act_runner/config.yaml
chmod 600 /opt/act_runner/config.yaml
6. Configurer les labels
Éditer le fichier :
nano /opt/act_runner/config.yaml
Dans la section runner, configurer les labels suivants :
runner:
labels:
- "docker-builder:host"
- "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
- "ubuntu-24.04:docker://docker.gitea.com/runner-images:ubuntu-24.04"
- "ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04"
Le label utilisé par ce dépôt est :
docker-builder:host
Dans un workflow, il est appelé sans le suffixe :host :
runs-on: docker-builder
Le suffixe :host indique que les commandes sont exécutées directement dans le LXC, au lieu d'être placées dans un conteneur de job isolé.
7. Récupérer le token d'enregistrement
Pour créer un runner global :
Administration Gitea
→ Actions
→ Runners
→ Create new Runner
Copier le token affiché. Un token de runner global permet à ce runner de prendre les jobs de tous les dépôts autorisés sur l'instance.
Pour limiter son accès, il est également possible de créer le token depuis les paramètres d'une organisation ou d'un dépôt précis.
8. Enregistrer le runner
Depuis /opt/act_runner :
cd /opt/act_runner
/usr/local/bin/act_runner \
--config /opt/act_runner/config.yaml \
register \
--no-interactive \
--instance "https://git.jst.ovh" \
--token "COLLER_LE_TOKEN_ICI" \
--name "gitea-builder-01" \
--labels "docker-builder:host,ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest,ubuntu-24.04:docker://docker.gitea.com/runner-images:ubuntu-24.04,ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04"
L'enregistrement crée le fichier suivant :
/opt/act_runner/.runner
Ce fichier contient l'identité du runner. Ne pas le modifier manuellement.
Vérifier sa présence :
ls -la /opt/act_runner/.runner
9. Tester manuellement le runner
Avant de créer le service systemd :
cd /opt/act_runner
/usr/local/bin/act_runner daemon --config /opt/act_runner/config.yaml
Dans l'interface Gitea, le runner doit apparaître avec :
Nom : gitea-builder-01
État : Idle
Type : Global
Labels : docker-builder, ubuntu-latest, ubuntu-24.04, ubuntu-22.04
Arrêter le test avec Ctrl+C.
10. Créer le service systemd
Créer le service :
cat > /etc/systemd/system/act_runner.service <<'EOF_SYSTEMD'
[Unit]
Description=Gitea Actions Runner
Documentation=https://docs.gitea.com/usage/actions/runner
Wants=network-online.target
After=network-online.target docker.service
Requires=docker.service
[Service]
Type=simple
User=root
Group=root
Environment="HOME=/root"
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
WorkingDirectory=/opt/act_runner
ExecStart=/usr/local/bin/act_runner daemon --config /opt/act_runner/config.yaml
Restart=always
RestartSec=5
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target
EOF_SYSTEMD
Activer et démarrer le service :
systemctl daemon-reload
systemctl enable --now act_runner
Vérification :
systemctl status act_runner --no-pager -l
journalctl -u act_runner -n 100 --no-pager
Suivre les logs en direct :
journalctl -u act_runner -f
11. Activer les Actions dans le dépôt
Dans le dépôt Gitea :
Paramètres du dépôt
→ Unités du dépôt
→ Activer Repository Actions
Le workflow du projet est stocké dans :
.gitea/workflows/build-caddy.yml
Il cible ce runner avec :
jobs:
build-caddy:
runs-on: docker-builder
12. Autoriser la création des releases
Le workflow utilise le token intégré à chaque job :
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
Il n'est pas nécessaire de créer manuellement un secret portant ce nom. Gitea fournit automatiquement GITEA_TOKEN à chaque job.
Le workflow demande l'autorisation d'écrire dans les releases :
permissions:
contents: write
Vérifier également dans Gitea :
Dépôt
→ Paramètres
→ Actions
→ Général
Les permissions maximales du token doivent autoriser l'écriture sur le contenu ou les releases. Une permission maximale en lecture seule provoquera une erreur HTTP 403 lors de la création de la release.
13. Tester le runner avec un workflow minimal
Créer temporairement .gitea/workflows/test-runner.yml :
name: Test runner
on:
workflow_dispatch:
jobs:
test:
runs-on: docker-builder
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Vérifications
run: |
hostname
id
node --version
git --version
docker version
docker buildx version
Lancer ensuite le workflow depuis l'onglet Actions de Gitea.
Fonctionnement du build Caddy
Déclencheurs
Le workflow principal est lancé :
- chaque jour à
06:00 UTC; - manuellement avec
workflow_dispatch; - après une modification de
build.sh,modules.txtou du workflow sur la branchemain.
Configuration :
on:
schedule:
- cron: "0 6 * * *"
workflow_dispatch:
push:
branches:
- main
Compilation
Le runner lance l'image officielle de construction Caddy :
caddy:2-builder-alpine
Le dépôt est monté dans le conteneur et build.sh utilise xcaddy pour compiler le binaire avec les modules présents dans modules.txt.
Fichiers publiés
Chaque release contient :
caddy-vX.Y.Z-linux-amd64.tar.gz
caddy-vX.Y.Z-linux-amd64.tar.gz.sha256
Le binaire est également vérifié avec :
./dist/caddy version
./dist/caddy list-modules
Administration courante
État du runner
systemctl status act_runner --no-pager -l
Logs récents
journalctl -u act_runner -n 100 --no-pager
Redémarrer le runner
systemctl restart act_runner
Vérifier les composants
/usr/local/bin/act_runner --version
node --version
docker version
docker buildx version
Nettoyer le cache Docker
Afficher l'espace utilisé :
docker system df
Nettoyer les images et caches inutilisés depuis plus de sept jours :
docker image prune -af --filter "until=168h"
docker builder prune -af --filter "until=168h"
Mettre à jour le runner
Exemple pour mettre à jour vers une nouvelle version :
NEW_VERSION="2.2.0"
RUNNER_FILE="gitea-runner-${NEW_VERSION}-linux-amd64"
RUNNER_URL="https://dl.gitea.com/gitea-runner/${NEW_VERSION}"
cd /tmp
curl -fLO "${RUNNER_URL}/${RUNNER_FILE}"
curl -fLO "${RUNNER_URL}/${RUNNER_FILE}.sha256"
sha256sum -c "${RUNNER_FILE}.sha256"
systemctl stop act_runner
install -m 0755 "${RUNNER_FILE}" /usr/local/bin/act_runner
systemctl start act_runner
/usr/local/bin/act_runner --version
systemctl status act_runner --no-pager
Adapter NEW_VERSION à la version souhaitée.
Dépannage
No matching online runner with label: docker-builder
Vérifier que le runner est en ligne :
systemctl status act_runner
Vérifier que le label est présent dans /opt/act_runner/config.yaml :
- "docker-builder:host"
Puis redémarrer :
systemctl restart act_runner
Le workflow doit contenir :
runs-on: docker-builder
Gitea sélectionne les runners selon leurs labels, et non selon leur nom visible gitea-builder-01.
Cannot find: node in PATH
Installer Node.js et redémarrer le runner :
apt update && apt install -y nodejs
node --version
systemctl restart act_runner
Cette erreur apparaît notamment avec actions/checkout@v4, qui est une action JavaScript.
Le runner reste hors ligne
journalctl -u act_runner -n 100 --no-pager
Vérifier :
- que
https://git.jst.ovhest accessible depuis le LXC ; - que
/opt/act_runner/.runnerexiste ; - que le service utilise le bon répertoire de travail ;
- que le token utilisé lors de l'enregistrement correspond à la bonne instance Gitea.
Test manuel :
systemctl stop act_runner
cd /opt/act_runner
/usr/local/bin/act_runner daemon --config /opt/act_runner/config.yaml
Réenregistrer le runner
À utiliser uniquement si le fichier d'enregistrement est invalide ou si le runner a été supprimé de Gitea :
systemctl stop act_runner
rm -f /opt/act_runner/.runner
Récupérer un nouveau token dans Gitea, puis recommencer l'étape d'enregistrement.
Docker ne fonctionne pas dans le workflow
Tester directement dans le LXC :
docker version
docker run --rm hello-world
Comme le runner fonctionne en root et avec le label :host, il doit pouvoir accéder directement au démon Docker du LXC.
Erreur HTTP 403 lors de la création d'une release
Vérifier :
- la présence de
permissions: contents: writedans le workflow ; - les permissions maximales du token dans Paramètres → Actions → Général ;
- que l'exécution ne provient pas d'une pull request non fiable ou d'un fork, pour lesquels les permissions sont restreintes.
Sécurité
Le runner fonctionne avec deux éléments très privilégiés :
root + docker-builder:host
Un workflow peut donc exécuter n'importe quelle commande root dans le LXC et contrôler son démon Docker.
Mesures recommandées :
- dédier entièrement le LXC au runner ;
- ne pas y héberger d'autres services ;
- ne pas y stocker de clés SSH de production ;
- n'autoriser que des utilisateurs de confiance à modifier les workflows ;
- ne pas utiliser ce runner pour des dépôts publics acceptant des pull requests non fiables ;
- sauvegarder le dépôt, mais pas nécessairement les caches Docker ;
- maintenir Docker, Debian et Gitea Runner à jour.