Automatiser la construction d’un site statique Hugo et le déployer sur un serveur personnel, rien de plus simple. Avec un pipeline GitLab et rsync, voici comment y parvenir.
Création d’un utilisateur dédié
La première étape est de créer un utilisateur sur le système. Il sert à recevoir la connexion rsync lancée par GitLab et à écrire les fichiers générés. Ses droits restent limités : il n’est pas administrateur.
Les commandes suivantes se lancent en root. adduser pose quelques questions (nom complet, mot de passe) : un mot de passe vide convient, la connexion se fera par clé.
adduser gitlabci
mkdir -p /var/www/mysite
chown gitlabci:www-data /var/www/mysite
usermod -aG www-data gitlabci
Génération de la clé SSH
Une paire de clés est générée pour l’utilisateur gitlabci. La clé privée sera confiée à GitLab, la clé publique autorise la connexion sur le serveur. Une seule paire suffit : GitLab s’en sert pour le rsync, et le serveur l’accepte dans authorized_keys.
La clé ne doit pas avoir de phrase de passe. Le job n’a pas de terminal pour la saisir.
Passer sur le compte gitlabci avec un shell de login, afin d’être dans son répertoire personnel :
su - gitlabci
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
Deux fichiers sont créés dans ~/.ssh/ :
id_ed25519— à coller dans la variable GitLabSSH_PRIVATE_KEY;id_ed25519.pub— déjà ajoutée à~/.ssh/authorized_keys.
Afficher la clé privée pour la copier. Elle ne doit pas être commitée dans le dépôt.
cat ~/.ssh/id_ed25519
Configuration GitLab
Le build et le déploiement sont décrits dans .gitlab-ci.yml, à la racine du projet. Le pipeline a deux étapes :
- build : Hugo extended produit les pages statiques ;
- deploy : rsync les copie sur le serveur.
Le job build utilise cibuilds/hugo:0.166.0. Cette image contient Hugo extended et bash, dont le runner Docker de GitLab a besoin pour exécuter le script. Le job deploy n’a pas besoin de Hugo : debian:bookworm-slim fournit bash, puis le script installe openssh-client et rsync.
Le pipeline ne s’exécute que sur la branche par défaut du dépôt (main sur un GitLab récent).
stages:
- build
- deploy
build:
stage: build
image: cibuilds/hugo:0.166.0
script:
- hugo version
- hugo -d public_html
artifacts:
paths:
- public_html
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
deploy:
stage: deploy
image: debian:bookworm-slim
before_script:
- apt-get update
- apt-get install -y --no-install-recommends openssh-client rsync
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- cp "$SSH_PRIVATE_KEY" ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
script:
- rsync -hrvz --delete -e 'ssh -p 22 -o StrictHostKeyChecking=accept-new' public_html/ "${SSH_USER_HOST_LOCATION}"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
L’artefact public_html produit par build est disponible dans deploy. rsync copie le contenu de ce dossier. --delete retire du serveur les fichiers qui ne sont plus dans le build. StrictHostKeyChecking=accept-new enregistre la clé d’hôte du serveur à la première connexion, puis refuse un changement silencieux.
Variables du dépôt
Dans le dépôt GitLab : Settings → CI/CD → Variables.
SSH_PRIVATE_KEY — type File. Coller le contenu complet de ~/.ssh/id_ed25519. Avec ce type, GitLab écrit la clé dans un fichier et la variable contient le chemin de ce fichier : le job la copie avec cp. Ne pas cocher Mask variable : une clé occupe plusieurs lignes, et une variable masquée ne peut pas en contenir. Si Protect variable est coché, la branche par défaut doit elle aussi être protégée, sinon la variable arrive vide.
SSH_USER_HOST_LOCATION — type Variable. C’est la destination rsync, par exemple gitlabci@serveur.com:/var/www/mysite/.