Aller au contenu

Déployer Kirexo en production

Vous êtes mainteneur·se de Kirexo avec un accès SSH au serveur de production et vous voulez mettre en ligne une release déjà buildée par la CI, ou revenir à une release antérieure. Cette recette couvre le déploiement et le rollback.

Prérequis

  • Une release a déjà été créée via la pipeline (cf. Créer un tag de release) : un tag Git YYYYMMDDHHMM existe, et le job docker:build-prod a poussé l'image kirexo-prod:<tag> dans le registry.
  • Le serveur de prod est un hôte Docker avec Traefik en reverse proxy (cf. labels dans compose.prod.yaml).
  • Le dépôt est cloné sur le serveur (pour disposer de compose.yaml et compose.prod.yaml), ou ces deux fichiers y sont présents.
  • Les secrets de prod (APP_SECRET, POSTGRES_PASSWORD, RABBITMQ_PASSWORD, TYPESENSE_API_KEY, CADDY_MERCURE_JWT_SECRET, SENTRY_DSN…) et les variables d'infra (SERVER_NAME…) sont exportés dans l'environnement du serveur — jamais versionnés. Voir À surcharger obligatoirement en production.
  • Vous avez authentifié le démon Docker auprès du registry GitLab : docker login registry.gitlab.com.
  • cosign ≥ v2.x est installé sur le serveur (paquet de distribution cosign ou binaire téléchargé depuis les releases sigstore). C'est ce binaire qui vérifie la signature keyless de l'image avant le pull (cf. Vérifier la signature de l'image avant de la pull). Épinglez la même version majeure que celle utilisée par la CI (cf. Signature keyless de kirexo-prod) pour éviter une dérive de format d'attestation.

Le serveur pull, il ne build pas

Depuis l'étape 4, le service php de compose.prod.yaml référence une image immuable poussée par la CI au lieu de la builder sur place :

image: ${IMAGES_PREFIX:-registry.gitlab.com/shaurifr/kirexo/}kirexo-prod:${KIREXO_VERSION:-latest}

Le serveur pull cette image. Builder sur la prod serait non reproductible (build différent de celui testé par la CI), exigerait toute la toolchain Docker plus le code source sur le serveur, et ferait perdre la traçabilité de version. Le bloc build: est conservé en commentaire dans compose.prod.yaml uniquement pour un rebuild local ponctuel de debug — jamais pour un déploiement.

Deux variables pilotent l'image tirée (détail dans Image de production et préfixe de registry) :

  • KIREXO_VERSION — le tag à déployer (un tag Git YYYYMMDDHHMM). Défaut latest.
  • IMAGES_PREFIX — le préfixe de registry. Défaut prod : registry.gitlab.com/shaurifr/kirexo/ (notez le / final obligatoire).

Toujours exporter KIREXO_VERSION

Le défaut latest est un tag mutable, réécrit à chaque release. Déployer sans KIREXO_VERSION, c'est déployer « la dernière release du moment » sans pouvoir la rejouer ni revenir en arrière de façon déterministe. Exportez toujours un tag précis.

Vérifier la signature de l'image avant de la pull

Chaque image kirexo-prod poussée sur tag de release est signée par la CI en mode keyless via cosign (cf. Signature keyless de kirexo-prod). Avant tout docker compose pull, vérifiez côté serveur que l'image cible porte bien une signature émise par le pipeline GitLab de ce projet. Une image non signée ou signée par un autre pipeline doit faire refuser le déploiement.

export KIREXO_VERSION=202605231742

cosign verify "registry.gitlab.com/shaurifr/kirexo/kirexo-prod:${KIREXO_VERSION}" \
    --certificate-identity-regexp='^https://gitlab\.com/shaurifr/kirexo' \
    --certificate-oidc-issuer='https://gitlab.com'
Option Rôle
--certificate-identity-regexp='^https://gitlab\.com/shaurifr/kirexo' Restreint les signatures acceptées à celles émises par un pipeline du projet GitLab Kirexo. Toute autre identité (autre projet, autre namespace) est rejetée.
--certificate-oidc-issuer='https://gitlab.com' Restreint l'émetteur OIDC au provider GitLab.com — un certificat Fulcio délivré sur la base d'un JWT GitHub Actions, par exemple, serait rejeté.

Lire la sortie

Sur succès, cosign écrit en sortie une liste d'objets JSON contenant :

  • les claims OIDC capturés par Fulcio au moment de la signature : URL du projet, ref / sha du commit, identité sub du pipeline (https://gitlab.com/<group>/<project>//.gitlab-ci.yml@refs/tags/<tag>) ;
  • le hash de l'entrée Rekor correspondante (logIndex, logID) — preuve immuable que la signature a bien été publiée dans le log de transparence public.

La chaîne de confiance est complète : le tag de version est lié au pipeline GitLab qui l'a buildé, lui-même attesté par une entrée Rekor que l'on peut auditer a posteriori sans dépendre du serveur GitLab.

Sur échec (signature absente, certificat émis par un autre projet, image altérée), cosign termine en code non nul avec un message du type no matching signatures ou certificate identity does not match. Ne pas déployer : reprendre l'image, identifier la source de la divergence, et ré-investiguer côté pipeline avant d'aller plus loin.

Intégrer la vérification au shell de déploiement

Encapsulez la commande dans la même fonction shell qui fait le pull / up -d : un cosign verify ... || exit 1 placé avant docker compose pull interdit physiquement un déploiement non vérifié. Plus de risque d'oublier l'étape un soir de hotfix.

Déployer une release

  1. Identifier le tag à déployer (l'onglet Tags ou Deploy → Releases sur GitLab, ou Deploy → Container Registry pour confirmer que kirexo-prod:<tag> existe).

  2. Sur le serveur, exporter la version puis pull et redémarrer :

    export KIREXO_VERSION=202605231742
    docker compose -f compose.yaml -f compose.prod.yaml pull
    docker compose -f compose.yaml -f compose.prod.yaml up -d
    

    pull récupère l'image taggée depuis le registry ; up -d recrée le conteneur php sur la nouvelle image. Les autres services (database, redis, rabbitmq, typesense, gotenberg) ne changent pas d'image et ne sont redémarrés que si nécessaire.

  3. Vérifier que le conteneur est sain :

    docker compose -f compose.yaml -f compose.prod.yaml ps
    

    Le service php doit être running et healthy (le healthcheck interroge l'endpoint admin Caddy :2019/metrics, défini dans compose.yaml).

Rendre la version persistante

Pour qu'un redémarrage ultérieur du serveur ne retombe pas sur le défaut latest, persistez KIREXO_VERSION côté serveur (variable d'environnement systemd, fichier d'env chargé par le shell de déploiement, gestionnaire de config…). Ne la mettez pas dans un fichier versionné du dépôt.

Revenir à une version antérieure (rollback)

Le rollback consiste à réexporter un KIREXO_VERSION antérieur et à re-pull — l'image cible existe déjà dans le registry, rien à rebuilder.

export KIREXO_VERSION=202605201408   # un tag connu et fonctionnel
docker compose -f compose.yaml -f compose.prod.yaml pull
docker compose -f compose.yaml -f compose.prod.yaml up -d

Le rollback ne couvre que l'image applicative

Revenir à une image antérieure ne défait pas les migrations de base de données déjà appliquées. Si la release fautive a joué une migration Doctrine destructive ou incompatible avec l'ancienne image, prévoyez une sauvegarde de la base avant de déployer, et un plan de restauration distinct. Le tag d'image ne versionne que le code, pas l'état du schéma.

SBOM disponible en asset de la release

Chaque release GitLab YYYYMMDDHHMM expose en assets deux Software Bill of Materials de l'image kirexo-prod:<tag> correspondante (produits par le job release:sbom, cf. Job release:sbom) :

Asset (widget « Assets » de la release) Format Consommateurs typiques
SBOM (SPDX JSON) SPDX 2.x — référence côté conformité (OpenChain, NTIA Minimum Elements). Outils d'audit logiciel, exports juridiques.
SBOM (CycloneDX JSON) CycloneDX — référence côté outillage de sécurité. Dependency-Track, Trivy en mode SBOM, Snyk.

Les deux fichiers listent les paquets OS Debian, les extensions PHP et les dépendances Composer présentes dans vendor/. Ils restent téléchargeables depuis l'onglet Deploy → Releases du projet GitLab tant que les artifacts du job release:sbom ne sont pas expirés (rétention 1 an).

Si vous opérez un Dependency-Track ou un Trivy en pipeline d'audit, alimentez-le directement avec ces fichiers. Aucun retraitement intermédiaire n'est nécessaire — les SBOM sont émis dans des formats consommés tels quels par ces outils.

Cas d'erreur

docker compose pull échoue sur manifest unknown ou not found

Le tag KIREXO_VERSION exporté ne correspond à aucune image dans le registry. Vérifier dans Deploy → Container Registry que kirexo-prod:<tag> existe — il n'est créé que si le job docker:build-prod a réussi sur la pipeline du tag (cf. Créer un tag de release).

docker compose pull échoue sur unauthorized / denied

Le démon Docker du serveur n'est pas (ou plus) authentifié auprès du registry. Relancer docker login registry.gitlab.com avec un compte ayant accès au projet.

Le préfixe d'image est collé au nom (kirexokirexo-prod)

IMAGES_PREFIX a été redéfini manuellement sans / final. Le corriger pour qu'il se termine par une barre oblique (cf. l'avertissement dédié).

cosign verify échoue avec no matching signatures

L'image cible n'a pas été signée par le pipeline GitLab Kirexo. Causes possibles : tag manuellement poussé hors release officielle (ex. wip-foo), image antérieure à l'introduction de docker:sign-prod, ou divergence d'identité (autre fork du projet). Refuser le déploiement tant que la signature n'est pas valide ; relancer une release officielle via Créer un tag de release si nécessaire.

cosign verify échoue avec certificate identity does not match

L'image a été signée — mais par un pipeline qui ne matche pas la regex d'identité (autre namespace, autre projet, ou JWT émis par un provider OIDC différent de GitLab). Vérifier que le tag pointe bien sur le bon registry (registry.gitlab.com/shaurifr/kirexo/kirexo-prod:<tag>) ; ne jamais assouplir la regex pour faire passer une signature suspecte.

Voir aussi