sol2flow mit Docker Compose installieren
Ein selbst gehostetes sol2flow besteht aus einem Container (Web-App, API und Hintergrundjobs) plus einer PostgreSQL-Datenbank (16, 17 oder 18; 18 empfohlen). Hochgeladene Dateien landen auf einem Volume oder in S3-kompatiblem Speicher. E-Mails gehen per SMTP hinaus.
Voraussetzungen
- Ein Linux-Server (x86-64 oder ARM64) mit Docker und dem Docker Compose-Plugin.
- 1 CPU und 1–2 GB Arbeitsspeicher für ein kleines Team; mehr für viele Benutzer oder große Importe.
- Ein Domainname, der auf den Server zeigt, und ein Reverse-Proxy für HTTPS (Reverse-Proxy und TLS).
- Ein SMTP-Konto zum Versenden von E-Mails (E-Mail).
- Speicherplatz für die Datenbank und für Uploads, plus Platz für Backups.
- PostgreSQL 16, 17 oder 18 (18 empfohlen). Die
compose.ymlunten bringt 18 mit; Sie nutzen schon 16 oder 17? Siehe PostgreSQL aktualisieren.
Das Image ist ghcr.io/sol2flow/sol2flow. Tags: latest, ein Release wie 1.2.3 oder eine Minor-Linie wie 1.2.
Legen Sie in Produktion eine feste Version fest, damit Upgrades dann passieren, wenn Sie es wollen.
1. Ein Verzeichnis vorbereiten
sudo mkdir -p /srv/sol2flow && cd /srv/sol2flow
Legen Sie compose.yml an:
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: {} }
Die App läuft als Benutzer und Gruppe 1001, nicht als root, und besitzt im Image /data/uploads und /data/logs.
Benannte Volumes wie die oben übernehmen das von selbst. Um die Dateien stattdessen in einem Verzeichnis des Hosts
abzulegen (ein Bind-Mount wie /srv/sol2flow/uploads:/data/uploads), übergeben Sie es zuerst diesem Benutzer:
sudo mkdir -p /srv/sol2flow/uploads /srv/sol2flow/logs
sudo chown -R 1001:1001 /srv/sol2flow/uploads /srv/sol2flow/logs
2. Konfigurieren
Legen Sie daneben eine .env an. Das Minimum für Produktion:
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>
Ersetzen Sie jedes <…> durch einen echten Wert. Machen Sie .env nur für root lesbar (chmod 600 .env).
APP_ENCRYPTION_KEY verschlüsselt Secrets, die in der Datenbank gespeichert sind (Secrets von Identity-Providern,
Zwei-Faktor-Secrets, Webhook-Secrets). Bewahren Sie eine Kopie außerhalb des Servers und außerhalb Ihrer
Datenbank-Backups auf. Geht der Schlüssel verloren oder wird er geändert, sind diese Secrets nicht mehr lesbar. Siehe
Backups und Upgrades.
Alle Variablen sind unter Konfiguration beschrieben.
3. Starten
docker compose pull
docker compose up -d
docker compose logs -f app
Bei jedem Start wendet die App ausstehende Datenbankmigrationen an und startet dann den Server auf Port 3000. Zwei Endpunkte zeigen, dass sie läuft:
/api/healthantwortet, wenn der Prozess läuft./api/readyantwortet, wenn zusätzlich die Datenbank erreichbar ist.
curl -fsS http://127.0.0.1:3000/api/ready
4. HTTPS davorschalten
Richten Sie Ihren Reverse-Proxy auf 127.0.0.1:3000 und liefern Sie die App unter Ihrer Domain aus:
Reverse-Proxy und TLS. APP_URL muss exakt die Adresse sein, die Personen eingeben (Schema, Host und
Port, falls nicht der Standardport).
5. Der erste Administrator
Ist BOOTSTRAP_ADMIN_PASSWORD gesetzt, legt der erste Start das Konto aus den BOOTSTRAP_ADMIN_*-Variablen als
Owner der Instanz an, die höchste Staff-Rolle. Der Benutzername ist admin, sofern Sie keinen anderen setzen; die
E-Mail-Adresse ist optional. Das geschieht nur, solange die Instanz keine Benutzer hat; Sie können BOOTSTRAP_ADMIN_PASSWORD
danach also aus der .env entfernen.
Seine E-Mail-Adresse gilt als bestätigt, ebenso die Adresse jedes Kontos, das das Skript create-admin unten anlegt.
Eine neue Instanz startet leer: Dieses Konto ist ihr einziges, und es gibt keine Demodaten. Die integrierten Board-Vorlagen sind von Anfang an da.
Ohne BOOTSTRAP_ADMIN_PASSWORD legen Sie den Owner über die Kommandozeile an:
docker compose exec app node scripts/create-admin.mjs <username> <email> <password>
Das Skript funktioniert auch später:
- Solange die Instanz keinen Owner hat, legt es einen Owner an (oder befördert ein Konto dazu); sonst einen Admin.
- Mit
--role owner|admin|support|auditorwählen Sie eine andere Staff-Rolle, zum Beispieldocker compose exec app node scripts/create-admin.mjs lea [email protected] '…' --role support. - Ein vorhandenes Konto behält sein Passwort und erhält die Rolle. Das Skript stuft einen vorhandenen Owner nie herab; Rollen ändern Sie unter Admin → Benutzer.
Was jede Rolle darf: Staff-Rollen.
6. Nach der ersten Anmeldung
- Admin → Allgemein: Name der Instanz, Upload-Limits, Benachrichtigungs-E-Mails. Siehe Instanz-Einstellungen.
- Admin → Authentifizierung: Anmeldung per Passwort, Selbstregistrierung, Single Sign-on. Siehe Anmeldung.
- Schicken Sie sich selbst einen Passwort-Reset, um zu prüfen, ob der E-Mail-Versand funktioniert.
- Richten Sie Backups ein, bevor echte Daten hinzukommen.
Separater Worker (optional)
Hintergrundarbeit (E-Mails, Aufräumarbeiten, Exporte, Importe, Webhooks) läuft im App-Container. Auf einer stark genutzten Instanz können Sie sie in einen eigenen Container auslagern:
- Setzen Sie
ROLE=webauf den Containern, die Benutzer bedienen: Sie führen dann keine Hintergrundjobs mehr aus. - Fügen Sie einen weiteren Service mit demselben Image und derselben
.envhinzu, mitROLE=workerund ohne veröffentlichten Port. Er führt die Jobs aus.