Aller au contenu principal

Docker

Le répertoire release/ du dépôt fournit tout le nécessaire :

FichiersRôle
docker-compose.light.ymlConteneur unique + SQLite (agencement d'évaluation).
docker-compose.full.yml5 services derrière Traefik (agencement de production).
docker-compose.swarm.ymlL'agencement full, porté vers la grammaire Swarm.
docker-compose.tls-letsencrypt.ymlOverlay TLS — Let's Encrypt via challenge TLS-ALPN.
docker-compose.tls-provided.ymlOverlay TLS — certificats fournis par l'opérateur (CA d'entreprise, PKI interne).
docker-compose.apps.ymlOverlay des apps sous licence — bind-mount de ./apps vers /apps:ro + positionne LIBERTY_APPS_DIR.
install.shGénère .env, récupère les images, démarre la pile, affiche les identifiants.
install-apps.shMatérialise la wheel des apps sous licence dans ./apps/ + câble l'overlay.
deploy-swarm.shCharge .env dans le shell + docker stack deploy.
backup.shArchive en tar chaque volume nommé Liberty + le bind mount apps dans un répertoire horodaté.
.env.exampleFichier d'environnement de référence documentant chaque variable prise en charge.
traefik/dynamic/dynamic.ymlMiddlewares basic-auth + en-têtes de sécurité + redirection vers HTTPS.

L'image se trouve à ghcr.io/fblettner/liberty-next (publique).

Cette page parcourt chaque agencement de bout en bout et détaille la discipline COMPOSE_FILE — la règle qui maintient chaque overlay actif sur toutes les commandes docker compose. Pour la vue d'ensemble conceptuelle et la comparaison des quatre formats, lire d'abord la Vue d'ensemble.


Prérequis

OutilVersion
Docker Engine≥ 24
Docker Composev2 (le plugin docker compose) — install.sh en vérifie la présence
Disque hôte~2 Go pour l'image + votre volume de BDD (light : ~50 Mo ; full : quelques Go une fois Postgres alimenté)
RAM hôte≥ 1 Go libre (light) ; ≥ 4 Go libre (full — Postgres shared_buffers=2GB par défaut)

Un hôte Linux (Ubuntu / Debian / Rocky / Alpine) est la cible classique. Docker Desktop sur macOS / Windows convient pour des essais locaux.


La discipline COMPOSE_FILE

install.sh inscrit une ligne de ce type dans .env :

.env (extrait)
COMPOSE_FILE=docker-compose.full.yml:docker-compose.tls-letsencrypt.yml:docker-compose.apps.yml

Docker Compose lit cette variable d'environnement à chaque commande et fusionne automatiquement chaque fichier listé. Les opérateurs ne saisissent jamais -f.

Commande (correcte)Commande (incorrecte)
docker compose pull (fusionne chaque overlay)docker compose -f docker-compose.full.yml pull (abandonne les overlays TLS + apps)
docker compose up -ddocker compose -f docker-compose.full.yml up -d
docker compose logs -f liberty-nextdocker compose -f docker-compose.full.yml logs -f liberty-next
docker compose downdocker compose -f docker-compose.full.yml down

Règle : après ./install.sh (ou ./install-apps.sh), une fois COMPOSE_FILE câblé, NE JAMAIS passer -f à la main. Passer -f écrase COMPOSE_FILE et abandonne silencieusement chaque overlay — le prochain up -d retirerait le montage apps et les routes TLS.

Pour une exécution ponctuelle qui cible réellement un fichier compose précis (debug, smoke test), employer COMPOSE_FILE=docker-compose.full.yml docker compose <cmd> afin de restreindre la surcharge à cette seule invocation.

install.sh répare les fichiers .env plus anciens

