Zola #2 - Mise en place
Cet article fait suite à Zola #1 - Comment j'ai choisi mon CMS/SSG en 2026 et décrit les configurations possibles pour une exploitation de Zola. Les étapes décrites dans ce document sont adaptées à GitLab et FreeBSD.
Mise en place de Zola
J'envisage 2 scénarios pour la mise en place de Zola:
-
Scénario PULL: le serveur de production se tiens à jour périodiquement vis à vis des sources du site. Il possède une installation locale de Zola et peut lancer un build quand il détecte une mise à jour de contenu sur le site. Dans ce cas, le serveur "pull" les changements depuis GitLab puis build et publie directement les nouveaux contenus.
-
Scénario PUSH: le serveur de production ne fait rien et ne possède pas Zola. Il possède uniquement un serveur web et autorise des connexions ssh/rsync depuis GitLab. Dans ce cas, il faut mettre en place une pipeline CI/CD sur GitLab pour lancer une image docker contenant Zola et faire un build CI/CD du site. Si le build est en succès il faut alors deployer le site généré sur le serveur de production via rsync.
Scénario PULL
Sur mon serveur, équipé en FreeBSD 15.0, je dois recompiler Zola dans sa version 0.23.2 car c'est la version que j'ai utilisée pour écrire le site et cette version n'est pas encore disponible sous FreeBSD.
Le plan de compilation
# installer les outils de build
$ pkg install rust git pkgconf
# récupérer les sources à jour de Zola
$ git clone https://github.com/getzola/zola.git
# basculer sur la bonne version: 'master' correspond à 0.23.2
$ cd zola
$ git checkout master
# lancer le build
$ cargo build --release
Les première étapes déroulent sans le moindre souci:
$ pkg install rust git pkgconfThe following 14 package(s) will be affected (of 0 checked):
New packages to be INSTALLED:
git: 2.54.0 [FreeBSD-ports]
p5-Authen-SASL: 2.1900 [FreeBSD-ports]
p5-Crypt-URandom: 0.54 [FreeBSD-ports]
p5-Digest-HMAC: 1.05 [FreeBSD-ports]
p5-Error: 0.17030 [FreeBSD-ports]
p5-IO-Socket-SSL: 2.099 [FreeBSD-ports]
p5-MIME-Base32: 1.303 [FreeBSD-ports]
p5-MIME-Base64: 3.16 [FreeBSD-ports]
p5-Mozilla-CA: 20250602 [FreeBSD-ports]
p5-Net-SSLeay: 1.94 [FreeBSD-ports]
p5-URI: 5.34 [FreeBSD-ports]
pkgconf: 2.4.3_1,1 [FreeBSD-ports]
python312: 3.12.13_3 [FreeBSD-ports]
rust: 1.96.1 [FreeBSD-ports]
Number of packages to be installed: 14
The process will require 2 GiB more space.
228 MiB to be downloaded.
[...]
Checking integrity... done (0 conflicting)
[ 1/14] Installing p5-Crypt-URandom-0.54...
[ 1/14] Extracting p5-Crypt-URandom-0.54: 100%
[ 2/14] Installing p5-Digest-HMAC-1.05...
[ 2/14] Extracting p5-Digest-HMAC-1.05: 100%
[ 3/14] Installing p5-Authen-SASL-2.1900...
[ 3/14] Extracting p5-Authen-SASL-2.1900: 100%
[ 4/14] Installing p5-Error-0.17030...
[ 4/14] Extracting p5-Error-0.17030: 100%
[ 5/14] Installing p5-MIME-Base32-1.303...
[ 5/14] Extracting p5-MIME-Base32-1.303: 100%
[ 6/14] Installing p5-MIME-Base64-3.16...
[ 6/14] Extracting p5-MIME-Base64-3.16: 100%
[ 7/14] Installing p5-Mozilla-CA-20250602...
[ 7/14] Extracting p5-Mozilla-CA-20250602: 100%
[ 8/14] Installing p5-Net-SSLeay-1.94...
[ 8/14] Extracting p5-Net-SSLeay-1.94: 100%
[ 9/14] Installing p5-URI-5.34...
[ 9/14] Extracting p5-URI-5.34: 100%
[10/14] Installing p5-IO-Socket-SSL-2.099...
[10/14] Extracting p5-IO-Socket-SSL-2.099: 100%
[11/14] Installing pkgconf-2.4.3_1,1...
[11/14] Extracting pkgconf-2.4.3_1,1: 100%
[12/14] Installing python312-3.12.13_3...
[12/14] Extracting python312-3.12.13_3: 100%
[13/14] Installing git-2.54.0...
===> Creating groups
Creating group 'git_daemon' with gid '964'
===> Creating users
Creating user 'git_daemon' with uid '964'
[13/14] Extracting git-2.54.0: 100%
[14/14] Installing rust-1.96.1...
[14/14] Extracting rust-1.96.1: 100%$ git clone https://github.com/getzola/zola.gitCloning into 'zola'...
remote: Enumerating objects: 32900, done.
remote: Counting objects: 100% (485/485), done.
remote: Compressing objects: 100% (265/265), done.
remote: Total 32900 (delta 325), reused 220 (delta 220), pack-reused 32415 (from 3)
Receiving objects: 100% (32900/32900), 119.73 MiB | 11.22 MiB/s, done.
Resolving deltas: 100% (18702/18702), done.$ cd zola
$ git switch masterAlready on 'master'
Your branch is up to date with 'origin/master'.
Tout est prêt pour le build. Pourtant le build échouera avant la fin par manque RAM et de swap. En effet, Rust procède à un grand nombre d'optimisations très couteuses en mémoire lors de la phase finale du build. Mon modeste VPS avec 2Go de RAM et 1Go de swap est arrivé à saturation avant la fin du build.
Build adapté au capacités du VPS
Pour limiter le nombre de threads mais aussi les optimiseurs du linker (et d'autres), on préfère lancer la commande de build avec ces paramètres:
CARGO_PROFILE_RELEASE_LTO=false \
CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16 \
cargo build --release -j 1 Updating crates.io index
Downloaded anstyle-query v1.1.5
Downloaded ahash v0.8.12
Downloaded equivalent v1.0.2
Downloaded env_filter v2.0.0
Downloaded block-buffer v0.10.4
[...]
Downloaded libc v0.2.189
Downloaded giallo v0.5.2
Downloaded encoding_rs v0.8.35
Downloaded webp v0.3.1
Downloaded rust-stemmers v1.2.0
Downloaded libwebp-sys v0.9.6
Downloaded 485 crates (66.9MiB) in 7.47s (largest was `aws-lc-sys` at 9.2MiB)
Compiling proc-macro2 v1.0.107
Compiling unicode-ident v1.0.24
Compiling quote v1.0.47
Compiling syn v2.0.119
Compiling syn v3.0.3
Compiling cfg-if v1.0.4
Compiling libc v0.2.189
[...]
Compiling errors v0.23.2 (/home/freebsd/zola/components/errors)
Compiling utils v0.23.2 (/home/freebsd/zola/components/utils)
Compiling config v0.23.2 (/home/freebsd/zola/components/config)
Compiling content v0.23.2 (/home/freebsd/zola/components/content)
Compiling render v0.23.2 (/home/freebsd/zola/components/render)
Compiling markdown v0.23.2 (/home/freebsd/zola/components/markdown)
Compiling imageproc v0.23.2 (/home/freebsd/zola/components/imageproc)
Compiling templates v0.23.2 (/home/freebsd/zola/components/templates)
Compiling zola v0.23.2 (/home/freebsd/zola)
Compiling search v0.23.2 (/home/freebsd/zola/components/search)
Compiling link_checker v0.23.2 (/home/freebsd/zola/components/link_checker)
Compiling site v0.23.2 (/home/freebsd/zola/components/site)
Compiling axum v0.8.9
Compiling notify-debouncer-full v0.7.0
Compiling env_logger v0.11.11
Compiling ctrlc v3.5.2
Compiling open v5.4.1
Compiling console v0.23.2 (/home/freebsd/zola/components/console)
Finished `release` profile [optimized] target(s) in 46m 26s
On peut donc vérifier que la version du build est bien la 0.23.2 et ensuite l'installer sur le filesystem:
$ ./target/release/zola --version
zola 0.23.2
$ install -m 755 target/release/zola /usr/local/bin/zola
Il faut ensuite cloner la repository des sources du site depuis GitLab une première fois, s'assurer de rester sur la branche "main" qui est celle de publication, puis mettre en place un cron qui fait des update git à intervales régulier (par exemple toutes les nuits) et si un chamgement est détecté il faudra lancer lancer un build Zola.
Clonage de la repository git et switch sur "main":
freebsd@server:~ $ git clone https://gitlab.com/kosmology/website.git
Cloning into 'website'...
remote: Enumerating objects: 252, done.
remote: Counting objects: 100% (22/22), done.
remote: Compressing objects: 100% (20/20), done.
remote: Total 252 (delta 3), reused 0 (delta 0), pack-reused 230 (from 2)
Receiving objects: 100% (252/252), 6.16 MiB | 8.92 MiB/s, done.
Resolving deltas: 100% (9/9), done.
freebsd@server:~ $ cd website/
freebsd@server:~/website $ git switch main
Already on 'main'
Your branch is up to date with 'origin/main'.
Premier build du site avec zola:
freebsd@server:~/website$ zola build
Building site...
-> Creating 18 pages (0 orphan) and 2 sections
Done in 474ms.
On ajoute ensuite une entrée dans la crontab du user pour garantir la mise à jour du site toutes les nuits:
$ crontab -e
0 1 * * * cd /home/freebsd/website && /usr/local/bin/git pull --ff-only && /usr/local/bin/zola build >> /home/freebsd/website/cron-build.log 2>&1
Enfin une petite configuration Nginx pour l'hébergement du site:
server {
listen 80;
server_name my-website.fr www.my-website.fr;
root /home/freebsd/website/public;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Il faudra peaufiner les réglages Nginx et les droits sur les fichiers et répertoires, voir héberger les fichiers à un autre endroit sur le filesystem. Je n'ai fais que montrer le principe.
Voila l'essentiel pour faire fonctionner le scénario PULL.
Scénario PUSH
La partie CI/CD de Gitlab contiendra 3 phases:
- image: construction de l'image docker avec la version de Zola 0.23.x et les outils système tel que rsync
- build: phase de build classe qui utilise l'image docker avec zola pour récupérer les sources du site et faire le build
- deploy: phase de déploiement consécutive à la phase de build. Déploiement sur le serveur cible.
Préparation de l'image
On construit une image docker à partir d'Alpine Linux et ajoutant la version de Zola qui convient. On installe dans l'Alpine Linux: bash, curl, tar, gzip, git, ssh et rsync.
FROM alpine:3.22
ARG ZOLA_VERSION=0.23.2
RUN apk add --no-cache \
bash \
curl \
tar \
gzip \
git \
openssh-client \
rsync \
ca-certificates
RUN curl -L \
"https://github.com/getzola/zola/releases/download/v${ZOLA_VERSION}/zola-v${ZOLA_VERSION}-x86_64-unknown-linux-musl.tar.gz" \
-o /tmp/zola.tar.gz \
&& tar -xzf /tmp/zola.tar.gz -C /usr/local/bin \
&& rm /tmp/zola.tar.gz \
&& chmod +x /usr/local/bin/zola
RUN zola --version
WORKDIR /buildConfiguration GitLab CI
On définit le fichier YAML avec les 3 stages/phases qui nous intéressent.
stages:
- image
- build
- deploy
variables:
ZOLA_IMAGE: "$CI_REGISTRY_IMAGE/zola-ci:0.23.2"
#
# Construction de l'image CI Zola
#
build-ci-image:
stage: image
image: docker:latest
services:
- docker:dind
before_script:
- echo "$CI_REGISTRY_PASSWORD" |
docker login "$CI_REGISTRY" -u "$CI_REGISTRY_USER" --password-stdin
script:
- docker build -f Dockerfile.ci -t "$ZOLA_IMAGE" .
- docker push "$ZOLA_IMAGE"
rules:
- changes:
- Dockerfile.ci
#
# Construction du site Zola
#
build-site:
stage: build
image:
name: $ZOLA_IMAGE
entrypoint: [""]
script:
- zola --version
- zola build
artifacts:
name: "site-$CI_COMMIT_SHORT_SHA"
paths:
- public/
expire_in: 1 day
#
# Déploiement sur le VPS FreeBSD
#
deploy-site:
stage: deploy
image:
name: $ZOLA_IMAGE
entrypoint: [""]
needs:
- job: build-site
artifacts: true
before_script:
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- cp "$SSH_PRIVATE_KEY" ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
- cp "$SSH_KNOWN_HOSTS" ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
- rsync -az --delete public/ "$DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH/"
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
Pour que le deploy fonctionne il faut préparer le serveur destination: création d'un user de déploiement, création de clef ssh et réglages de base FreeBSD.
Configuration FreeBSD
On commence par créer le user "deploy". On définit un mot de passe et on prépare son SSH.
pw useradd deploy -m -s /bin/sh
passwd deploy
mkdir -p /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
touch /home/deploy/.ssh/authorized_keys
chmod 600 /home/deploy/.ssh/authorized_keys
chown -R deploy:deploy /home/deploy/.ssh
On installe rsync:
pkg install rsync
Adaptation des droits sur le répertoire qui va servir les fichiers pour le hosting:
chown -R deploy:deploy /usr/local/www/apache24/data/kosmology
On génère ensuite un clef SSH pour le user deploy. J'évite de le faire directement sur le serveur car cela n'est pas nécessaire. On reprends ensuite la clef publique pour la placer dans les authorized_keys du serveur:
local$ ssh-keygen -t ed25519 -C "gitlab-deploy" -f gitlab-deploy
local$ cat gitlab-deploy.pub
> ssh-ed25519 AAAbzzzz****************AAAAAA gitlab-deploy
server$ echo "ssh-ed25519 AAAbzzzz****************AAAAAA gitlab-deploy" >> ~/.ssh/authorized_keys
La suite se déroule dans l'interface de GitLab. Dans l'onglet Settings - CI/CD - Variables. On ajoute 5 variables de type "file":
SSH_PRIVATE_KEY : on y joint la clef privée du user "deploy"
SSH_KNOWN_HOSTS : on y joint le résultat de 'ssh-keyscan monsite.tld'
DEPLOY_HOST : le nom du host à joindre pour le déploiement.
DEPLOY_USER : "deploy" (le user qui servira pour les déploiements)
DEPLOY_PATH : /usr/local/www/.... (le répertoire de déploiement pour le serveur web)
Le résultat de la saisie devrait ressemble à cet écran:
On teste une petite Merge Request de la branche "drafting" vers "main" pour lancer une pipeline intégrale de build et de déploiement.
Et dans le détail:
Après vérification les fichiers ont bien été publiés sur le serveur. Le serveur web prends le relai et partage les fichiers directement après le dépot par GitLab.
Parfait !
Cela conclut la mise en place de tout l'outillage pour procéder à des publications automatisées via Zola.
