Installer sol2flow avec Docker Compose
Une instance sol2flow auto-hébergée, c’est un seul conteneur (l’application web, l’API et les tâches de fond) plus une base de données PostgreSQL (16, 17 ou 18 ; 18 recommandé). Les fichiers envoyés vont sur un volume ou dans un stockage compatible S3. Les e-mails partent via SMTP.
Prérequis
- Un serveur Linux (x86-64 ou ARM64) avec Docker et le plugin Docker Compose.
- 1 CPU et 1 à 2 Go de mémoire pour une petite équipe ; davantage pour beaucoup d’utilisateurs ou de gros imports.
- Un nom de domaine qui pointe vers le serveur, et un reverse proxy pour HTTPS (Reverse proxy et TLS).
- Un compte SMTP pour envoyer des e-mails (E-mail).
- De l’espace disque pour la base de données et les fichiers envoyés, plus de la place pour les sauvegardes.
- PostgreSQL 16, 17 ou 18 (18 recommandé). Le
compose.ymlci-dessous fournit la 18 ; déjà en 16 ou 17 ? Voir Mettre à niveau PostgreSQL.
L’image est ghcr.io/sol2flow/sol2flow. Tags : latest, une version comme 1.2.3, ou une branche mineure comme 1.2.
Fixez une version en production pour que les mises à niveau aient lieu quand vous le décidez.
1. Préparer un répertoire
sudo mkdir -p /srv/sol2flow && cd /srv/sol2flow
Créez compose.yml :
name: sol2flow
services:
app:
image: ghcr.io/sol2flow/sol2flow:${SOL2FLOW_VERSION:-latest}
restart: unless-stopped
env_file: .env
environment:
DATABASE_URL: postgresql://sol2flow:${POSTGRES_PASSWORD:-sol2flow}@db:5432/sol2flow?schema=public
ports: ["127.0.0.1:3000:3000"] # only the reverse proxy on this host talks to the app
volumes: [uploads:/data/uploads, logs:/data/logs] # logs: only used with LOG_FILE
depends_on: { db: { condition: service_healthy } }
db:
image: postgres:18-alpine
restart: unless-stopped
environment: { POSTGRES_USER: sol2flow, POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-sol2flow}", POSTGRES_DB: sol2flow }
volumes: [pgdata:/var/lib/postgresql] # from PostgreSQL 18 not …/data (data: …/18/docker)
healthcheck: { test: ["CMD-SHELL", "pg_isready -U sol2flow"], interval: 5s, retries: 20 }
volumes: { pgdata: {}, uploads: {}, logs: {} }
L’application s’exécute avec l’utilisateur et le groupe 1001, pas en root, et possède /data/uploads et /data/logs
dans l’image. Les volumes nommés comme ceux ci-dessus reprennent ces droits d’eux-mêmes. Pour garder plutôt les fichiers
dans un répertoire de l’hôte (un montage bind comme /srv/sol2flow/uploads:/data/uploads), attribuez-le d’abord à cet
utilisateur :
sudo mkdir -p /srv/sol2flow/uploads /srv/sol2flow/logs
sudo chown -R 1001:1001 /srv/sol2flow/uploads /srv/sol2flow/logs
2. Configurer
Créez .env à côté. Le minimum pour la production :
SOL2FLOW_VERSION=latest
APP_URL=https://flow.example.com
AUTH_SECRET=<openssl rand -base64 32>
APP_ENCRYPTION_KEY=<openssl rand -base64 32>
POSTGRES_PASSWORD=<openssl rand -hex 16>
MAIL_DRIVER=smtp
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_PASSWORD=<your SMTP password>
BOOTSTRAP_ADMIN_USERNAME=admin
BOOTSTRAP_ADMIN_PASSWORD=<a long password>
Remplacez chaque <…> par une vraie valeur. Rendez .env lisible uniquement par root (chmod 600 .env).
APP_ENCRYPTION_KEY chiffre les secrets stockés dans la base de données (secrets des fournisseurs d’identité, secrets
de double authentification, secrets des webhooks). Conservez-en une copie hors du serveur et hors de vos sauvegardes de
base de données. La perdre ou la changer rend ces secrets illisibles : voir
Sauvegardes et mises à niveau.
Chaque variable est décrite dans Configuration.
3. Démarrer
docker compose pull
docker compose up -d
docker compose logs -f app
À chaque démarrage, l’application applique les migrations de base de données en attente, puis lance le serveur sur le port 3000. Deux endpoints indiquent qu’elle fonctionne :
/api/healthrépond quand le processus tourne./api/readyrépond quand la base de données est aussi joignable.
curl -fsS http://127.0.0.1:3000/api/ready
4. Mettre HTTPS en frontal
Faites pointer votre reverse proxy vers 127.0.0.1:3000 et servez-le sur votre domaine : Reverse proxy et TLS.
APP_URL doit être exactement l’adresse que les gens saisissent (schéma, hôte, et port s’il n’est pas celui par défaut).
5. Le premier administrateur
Si BOOTSTRAP_ADMIN_PASSWORD est défini, le premier démarrage crée le compte décrit par BOOTSTRAP_ADMIN_* comme
Propriétaire de l’instance, le rôle staff le plus élevé. Le nom d’utilisateur est admin, sauf si vous en
choisissez un autre ; l’adresse e-mail est facultative. Cela ne se produit que tant que l’instance n’a aucun utilisateur ; vous pouvez donc retirer ensuite
BOOTSTRAP_ADMIN_PASSWORD de .env. Son adresse e-mail compte comme confirmée, tout comme l’adresse de chaque compte
créé par le script create-admin ci-dessous.
Une nouvelle instance démarre vide : ce compte est le seul, et il n’y a pas de données de démonstration. Les modèles de tableau intégrés sont disponibles dès le départ.
Sans BOOTSTRAP_ADMIN_PASSWORD, créez le Propriétaire en ligne de commande :
docker compose exec app node scripts/create-admin.mjs <username> <email> <password>
Le script fonctionne aussi plus tard :
- Tant que l’instance n’a pas de Propriétaire, il crée (ou promeut) un Propriétaire ; sinon un Admin.
- Choisissez un autre rôle staff avec
--role owner|admin|support|auditor, par exempledocker compose exec app node scripts/create-admin.mjs lea [email protected] '…' --role support. - Un compte existant garde son mot de passe et reçoit le rôle. Le script ne rétrograde jamais un Propriétaire existant : modifiez les rôles dans Admin → Utilisateurs.
Ce que chaque rôle peut faire : Rôles staff.
6. Après la première connexion
- Admin → Général : le nom de l’instance, les limites d’envoi de fichiers, les e-mails de notification. Voir Paramètres de l’instance.
- Admin → Authentification : connexion par mot de passe, inscription libre, authentification unique. Voir Connexion.
- Envoyez-vous une réinitialisation de mot de passe pour vérifier que l’e-mail fonctionne.
- Mettez en place les sauvegardes avant l’arrivée de vraies données.
Worker séparé (facultatif)
Le travail en arrière-plan (e-mails, nettoyages, exports, imports, webhooks) s’exécute dans le conteneur de l’application. Sur une instance chargée, vous pouvez le déplacer dans un conteneur dédié :
- Définissez
ROLE=websur le ou les conteneurs qui servent les utilisateurs : ils n’exécutent plus les tâches de fond. - Ajoutez un service supplémentaire avec la même image et le même
.env, avecROLE=workeret sans port publié. C’est lui qui exécute les tâches.