Sur les installations antérieures à la discipline COMPOSE_FILE, la réexécution de install.sh détecte la ligne manquante et l'ajoute automatiquement (COMPOSE_FILE=docker-compose.<agencement>.yml). Sans ce correctif, la découverte de projet de Compose remonte l'arborescence à la recherche d'un compose.yaml et peut sélectionner le mauvais fichier. La réparation est tracée : Existing .env lacks COMPOSE_FILE — adding 'COMPOSE_FILE=...'.


Agencement 1 — Light (docker-compose.light.yml)

Un seul conteneur, BDD framework en SQLite, pas de Postgres, pas de Traefik, pas de TLS. À utiliser pour un essai local, une démo mono-utilisateur ou toute installation qui n'a pas besoin d'un Postgres multi-utilisateurs.

Installation

git clone https://github.com/fblettner/liberty-next.git
cd liberty-next/release

./install.sh light # dernier tag
./install.sh light --tag 7.0.2 # épingler une version précise

Déroulement :

ÉtapeDescription
1. Vérification de volumes obsolètes.Si pg-data / pgadmin-data / liberty-data proviennent d'une installation antérieure mais que .env est absent, le script refuse de continuer — l'init Postgres ne s'exécute que sur un volume neuf, donc réemployer d'anciens volumes avec de nouveaux secrets aboutirait à un échec d'authentification permanent. Relancer avec --reset pour purger et repartir à neuf, ou restaurer le .env précédent.
2. Génère .env avec des secrets aléatoires (sans caractère $).Premier lancement uniquement.
3. Inscrit COMPOSE_FILE=docker-compose.light.yml dans .env.Toute commande docker compose ultérieure s'en sert.
4. docker compose pullRécupère ghcr.io/fblettner/liberty-next:<tag>.
5. docker compose up -dDémarre le conteneur liberty-next.
6. Attend jusqu'à 120 s le healthcheck du conteneur (GET /info).Affiche healthy une fois prêt.
7. Affiche l'URL du SPA et le mot de passe admin généré.À lire une seule fois ; également présent dans .env en mode 0600.

Le fichier compose :

docker-compose.light.yml (extrait)
services:
liberty-next:
image: ghcr.io/fblettner/liberty-next:${LIBERTY_IMAGE_TAG:-latest}
container_name: liberty-next
restart: unless-stopped
ports:
- "${LIBERTY_PORT:-8000}:8000"
environment:
LIBERTY_JWT_SECRET: "${LIBERTY_JWT_SECRET:?LIBERTY_JWT_SECRET is required}"
LIBERTY_MASTER_KEY: "${LIBERTY_MASTER_KEY:?LIBERTY_MASTER_KEY is required}"
LIBERTY_DB_URL: "${LIBERTY_DB_URL:-sqlite+aiosqlite:////data/liberty.db}"
LIBERTY_ADMIN_PASSWORD: "${LIBERTY_ADMIN_PASSWORD:-}" # premier démarrage uniquement — install.sh l'exporte ; non stocké dans .env
# La clé de licence, la clé d'API Anthropic et le client_secret OIDC ne se trouvent plus ici —
# les modifier via Settings → App dans le SPA (chiffrement au repos dans app.toml).
LIBERTY_LICENSE_KEY: "${LIBERTY_LICENSE_KEY:-}" # repli historique par variable d'environnement — laisser vide pour la gestion via l'UI
ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY:-}" # repli historique par variable d'environnement
volumes:
- liberty-data:/data # BDD SQLite + auth.toml
- liberty-config:/app/config # TOML édités par l'opérateur
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8000/info"]
interval: 30s
timeout: 5s
start_period: 40s
retries: 3

Ce que vous obtenez

Sur le port 8000 :

CheminDescription
/SPA React — se connecter avec admin et le mot de passe affiché par install.sh.
/docsSwagger UI.
/redocRéférence d'API ReDoc.
/openapi.jsonSpécification OpenAPI 3.
/infoLiveness public et compteurs (cible du healthcheck).

Deux volumes nommés :

