Documenso mit Docker installieren: Open-Source-Alternative zu DocuSign selbst hosten
Documenso ist die DSGVO-konforme Open-Source-Alternative zu DocuSign: digitale Signaturen nach PAdES-Standard, selbst gehostet ohne US-Cloud. Von der .env-Konfiguration bis zum ersten signierten Dokument – mit Troubleshooting für den Produktivbetrieb.

Wer rechtssichere digitale Signaturen braucht, greift meist zu DocuSign oder Adobe Acrobat Sign – und sendet dabei unweigerlich sensible Verträge in US-amerikanische Rechenzentren. Documenso schließt diese Lücke: Das Projekt (AGPL-3.0, über 13.000 GitHub-Sterne, aktuelle Version v2.11.0) bietet digitale Dokumentensignaturen nach dem EU-Standard PAdES auf dem eigenen Server. Für KMU, Rechtsabteilungen, Steuerkanzleien und HR-Teams bedeutet das: keine Abhängigkeit von US-Anbietern, volle DSGVO-Kontrolle und ein Audit-Trail, der auf der eigenen Infrastruktur liegt. Diese Anleitung führt dich Schritt für Schritt durch die Docker-Compose-Installation – von der Ordnerstruktur über das Signaturzertifikat bis zur ersten Einladung an Unterzeichner.
Voraussetzungen
- Docker Engine 20.10+ und Docker Compose v2.0+ auf dem Host installiert – falls noch nicht geschehen, hilft die Anleitung Docker und Docker Compose auf Linux installieren.
- Linux-Host, VM oder NAS mit mindestens 2 GB RAM, 2 CPU-Kernen und 20 GB freiem Speicher (Minimum: 1 GB RAM, 1 Kern, 10 GB).
- Eigene Domain mit DNS-A-Record auf den Server und ein TLS-Zertifikat – am einfachsten über Traefik oder Caddy mit automatischem Let's-Encrypt-Support. Für HTTPS ohne eigenen Reverse Proxy gilt die Anleitung Caddy als Reverse Proxy einrichten.
- OpenSSL auf dem Host (für Secret- und Zertifikatgenerierung).
- SMTP-Zugangsdaten eines E-Mail-Providers (z. B. Resend, Mailgun, eigener Postfix) – ohne funktionierenden Mail-Versand können keine Signaturanfragen verschickt werden.
- Root- oder sudo-Zugang zum Host (für Verzeichnis- und Berechtigungsoperationen).
| Eigenschaft | Wert |
|---|---|
| Docker-Image | documenso/documenso:v2.11.0 (Docker Hub) · ghcr.io/documenso/documenso:v2.11.0 (GHCR) |
| Image-Größe | ca. 644 MB |
| Web-Port | 3000 (konfigurierbar über PORT) |
| Datenbank | PostgreSQL 14+ (ausschließlich; kein MySQL/SQLite) |
| Signaturstandard | PAdES (PDF Advanced Electronic Signatures, EU-konform) |
| Lizenz | AGPL-3.0 |
| RAM (Produktion) | mind. 2 GB (Minimum: 1 GB) |
Schritt 1: Projektordner und Zertifikatsverzeichnis anlegen
Lege zunächst die Ordnerstruktur auf dem Host an. Der Pfad /opt/documenso ist der dokumentierte Standard-Mountpunkt für das Signaturzertifikat im Container:
sudo mkdir -p /opt/documenso
cd /opt/documensoSetze die Berechtigungen so, dass dein Admin-Benutzer die Dateien anlegen kann, der Container aber nur Lese-Zugriff auf das spätere Zertifikat bekommt:
sudo chown $(whoami):$(whoami) /opt/documensoVerifizieren: ls -la /opt/ | grep documenso – das Verzeichnis muss mit deinem Benutzer als Eigentümer existieren.
Schritt 2: Signaturzertifikat (.p12) erstellen
Documenso benötigt ein PKCS#12-Zertifikat für PAdES-Signaturen. Das Image enthält kein Standard-Zertifikat – du musst es selbst bereitstellen. Für interne Tests oder KMU-Einsatz ohne Anforderung an qualifizierte elektronische Signaturen (QES) reicht ein selbstsigniertes Zertifikat:
# Schlüssel und selbstsigniertes Zertifikat erzeugen (10 Jahre Laufzeit)
openssl req -x509 -nodes -newkey rsa:4096 \
-keyout /opt/documenso/key.pem \
-out /opt/documenso/cert.pem \
-days 3650 \
-subj "/CN=Documenso Signing/O=Mein Unternehmen/C=DE"
# PKCS#12-Bundle MIT Passwort erstellen (Pflicht – ohne Passwort schlägt Documenso fehl)
openssl pkcs12 -export \
-out /opt/documenso/cert.p12 \
-inkey /opt/documenso/key.pem \
-in /opt/documenso/cert.pem \
-passout pass:MEIN_SICHERES_ZERTPASSWORT
# Zwischendateien entfernen, Berechtigungen setzen
rm /opt/documenso/key.pem /opt/documenso/cert.pem
sudo chown 1001:1001 /opt/documenso/cert.p12
sudo chmod 400 /opt/documenso/cert.p12Notiere dir das gewählte Passwort – es kommt in Schritt 3 als NEXT_PRIVATE_SIGNING_PASSPHRASE in die .env. Für rechtssichere qualifizierte Signaturen (QES) nach eIDAS benötigst du ein Zertifikat einer akkreditierten Vertrauensstelle (z. B. D-Trust, Bundesdruckerei).
Verifizieren: ls -la /opt/documenso/cert.p12 – Ausgabe muss -r-------- (400) mit Eigentümer 1001 zeigen. Mit openssl pkcs12 -info -in /opt/documenso/cert.p12 -passin pass:MEIN_SICHERES_ZERTPASSWORT -nokeys 2>/dev/null | head -5 kannst du das Zertifikat inhaltlich prüfen.
Schritt 3: Secrets generieren und .env anlegen
Erzeuge zunächst alle benötigten Zufalls-Secrets mit OpenSSL auf der Kommandozeile. Drei unabhängige Secrets mit je mindestens 32 Zeichen sind Pflicht:
openssl rand -base64 32 # NEXTAUTH_SECRET
openssl rand -base64 32 # NEXT_PRIVATE_ENCRYPTION_KEY
openssl rand -base64 32 # NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY
openssl rand -base64 24 # POSTGRES_PASSWORDLege anschließend die Datei /opt/documenso/.env an und fülle sie mit deinen Werten:
# ── Datenbank ────────────────────────────────────────────────
POSTGRES_USER=documenso
POSTGRES_PASSWORD=DEIN_DB_PASSWORT_HIER
POSTGRES_DB=documenso
NEXT_PRIVATE_DATABASE_URL=postgresql://documenso:DEIN_DB_PASSWORT_HIER@database:5432/documenso
# ── Auth & Verschlüsselung ────────────────────────────────────
NEXTAUTH_SECRET=DEIN_NEXTAUTH_SECRET_HIER
NEXT_PRIVATE_ENCRYPTION_KEY=DEIN_ENCRYPTION_KEY_HIER
NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY=DEIN_SECONDARY_KEY_HIER
# ── URLs (exakt wie im Browser erreichbar) ───────────────────
NEXT_PUBLIC_WEBAPP_URL=https://sign.example.com
NEXT_PRIVATE_INTERNAL_WEBAPP_URL=http://localhost:3000
# ── E-Mail ────────────────────────────────────────────────────
NEXT_PRIVATE_SMTP_TRANSPORT=smtp-auth
NEXT_PRIVATE_SMTP_HOST=smtp.example.com
NEXT_PRIVATE_SMTP_PORT=587
NEXT_PRIVATE_SMTP_USERNAME=dein@absender.de
NEXT_PRIVATE_SMTP_PASSWORD=DEIN_SMTP_PASSWORT
NEXT_PRIVATE_SMTP_FROM_ADDRESS=dein@absender.de
NEXT_PRIVATE_SMTP_FROM_NAME=Documenso
# ── Signaturzertifikat ────────────────────────────────────────
NEXT_PRIVATE_SIGNING_PASSPHRASE=MEIN_SICHERES_ZERTPASSWORT
# ── Optional: Telemetrie deaktivieren ─────────────────────────
DOCUMENSO_DISABLE_TELEMETRY=true
# ── Optional: Registrierung nach Erst-Setup sperren ──────────
# NEXT_PUBLIC_DISABLE_SIGNUP=trueSchütze die Datei vor fremdem Zugriff:
chmod 600 /opt/documenso/.envVerifizieren: ls -la /opt/documenso/.env muss -rw------- (600) anzeigen. Prüfe kritische Werte: grep NEXT_PRIVATE_DATABASE_URL /opt/documenso/.env – der Hostname muss database lauten (Docker-Compose-Servicename), niemals localhost.
Schritt 4: compose.yaml anlegen
Erstelle die Compose-Datei unter /opt/documenso/compose.yaml. Der healthcheck beim Datenbank-Service ist wichtig: Documenso wartet damit auf eine tatsächlich startbereite PostgreSQL-Instanz, bevor es mit Migrationen beginnt.
name: documenso
services:
database:
image: postgres:15
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- database:/var/lib/postgresql/data
documenso:
image: documenso/documenso:v2.11.0
restart: unless-stopped
depends_on:
database:
condition: service_healthy
ports:
- "${PORT:-3000}:${PORT:-3000}"
environment:
PORT: ${PORT:-3000}
# Datenbank
NEXT_PRIVATE_DATABASE_URL: ${NEXT_PRIVATE_DATABASE_URL}
# Auth & Verschlüsselung
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
NEXT_PRIVATE_ENCRYPTION_KEY: ${NEXT_PRIVATE_ENCRYPTION_KEY}
NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY: ${NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY}
# URLs
NEXT_PUBLIC_WEBAPP_URL: ${NEXT_PUBLIC_WEBAPP_URL}
NEXT_PRIVATE_INTERNAL_WEBAPP_URL: ${NEXT_PRIVATE_INTERNAL_WEBAPP_URL:-http://localhost:3000}
# E-Mail
NEXT_PRIVATE_SMTP_TRANSPORT: ${NEXT_PRIVATE_SMTP_TRANSPORT:-smtp-auth}
NEXT_PRIVATE_SMTP_HOST: ${NEXT_PRIVATE_SMTP_HOST}
NEXT_PRIVATE_SMTP_PORT: ${NEXT_PRIVATE_SMTP_PORT:-587}
NEXT_PRIVATE_SMTP_USERNAME: ${NEXT_PRIVATE_SMTP_USERNAME}
NEXT_PRIVATE_SMTP_PASSWORD: ${NEXT_PRIVATE_SMTP_PASSWORD}
NEXT_PRIVATE_SMTP_FROM_ADDRESS: ${NEXT_PRIVATE_SMTP_FROM_ADDRESS}
NEXT_PRIVATE_SMTP_FROM_NAME: ${NEXT_PRIVATE_SMTP_FROM_NAME:-Documenso}
# Signaturzertifikat
NEXT_PRIVATE_SIGNING_PASSPHRASE: ${NEXT_PRIVATE_SIGNING_PASSPHRASE}
# Telemetrie
DOCUMENSO_DISABLE_TELEMETRY: "true"
volumes:
- /opt/documenso/cert.p12:/opt/documenso/cert.p12:ro
volumes:
database:Verifizieren: docker compose -f /opt/documenso/compose.yaml config – Compose analysiert die Datei und zeigt die aufgelöste Konfiguration ohne Fehler an. Fehlende Pflicht-Variablen werden direkt als Fehler gemeldet.
Schritt 5: Stack starten und Migrationen abwarten
Starte den Stack aus dem Projektordner heraus:
cd /opt/documenso
docker compose up -dBeim ersten Start führt Documenso automatisch alle Datenbankmigrationen aus – das kann zwei bis drei Minuten dauern. Beobachte den Fortschritt live:
docker compose logs -f documensoDu wartest auf eine Ausgabe wie ready - started server on 0.0.0.0:3000. Sobald diese Zeile erscheint, ist die App bereit.
Verifizieren:
docker compose psErwartete Ausgabe (beide Container müssen laufen):
NAME IMAGE STATUS
documenso-database-1 postgres:15 Up X minutes (healthy)
documenso-documenso-1 documenso/documenso:v2.11.0 Up X minutesAnschließend Health-Check-Endpunkt prüfen:
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/api/healthErwartete Antwort: 200. Den Zertifikat-Status prüfst du mit:
curl -s http://localhost:3000/api/certificate-statusSchritt 6: Reverse Proxy und HTTPS einrichten
Für den Produktivbetrieb ist HTTPS Pflicht – NEXT_PUBLIC_WEBAPP_URL muss die https://-URL enthalten, sonst funktionieren Token-Links in E-Mails und OAuth-Callbacks nicht. Richte einen Reverse Proxy vor Documenso (Port 3000) ein. Empfohlen:
- Traefik: Labels am Documenso-Service ergänzen, Traefik übernimmt Let's-Encrypt-Zertifikate automatisch. Anleitung: Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten.
- Caddy: Eintrag in der Caddyfile:
sign.example.com { reverse_proxy documenso:3000 }. Anleitung: Caddy als Reverse Proxy einrichten. - Nginx Proxy Manager: Proxy-Host für Port 3000 anlegen, SSL via Let's Encrypt aktivieren.
Wichtig: Setze in der .env nach dem DNS-Eintrag und dem Reverse-Proxy-Setup die korrekte öffentliche URL und die interne URL für Hintergrund-Jobs:
NEXT_PUBLIC_WEBAPP_URL=https://sign.example.com
NEXT_PRIVATE_INTERNAL_WEBAPP_URL=http://localhost:3000Die interne URL muss auf localhost:3000 zeigen (nicht auf die öffentliche Domain), damit Hintergrund-Jobs den Reverse Proxy umgehen. Starte den Stack nach der Änderung neu:
docker compose up -d --force-recreate documensoVerifizieren: Rufe https://sign.example.com im Browser auf – du solltest die Documenso-Startseite mit gültigem TLS-Zertifikat sehen. curl -I https://sign.example.com/api/health gibt HTTP 200 zurück.
Schritt 7: Erst-Einrichtung im Browser und Registrierung sperren
Öffne https://sign.example.com und erstelle den ersten Admin-Account über das Registrierungsformular. Sichere Passwort und E-Mail-Adresse sorgfältig – über diesen Account verwaltest du später alle Teams und Einstellungen.
Nach dem ersten Login empfiehlt es sich, weitere Registrierungen zu sperren, wenn du Documenso nur für dein Team nutzen willst. Ergänze in der .env:
NEXT_PUBLIC_DISABLE_SIGNUP=trueAlternativ schränkst du die Registrierung auf bestimmte E-Mail-Domains ein:
NEXT_PRIVATE_ALLOWED_SIGNUP_DOMAINS=deinunternehmen.de,partner.deContainer neu starten, damit die Änderung wirksam wird:
docker compose up -d --force-recreate documensoVerifizieren: Logge dich als Admin ein und rufe https://sign.example.com/api/certificate-status im Browser auf. Die Antwort zeigt, ob das Signaturzertifikat korrekt geladen ist. Lade ein Test-PDF hoch, füge dich als Unterzeichner hinzu und prüfe, ob die Einladungsmail eintrifft.
Schritt 8: Updates und Datenbank-Backup
Documenso erscheint regelmäßig mit neuen Versionen. Prüfe vor jedem Update die Release-Notes auf Breaking Changes. Erstelle immer zuerst ein Datenbank-Backup:
# Backup erstellen
docker compose exec database pg_dump -U documenso documenso > /opt/documenso/backup_$(date +%Y%m%d).sql
# Image-Tag in compose.yaml auf neue Version anpassen, dann:
docker compose pull
docker compose up -dDatenbankmigrationen laufen automatisch beim Neustart. Überwache den Fortschritt mit docker compose logs -f documenso. Für eine strukturierte Backup-Strategie empfiehlt sich die Anleitung zu PostgreSQL pg_dump und pg_restore: Backup und Migration. Für automatische Update-Benachrichtigungen ohne blindes :latest-Pulling hilft die Anleitung zu Docker-Container automatisch aktualisieren.
Verifizieren: Nach dem Update docker compose ps – beide Container müssen mit dem neuen Image-Tag und Status Up laufen. curl -s http://localhost:3000/api/health gibt weiterhin HTTP 200 zurück. Im Browser zeigt die neue Versionsnummer in den Einstellungen den Erfolg.
Troubleshooting / Typische Fehler
- „Failed to get private key bags": Das
.p12-Zertifikat wurde ohne Passwort erstellt. Lösung: Zertifikat neu erstellen und dabei-passout pass:PASSWORTübergeben;NEXT_PRIVATE_SIGNING_PASSPHRASEin der.envsetzen. - EACCES permission denied beim Signieren: Der Container läuft als UID 1001 (non-root), hat aber keinen Lesezugriff auf
cert.p12. Lösung:sudo chown 1001:1001 /opt/documenso/cert.p12 && sudo chmod 400 /opt/documenso/cert.p12auf dem Host ausführen. - Signatur läuft durch, erzeugt aber keine gültige Unterschrift: Kein Zertifikat konfiguriert oder falsch gemountet – Documenso startet problemlos auch ohne Zertifikat. Diagnose:
/api/certificate-statusim Browser aufrufen. - Datenbankverbindung schlägt fehl – „connection refused":
NEXT_PRIVATE_DATABASE_URLverwendetlocalhoststatt dem Compose-Servicenamen. Lösung: URL-Hostname mussdatabaselauten – alsopostgresql://documenso:PASS@database:5432/documenso. - Token-Links in E-Mails sind falsch oder OAuth-Callback schlägt fehl:
NEXT_PUBLIC_WEBAPP_URList falsch gesetzt (z. B.http://statthttps://oder fehlender Port). Lösung: URL exakt so setzen, wie sie im Browser erreichbar ist. - Erster Start hängt oder läuft in Timeout: Datenbankmigrationen beim Erststart benötigen Zeit. Lösung:
depends_onmitcondition: service_healthyin der Compose-Datei sicherstellen unddocker compose logs -f documensoabwarten. - Hintergrund-Jobs (E-Mail-Versand) schlagen fehl:
NEXT_PRIVATE_INTERNAL_WEBAPP_URLzeigt auf die öffentliche Domain statt aufhttp://localhost:3000. Lösung: Variable auf die interne Container-URL setzen. - Breaking Changes nach Update: Verwendung von
:latest-Tag. Lösung: In dercompose.yamlimmer konkrete Versionstags wie:v2.11.0einsetzen und vor jedem Update die Release-Notes lesen.
Häufige Fragen
Benötige ich zwingend ein SSL-Zertifikat für den Betrieb?
Ja – für den Produktivbetrieb ist HTTPS Pflicht. HTTP reicht ausschließlich für lokale Tests. NEXT_PUBLIC_WEBAPP_URL muss die https://-URL enthalten, sonst funktionieren Token-Links in E-Mails, OAuth-Callbacks und viele sicherheitsrelevante Browser-Features nicht korrekt. Am einfachsten übernimmt ein vorgelagerter Reverse Proxy (Traefik, Caddy, Nginx) die TLS-Terminierung mit Let's-Encrypt-Zertifikaten.
Wie erstelle ich ein Signaturzertifikat (.p12) für rechtssichere Signaturen?
Für interne Zwecke oder fortgeschrittene elektronische Signaturen reicht ein selbstsigniertes OpenSSL-Zertifikat wie in Schritt 2 beschrieben. Für qualifizierte elektronische Signaturen (QES) nach eIDAS – die höchste Rechtsstufe, gleichwertig mit handschriftlicher Unterschrift – benötigst du ein Zertifikat von einer akkreditierten Vertrauensstelle (z. B. D-Trust, Bundesdruckerei). Diese Zertifikate sind kostenpflichtig und erfordern eine Identitätsprüfung.
Werden Dokumente in der Datenbank oder im Dateisystem gespeichert?
Standardmäßig in PostgreSQL (NEXT_PUBLIC_UPLOAD_TRANSPORT=database). Das ist für KMU mit moderatem Dokumentenaufkommen praktisch, da kein zusätzlicher Speicher-Service benötigt wird. Bei großen Dokumentenmengen empfiehlt sich S3-kompatible Speicherung (AWS S3, MinIO, Cloudflare R2) über die entsprechenden S3-Umgebungsvariablen.
Kann ich die Benutzerregistrierung deaktivieren?
Ja: NEXT_PUBLIC_DISABLE_SIGNUP=true sperrt alle Neuregistrierungen vollständig. Mit NEXT_PRIVATE_ALLOWED_SIGNUP_DOMAINS=deinunternehmen.de erlaubst du nur Registrierungen von bestimmten E-Mail-Domains. Bestehende Benutzerkonten sind von beiden Einstellungen nicht betroffen.
Benötigt Documenso Redis?
Nein. Redis ist optional. Der Standard-Jobs-Provider local nutzt PostgreSQL für die interne Jobqueue – ohne externe Abhängigkeiten. Redis (BullMQ-Provider) oder Inngest empfehlen sich erst bei sehr hohem Durchsatz oder wenn du eine verwaltete Job-Infrastruktur bevorzugst.
Kann ich Nicht-PDF-Dokumente (DOCX, ODT) hochladen?
Ja, wenn du einen Gotenberg-Container als zusätzlichen Service in den Stack einbindest und NEXT_PRIVATE_DOCUMENT_CONVERSION_URL=http://gotenberg:3000 setzt. Gotenberg konvertiert DOCX, ODT und weitere Formate serverseitig zu PDF, bevor Documenso sie verarbeitet.
Fazit
Documenso ist eine ausgereifte, aktiv gepflegte Alternative zu DocuSign, die sich mit überschaubarem Aufwand auf eigener Infrastruktur betreiben lässt. Der größte konzeptionelle Unterschied zu SaaS-Angeboten: Du trägst die Verantwortung für Betrieb, Backups und Updates selbst. Das zahlt sich aus, wenn DSGVO-Compliance ohne US-Datenverarbeitung für dich oder deine Kunden nicht verhandelbar ist. Die Pflicht-Komplexität liegt vor allem beim Signaturzertifikat (PKCS#12 mit Passwort) und der korrekten URL-Konfiguration – zwei Punkte, bei denen erfahrungsgemäß die meisten Fehler entstehen. Wer diese Stolpersteine kennt, hat eine zuverlässige, rechtssichere Signaturlösung auf dem eigenen Server, die mit dem Team wächst.
Weiterführende Anleitungen und Quellen
- Docker und Docker Compose auf Linux installieren – die Self-Hosting-Grundlage
- Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
- Caddy als Reverse Proxy einrichten: Anfänger-Anleitung mit automatischem HTTPS
- Docker-Container automatisch aktualisieren: Diun, WUD und Renovate im Vergleich
- Paperless-ngx mit Docker einrichten: papierlose Dokumentenverwaltung mit OCR
- Stirling-PDF mit Docker: der lokale PDF-Werkzeugkasten
- PostgreSQL pg_dump und pg_restore: Backup und Migration per Kommandozeile
Offizielle Quellen: Documenso Docs – Docker Compose Deployment · Environment Variables Reference · Tips und Common Pitfalls · GitHub Repository