VolumeDescriptionStratégie de sauvegarde
liberty-dataBDD SQLite + auth.toml (empreintes Argon2 des mots de passe).Capturé par backup.sh.
liberty-configTous les TOML édités par l'opérateur via Settings → ….Idem.

Mise à niveau

./backup.sh # toujours commencer par un instantané
docker compose pull # COMPOSE_FILE sélectionne les bons fichiers
docker compose up -d

L'entrypoint lance liberty-admin init-db à chaque démarrage — sans risque en double : il ajoute les nouvelles tables framework d'une version récente et laisse les lignes existantes intactes. Pour épingler une version précise, définir LIBERTY_IMAGE_TAG=7.0.2 dans .env (ou passer --tag 7.0.2 à la première installation).


Agencement 2 — Full (docker-compose.full.yml)

Cinq services derrière Traefik sur un seul hôte. L'agencement production / staging — et la cible canonique des bundles sous licence (Nomasx-1, Nomajde) puisqu'ils nécessitent un Postgres multi-utilisateurs.

Installation

./install.sh full # dernier tag, sans TLS
./install.sh full --tag 7.0.2 # tag épinglé
./install.sh full --ssl letsencrypt \ # + Let's Encrypt
--domain liberty.example.com --email ops@example.com
./install.sh full --apps ./liberty_apps-7.0.1.whl # + apps sous licence en une seule commande

install.sh génère .env avec des secrets aléatoires pour les valeurs exigées par la pile full — LIBERTY_JWT_SECRET, LIBERTY_MASTER_KEY, POSTGRES_PASSWORD, PGADMIN_PASSWORD — puis récupère toutes les images et démarre la pile. Le LIBERTY_ADMIN_PASSWORD du premier démarrage est généré, exporté vers le shell pour que le boot le récupère, puis affiché une seule fois dans le récapitulatif d'installation et non écrit dans .env (lors d'une réexécution, l'utilisateur admin existant conserve son mot de passe précédent). Durée totale d'installation sur cache chaud : ~30 s.

La clé de licence se renseigne après installation via Settings → App → License dans le SPA — chiffrée au repos dans app.toml avec la master key d'installation, appliquée à chaud à l'enregistrement (aucun redémarrage). Voir App settings. Le flag --license-key a été retiré de install.sh.

Ce que vous obtenez

Routage sur le port 80 (ou 443 une fois le TLS câblé) :

CheminServiceDescription
/ (catchall, priorité 1)liberty-nextSPA + API REST + admin + docs.
/pgadmin (priorité 100)pgAdminInterface Postgres — se connecter avec admin@liberty.fr (surchargeable via PGADMIN_EMAIL dans .env) et PGADMIN_PASSWORD issu de .env.
/portainer (priorité 100)PortainerInterface Docker.
/traefik (priorité 1000)Tableau de bord TraefikProtégé par basic-auth — par défaut admin/admin, à changer dans traefik/dynamic/dynamic.yml.

Les cinq volumes nommés de l'agencement full :

VolumeDescriptionInclus dans backup.sh ?
liberty-configTOML édités par l'opérateur.Oui.
pg-dataFichiers de la base Postgres.Oui.
pgadmin-dataEnregistrements de serveurs pgAdmin et préférences.Oui.
portainer-dataÉtat de Portainer.Oui.
traefik-acmeStockage des certificats Let's Encrypt (monté sur /acme dans Traefik).Non (récupérables à la demande).

Quand l'overlay apps est actif, ./apps/ (un répertoire hôte, pas un volume Docker) est également sauvegardé par backup.sh — celui-ci lit APPS_HOST_PATH depuis .env.

Réglages Postgres

Le Postgres fourni est livré avec des défauts type pgtune pour un hôte d'environ 8 Go :

docker-compose.full.yml (commande Postgres)
command:
- postgres
- -c
- shared_buffers=2GB
- -c
- work_mem=256MB
- -c
- maintenance_work_mem=128MB
- -c
- max_wal_size=8GB
- -c
- wal_level=minimal # désactive la réplication / PITR — mono-instance + sauvegardes nocturnes
- -c
- max_wal_senders=0
- -c
- synchronous_commit=off # ~1 s d'écritures peut être perdue sur un crash brutal — acceptable pour de l'ETL
- -c
- checkpoint_timeout=20min
- -c
- log_destination=stderr # journaux vers stderr (visibles via docker compose logs pg)
Taille de l'hôteAjustement
≤ 4 Go de RAMDiviser shared_buffers et work_mem par deux.
~8 Go de RAMValeurs par défaut.
≥ 16 Go de RAMMonter shared_buffers à ~25 % de la RAM et work_mem à 512 Mo.

Deux réglages échangent durabilité contre débit — à revoir avant des charges à durabilité stricte :

RéglageCompromis
wal_level=minimal + max_wal_senders=0Désactive la réplication physique / le PITR / le decoding logique. Acceptable pour un mono-instance avec sauvegardes nocturnes ; passer à wal_level=replica pour un hot standby.
synchronous_commit=offUn crash brutal peut perdre les dernières transactions validées (< 1 s d'écritures). Basculer sur on pour des charges financières.

Journalisation Postgres

Postgres écrit ses journaux sur stderr — consultables via docker compose logs -f pg. Le compose fourni rattache un driver de logs Docker json-file avec rotation (max-size: 100m, max-file: 3) afin que le fichier hôte /var/lib/docker/containers/<id>/<id>-json.log ne croisse pas indéfiniment.

Le fichier compose n'active PAS logging_collector=on + un volume nommé pg-logs — l'image postgres s'exécute sous l'UID 70 et un volume nommé fraîchement créé est monté en root:root, donc logging_collector planterait avec "Permission denied" dès la première écriture. Pour des journaux sur fichier, configurer un driver de logs côté hôte (json-file, syslog, fluentd) au niveau du démon Docker ou de chaque service.

Exposition du port Postgres

5432:5432 est mappé vers l'hôte par défaut — utile pour DBeaver depuis votre poste. Commenter le bloc ports: (ou positionner POSTGRES_PORT="" dans .env) pour garder Postgres en interne uniquement.

Câbler le TLS

Deux modes, tous deux câblés par install.sh --ssl. À choisir à l'installation, ou à reconfigurer plus tard (la réexécution conserve les secrets de .env mais met à jour la configuration SSL et COMPOSE_FILE).

Let's Encrypt (hôtes de démonstration / accessibles depuis Internet)

./install.sh full --ssl letsencrypt \
--domain liberty.example.com \
--email ops@example.com

Prérequis :

  • Le nom d'hôte résout vers cet hôte (enregistrement DNS A/AAAA).
  • Les ports :80 et :443 sont joignables depuis Internet (le challenge TLS-ALPN en a besoin).

Ce que cela fait :

  • Ajoute docker-compose.tls-letsencrypt.yml à COMPOSE_FILE dans .env.
  • Positionne LIBERTY_DOMAIN et ACME_EMAIL dans .env.
  • Traefik gère la demande et le renouvellement des certificats via le résolveur ACME. Les certificats persistent dans le volume nommé traefik-acme (monté sur /acme à l'intérieur de Traefik).

Certificats fournis par l'opérateur (hôtes d'entreprise / coupés du réseau)

./install.sh full --ssl provided \
--domain liberty.internal.example.com \
--cert-dir /etc/pki/tls \
--cert-file liberty.crt \
--key-file liberty.key

Prérequis :

  • Un répertoire sur l'hôte contenant le certificat (.crt / .pem) et la clé privée. install.sh vérifie leur existence avant de continuer.

Ce que cela fait :

  • Ajoute docker-compose.tls-provided.yml à COMPOSE_FILE.
  • Positionne CERT_HOST_PATH=<cert-dir> dans .env — Traefik bind-mount ce répertoire sur /etc/certs:ro.
  • Génère traefik/dynamic/tls.yml (gitignored) avec les noms de fichiers certificat + clé déjà inscrits. Traefik surveille ce fichier via file.watch=true — l'éditer pour ajouter d'autres certificats / règles SNI sans redémarrer.

Changer de mode plus tard

Réexécuter ./install.sh full --ssl <nouveau-mode> … avec les mêmes secrets en place. Le script remplace l'overlay dans COMPOSE_FILE, réécrit tls.yml (ou le supprime pour le mode LE), et docker compose up -d prend en compte la nouvelle configuration.

Sans SSL (par défaut)

./install.sh full sans --ssl fonctionne en HTTP seul sur :80. Acceptable pour du dev local ou derrière un autre reverse proxy qui termine le TLS en amont.

Parcours TLS complet : Traefik.

Ajouter les apps sous licence

Une seule commande à l'installation :

./install.sh full --apps ./liberty_apps-7.0.1.whl

Ou en deux temps (base d'abord, apps ensuite) :

./install.sh full
./install-apps.sh ./liberty_apps-7.0.1.whl

Dans les deux cas, renseigner ensuite le JWT de licence éditeur via Settings → App → License — les connecteurs sont reconstruits à l'enregistrement sans redémarrage.

La wheel est matérialisée dans ./apps/ via un conteneur jetable python:3.12-slim — l'hôte n'a besoin ni de Python ni de pip. Procédure complète + flags : Déployer des apps préfabriquées.

Changer le mot de passe du tableau de bord Traefik

Le admin/admin par défaut suffit pour les 30 premières secondes passées sur le tableau de bord. À remplacer ensuite :

docker run --rm httpd:alpine htpasswd -nbB admin "<votre-mot-de-passe>"
# admin:$2y$05$abc...

Coller la ligne produite dans release/traefik/dynamic/dynamic.yml sous http.middlewares.traefik-auth.basicAuth.users. file.watch=true recharge la configuration dynamique en quelques secondes — aucun redémarrage de conteneur n'est nécessaire.

Mise à niveau

./backup.sh # toujours commencer par un instantané
docker compose pull # COMPOSE_FILE fusionne chaque overlay
docker compose up -d

Le même init-db, ré-exécutable sans risque, s'exécute au démarrage de liberty-next. Épingler la version via LIBERTY_IMAGE_TAG=7.0.2 dans .env.


Agencement 3 — Docker Swarm (docker-compose.swarm.yml)

Mêmes cinq services que Full, adaptés à Swarm. Convient aux swarms mono-nœud (une VM, staging) et multi-nœuds (un manager + N workers).

Pourquoi un fichier compose séparé

docker stack deploy ignore plusieurs constructions propres à Compose (container_name, depends_on: condition: service_healthy, restart: unless-stopped) et exige des éléments absents de Compose (clés deploy.*, --providers.swarm, réseaux overlay). Le compose swarm est l'agencement full, porté vers la grammaire Swarm.

Installation

À faire une fois sur le manager :

docker swarm init # mono-nœud
docker swarm init --advertise-addr <manager-ip> # multi-nœuds

Puis :

cd liberty-next/release

./install.sh prepare # génère uniquement .env (secrets aléatoires, sans caractère $)
./deploy-swarm.sh # déploie la pile — nom par défaut 'liberty'

./install.sh prepare écrit .env sans démarrer la moindre pile Compose (Swarm ne s'appuie pas sur le runtime Compose). ./deploy-swarm.sh fait le reste :

ÉtapeDescription
1. set -a; . .env; set +aCharge .env dans le shell — docker stack deploy ne dispose d'aucun flag --env-file et lit l'environnement depuis le shell.
2. Vérification des variables requisesLIBERTY_JWT_SECRET, LIBERTY_MASTER_KEY, POSTGRES_PASSWORD, PGADMIN_PASSWORD doivent être non vides.
3. docker stack deploy --with-registry-auth --prune --resolve-image alwaysDéploie la pile. --with-registry-auth transmet les jetons d'auth du manager pour que les workers puissent récupérer les images privées ; --prune supprime les services absents du fichier compose.
4. Attend jusqu'à 180 s la convergence des servicesTous les services rapportent 1/1 répliques.
5. Affiche le tableau de la pile et les URLY compris les commandes de reset et de rollback propres au swarm.

Autres invocations utiles :

./deploy-swarm.sh --stack mystack # nom de pile personnalisé
./deploy-swarm.sh --status # affiche l'état courant des services, sans déploiement
./deploy-swarm.sh --rm # démonte la pile (les volumes survivent)

Question des variables d'environnement

Une fois .env chargé dans le shell, docker stack deploy substitue les ${VAR} dans la spécification des services. Après substitution, les valeurs sont figées dans le raft store du swarm — modifier .env après le déploiement n'a aucun effet. Réexécuter ./deploy-swarm.sh pour pousser de nouvelles valeurs.

Pour les secrets de longue durée, Docker Secrets est l'alternative native au swarm — chiffrés au repos dans le raft store et montés sous forme de fichiers (pas de variables d'environnement) dans les conteneurs cibles. Voir le bloc de commentaires en bas de docker-compose.swarm.yml pour la recette de migration vers les secrets.

Flags install.sh vs Swarm

Les flags de install.sh réservés à Compose — --apps, --ssl letsencrypt|provided — ne sont PAS transposables à Swarm. Pour les opérateurs Swarm :

ObjectifMéthode
Épingler le tag d'imagePositionner LIBERTY_IMAGE_TAG=7.0.2 dans .env avant ./deploy-swarm.sh.
Appliquer le TLSFusionner manuellement l'overlay TLS : docker stack deploy -c docker-compose.swarm.yml -c docker-compose.tls-letsencrypt.yml liberty (Swarm accepte -c répété).
Appliquer l'overlay appsIdem : -c docker-compose.swarm.yml -c docker-compose.apps.yml, avec APPS_HOST_PATH défini dans l'environnement du shell. Matérialiser d'abord la wheel via ./install-apps.sh ./liberty_apps-*.whl --target ./apps depuis un manager (le script saute le redémarrage Compose sur Swarm — le volume est déjà en place).
Mettre à jour un seul servicedocker service update --image ghcr.io/fblettner/liberty-next:0.2.0 liberty_liberty-next.
Rollbackdocker service rollback liberty_liberty-next.

Contraintes de placement

Le compose swarm épingle chaque service à un manager par défaut — convient pour les swarms mono-nœud et les petits clusters. Pour des déploiements plus larges :

ServiceOù l'épinglerPourquoi
pgUn nœud précis — node.hostname == <votre-nœud-pg>Le volume doit être rattaché au même endroit. Plusieurs managers sans cette contrainte = Postgres est replanifié sur un nœud avec un volume vide.
liberty-nextOptionnellement node.role == workerÀ déplacer vers des nœuds applicatifs dédiés s'ils existent.
traefikReste sur un manager--providers.swarm lit le socket Docker, accessible uniquement aux managers.

Notes sur la multi-réplication

replicas: 1 est la valeur par défaut pour chaque service. Les services à état (pg, pgadmin, portainer) doivent y rester — aucun ne possède de réplication intégrée. liberty-next conserve l'état Socket.IO en mémoire processus ; augmenter ses répliques sans backplane partagé (adaptateur Redis) donne aux clients une vue incohérente des tableaux de bord et flux de chat en direct. Le cookie sticky de Traefik aide mais ne suffit pas. À mettre à l'échelle une fois Redis câblé.

Sauvegardes et restaurations

backup.sh fonctionne à l'identique — les noms de volumes (liberty-config, pg-data, …) sont les mêmes en Compose et en Swarm. À lancer depuis le manager.


Sauvegardes — backup.sh

Prend un instantané tar de chaque volume nommé Liberty + du bind mount apps (quand il est défini) dans un répertoire horodaté. Fonctionne pour Compose ET Swarm. Lancement possible pile en marche (Docker assure la cohérence en lecture) ; pour un instantané à froid parfait, arrêter la pile au préalable.

./backup.sh # → ./backups/AAAA-MM-JJ_HHMMSS/
./backup.sh /mnt/nas/liberty # → /mnt/nas/liberty/AAAA-MM-JJ_HHMMSS/
./backup.sh --layout light # sauvegarde uniquement les volumes de l'agencement light
./backup.sh --layout full # sauvegarde uniquement les volumes de l'agencement full
./backup.sh --keep 30 # supprime les sauvegardes de plus de 30 jours dans la destination

Chaque exécution produit un répertoire :

FichierQuand il est présent
liberty-config.tar.gzToujours.
liberty-data.tar.gzAgencement light (SQLite + auth.toml).
pg-data.tar.gz, pgadmin-data.tar.gz, portainer-data.tar.gzAgencement full.
liberty-apps.tar.gzQuand APPS_HOST_PATH est défini dans .env (overlay apps actif).
.env.snapshotToujours (mode 0600 — à retirer avant synchronisation hors site si les secrets ne doivent pas figurer dans la sauvegarde).
docker-compose.*.ymlLe(s) fichier(s) compose présent(s) dans le répertoire au moment de la sauvegarde.

Exécution hebdomadaire via cron

0 3 * * 0 cd /opt/liberty-next/release && ./backup.sh /mnt/nas/liberty --keep 60

Restaurer un volume

backup.sh affiche la commande exacte en cas de succès. La forme générale :

docker compose down # DOIT être à l'arrêt — COMPOSE_FILE sélectionne les bons fichiers
docker volume rm pg-data # purge (sauter cette étape pour superposer)
docker run --rm -v pg-data:/data -v "$PWD/backups/<dir>:/backup" alpine \
sh -c 'rm -rf /data/* /data/.[!.]* && tar xzf /backup/pg-data.tar.gz -C /data'
docker compose up -d

Pour Swarm : démonter d'abord la pile (./deploy-swarm.sh --rm), restaurer, puis redéployer.

Restaurer le bind mount apps

Le répertoire apps est un dossier hôte, pas un volume Docker :

docker compose down # pour que liberty-next ne retienne pas le montage
rm -rf ./apps # ou le sauvegarder avant purge
tar xzf backups/<dir>/liberty-apps.tar.gz -C ./apps
docker compose up -d

Récupération — flag --reset

Quand une installation précédente a laissé des volumes obsolètes (pg-data initialisé avec un ancien mot de passe, puis .env perdu), le prochain install.sh générerait des secrets neufs qui ne correspondent plus — l'auth Postgres échoue à jamais, l'init Postgres ne s'exécutant que sur un volume neuf.

install.sh détecte ce cas et refuse de démarrer. Deux issues :

OptionDescription
./install.sh <agencement> --resetdocker compose down + docker volume rm de chaque volume de données Liberty (pg-data, pgadmin-data, portainer-data, liberty-data, liberty-config) + suppression de .env, puis sortie. Relancer ensuite ./install.sh avec les flags d'installation souhaités. Le volume traefik-acme est volontairement préservé — Let's Encrypt applique une limite de 5 certificats / 7 jours / ensemble de domaines ; le purger à chaque reset épuiserait le quota. Pour forcer un nouveau certificat (changement de domaine, compromission de clé), le supprimer manuellement : docker volume rm traefik-acme.
Restaurer le .env précédentReplacer l'ancien fichier .env dans release/, puis relancer ./install.sh. Le script détecte le .env existant et se contente de démarrer la pile — les secrets correspondent aux volumes.

Le .env.snapshot produit par backup.sh est le « .env précédent » canonique — à conserver à côté des instantanés de volumes.

--reset est destructif et s'arrête — pas de réinstallation automatique

Combiner --reset avec --apps, --ssl ou tout autre flag d'installation provoque une erreur — le comportement antérieur ignorait silencieusement les flags d'installation. Le message d'erreur indique la séquence de deux commandes probablement attendue :

./install.sh full --reset # 1) purge
./install.sh full --ssl letsencrypt --domain ... --apps ./... # 2) installation avec les flags souhaités

Opérations courantes

BesoinComposeSwarm
Réinitialiser le mot de passe admindocker compose exec liberty-next liberty-admin set-password admin <new>docker exec $(docker ps -qf name=liberty_liberty-next) liberty-admin set-password admin <new>
Ajouter un autre superutilisateurdocker compose exec liberty-next liberty-admin create-user <name> --superuserdocker exec $(docker ps -qf name=liberty_liberty-next) liberty-admin create-user <name> --superuser
Inspecter la clé de licencedocker compose exec liberty-next liberty-license verifydocker exec $(docker ps -qf name=liberty_liberty-next) liberty-license verify
Suivre les journauxdocker compose logs -f liberty-nextdocker service logs -f liberty_liberty-next
Ouvrir un shelldocker compose exec liberty-next bashdocker exec -it $(docker ps -qf name=liberty_liberty-next) bash
Lister les servicesdocker compose psdocker stack services liberty
Recharger la configuration (changement TOML)POST /admin/reload (le bouton de l'UI Settings le déclenche)Idem.

Voir liberty-admin --help / liberty-license --help pour la CLI complète.


Dépannage

Le conteneur sort immédiatement

docker compose logs liberty-next # pas besoin de -f — COMPOSE_FILE sélectionne les bons fichiers
Ligne de journalCauseCorrection
LIBERTY_JWT_SECRET is requiredLa variable d'environnement requise n'a pas été propagée.install.sh aurait dû la générer — vérifier .env.
Could not connect to database (agencement full)Postgres n'est pas encore en bonne santé.Attendre 10 s — la clause depends_on: condition: service_healthy couvre normalement le cas ; vérifier docker compose ps pg.
password authentication failed for user "liberty"Volume pg-data obsolète issu d'une installation antérieure ; .env contient désormais de nouveaux secrets../install.sh full --reset (purge + sortie — relancer ensuite install.sh avec les flags souhaités) ou restaurer l'ancien .env.
Le healthcheck ne passe jamais à healthyLe conteneur est démarré mais /info ne répond pas.Suivre les journaux — le plus souvent, un TOML de configuration sur le volume liberty-config comporte une erreur de syntaxe.

La page de connexion s'affiche, mais la connexion échoue

Le mot de passe de l'admin amorcé est affiché une seule fois par install.sh et n'est pas stocké dans .env. Pour le réinitialiser à la demande :

docker exec liberty-next liberty-admin reset-admin-password # génère et affiche un nouveau mot de passe
# ou :
docker compose exec liberty-next liberty-admin set-password admin <new>

L'overlay apps a été ajouté mais les TOML ne sont pas chargés

Vérifier COMPOSE_FILE dans .env — il doit se terminer par :docker-compose.apps.yml. Relancer ./install-apps.sh <wheel> si nécessaire. Une fois la variable positionnée, docker compose up -d prend en compte la modification.

Le port 8000 / 80 est occupé

Light : LIBERTY_PORT=8001 dans .env. Full : TRAEFIK_HTTP_PORT=8080 dans .env. Puis docker compose up -d.

Swarm : les services restent en 0/1

docker stack ps liberty --no-trunc # affiche la décision de placement et l'erreur
docker service logs liberty_<service-name> # suit les journaux du service

Le plus fréquent : une contrainte de placement insatisfaite (Postgres épinglé sur un nœud absent du swarm), ou le manager ne peut pas récupérer l'image (réseau / auth registry).


La suite