Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Cloud / Hosting 26.06.2026 · 11 min Lesezeit

OpenSign mit Docker installieren: Kostenlose DocuSign-Alternative für rechtssichere E-Signaturen

OpenSign ist die quelloffene Alternative zu DocuSign und Adobe Sign – mit kryptografischen Audit-Trails, Multi-Party-Workflows und Templates. Diese Anleitung zeigt, wie du den kompletten Stack per Docker Compose in 20 Minuten auf deinem eigenen Server deployst.

OpenSign mit Docker installieren als kostenlose DocuSign Alternative für rechtssichere elektronische Signaturen mit Dokumenten Dashboard, Signatur Workflow, Audit Logs und persistenter Datenspeicherung.

Wer regelmäßig Verträge, NDAs oder Angebote digital unterzeichnen lässt, kennt das Problem: DocuSign kostet ab 10 EUR pro Nutzer und Monat, Adobe Sign noch mehr – und beide schicken deine Dokumente durch externe US-Server. OpenSign löst dieses Problem vollständig: Die AGPL-3.0-lizenzierte Plattform bringt rechtssichere elektronische Signaturen, kryptografische Audit-Trails, Multi-Party-Workflows und wiederverwendbare Templates auf deinen eigenen Server. 6.500 GitHub-Sterne und über 50.000 Docker-Hub-Pulls je Image zeigen, dass die Lösung produktionsreif ist. Diese Anleitung richtet sich an KMU-Administratoren, Kanzleien und ambitionierte Selfhoster, die per docker compose up -d eine vollständige DocuSign-Alternative betreiben wollen – DSGVO-konform, ohne Cloud-Abhängigkeit, mit echtem ROI ab dem ersten unterzeichneten Vertrag.

Voraussetzungen

  1. Linux-Host, VM oder NAS mit Docker Engine und Docker Compose v2 (Plugin, nicht das veraltete docker-compose Binary) – Installations-Grundlage: Docker und Docker Compose auf Linux installieren
  2. Mindestens 2 GB RAM und 4 GB freier Speicherplatz (Frontend-Image 707 MB, Backend-Image 1,3 GB, MongoDB)
  3. Internetverbindung für den einmaligen Image-Download (ca. 2,5 GB gesamt)
  4. Optional: eigene Domain mit DNS-Verwaltungszugang (für HTTPS mit Let's Encrypt via Caddy); ohne Domain läuft alles unter https://localhost:3001
  5. Optional: SMTP-Postfach oder Mailgun-Account für E-Mail-Benachrichtigungen (Signatur-Einladungen)
  6. Optional: kommerzielles AATL-Zertifikat (PFX/P12) für Adobe-Acrobat-vertrauenswürdige Signaturen

Schritt 1: Eckdaten und Stack-Überblick

Bevor du den Stack startest, hilft ein Blick auf die beteiligten Images, Ports und Volumes. So verstehst du, warum jede Konfigurationsentscheidung wichtig ist.

KomponenteImageGrößeFunktion
Frontendopensign/opensign:main707 MBReact-UI, Signatur-Oberfläche
Backendopensign/opensignserver:main1,3 GBNode.js / Parse Server API
Datenbankmongo:latest~700 MBDokumente, Nutzer, Audit-Trails
Reverse Proxycaddy:latest~50 MBAuto-TLS, HTTPS-Termination
Port (Host)ContainerZweckÖffentlich?
3001CaddyHaupt-Zugangspunkt HTTPSJa (über Caddy)
80 / 443CaddyHTTP-Redirect / HTTPS + HTTP/3Ja (Custom Domain)
3000FrontendReact internNur intern
8080BackendNode.js APINiemals extern!
27018MongoDBDB-Zugriff (Host-Port)Niemals extern!
VolumeZweckKritisch?
data-volume:/data/dbMongoDB-Daten (Dokumente, Signaturen)Ja – ohne Volume Datenverlust!
opensign-files:/usr/src/app/filesLokaler PDF-Speicher (USE_LOCAL=true)Ja
caddy_data:/dataTLS-Zertifikate (Let's Encrypt)Empfohlen
caddy_config:/configCaddy-interne KonfigurationEmpfohlen

Verifizieren: Dieser Schritt erfordert keine Befehle. Merke dir: MongoDB-Port 27018 darf niemals in einer Firewall für das Internet geöffnet werden, da keine Authentifizierung konfiguriert ist.

Schritt 2: Projektordner anlegen und Konfigurationsdateien herunterladen

Lege einen dedizierten Ordner für den OpenSign-Stack an. Alle Konfigurationsdateien müssen sich im selben Verzeichnis befinden, weil Caddy die Caddyfile als relativen Bind-Mount einbindet.

mkdir -p /opt/opensign
cd /opt/opensign

# compose.yaml und Caddyfile aus dem offiziellen GitHub-Repo herunterladen
curl -fsSL https://raw.githubusercontent.com/OpenSignLabs/OpenSign/main/compose.yaml \
  -o compose.yaml

curl -fsSL https://raw.githubusercontent.com/OpenSignLabs/OpenSign/main/Caddyfile \
  -o Caddyfile

Verifizieren:

ls -la /opt/opensign/
# Erwartet: compose.yaml  Caddyfile (beide nicht leer)
wc -l compose.yaml
# Erwartet: mehr als 30 Zeilen

Fehlt die Caddyfile, startet Caddy zwar, aber OpenSign ist nicht erreichbar.

Schritt 3: Umgebungsvariablen konfigurieren (.env.prod)

Die gesamte Konfiguration – Secrets, URLs, E-Mail – landet in einer .env.prod-Datei. Ändere vor dem ersten Start unbedingt MASTER_KEY und PASS_PHRASE: Der Standard-MASTER_KEY (XnAadwKxxByMr) ist öffentlich bekannt und gibt vollen Datenbankzugriff.

Einen sicheren MASTER_KEY erzeugst du schnell per:

openssl rand -hex 20
# Ausgabe-Beispiel: a3f8c2d1e9b047561234abcd5678ef90abcd1234
# /opt/opensign/.env.prod
# =============================================
# PFLICHT-Einstellungen
# =============================================

# Öffentliche URL – bei Custom Domain anpassen (z. B. https://sign.example.com)
PUBLIC_URL=https://localhost:3001

# API-Endpunkt für das React-Frontend (intern – NICHT auf Public-URL ändern)
REACT_APP_SERVERURL=http://localhost:8080/app

# App-Identifier
REACT_APP_APPID=opensign
APP_ID=opensign

# MongoDB-Verbindung (Container-Name aus compose.yaml)
MONGODB_URI=mongodb://mongo-container:27017/OpenSignDB

# Interne API-URL
SERVER_URL=http://127.0.0.1:8080/app

# API-Mount-Pfad
PARSE_MOUNT=/app

# =============================================
# SECRETS – UNBEDINGT ÄNDERN!
# =============================================
MASTER_KEY=DEIN_SICHERER_MASTER_KEY_HIER
PASS_PHRASE=DEINE_SICHERE_PASSPHRASE_HIER

# =============================================
# Dateispeicher
# =============================================
USE_LOCAL=true

# =============================================
# E-Mail (optional, aber für Produktion nötig)
# =============================================
SMTP_ENABLE=false
SMTP_HOST=smtp.yourhost.com
SMTP_PORT=587
SMTP_USER_EMAIL=mailer@yourdomain.com
SMTP_PASS=SMTP_PASSWORT_HIER

# =============================================
# Performance
# =============================================
GENERATE_SOURCEMAP=false

Verifizieren:

grep "XnAadwKxxByMr" /opt/opensign/.env.prod
# Muss leer zurückkommen – sonst Standard-Secret noch aktiv!

Schritt 4: compose.yaml prüfen und ggf. anpassen

Die heruntergeladene compose.yaml ist lauffähig und referenziert deine .env.prod per env_file-Direktive. Für Localhost-Betrieb sind keine weiteren Änderungen nötig. Bei Custom-Domain-Betrieb setzt du HOST_URL in einer zusätzlichen .env-Datei:

# Nur für Custom-Domain-Betrieb:
echo "HOST_URL=https://sign.example.com" > /opt/opensign/.env

Die vollständige compose.yaml zur Referenz:

services:
  mongo:
    image: mongo:latest
    container_name: mongo-container
    restart: unless-stopped
    volumes:
      - data-volume:/data/db
    ports:
      - "27018:27017"
    networks:
      - app-network

  server:
    image: opensign/opensignserver:main
    container_name: OpenSignServer-container
    restart: unless-stopped
    depends_on:
      - mongo
    volumes:
      - opensign-files:/usr/src/app/files
    ports:
      - "8080:8080"
    env_file: .env.prod
    environment:
      - NODE_ENV=production
      - SERVER_URL=${HOST_URL:-https://localhost:3001}/api/app
      - PUBLIC_URL=${HOST_URL:-https://localhost:3001}
    networks:
      - app-network

  client:
    image: opensign/opensign:main
    container_name: OpenSign-container
    restart: unless-stopped
    depends_on:
      - server
    ports:
      - "3000:3000"
    env_file: .env.prod
    networks:
      - app-network

  caddy:
    image: caddy:latest
    container_name: caddy-container
    restart: unless-stopped
    ports:
      - "3001:3001"
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    environment:
      - HOST_URL=${HOST_URL:-localhost:3001}
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

volumes:
  data-volume:
  opensign-files:
  caddy_data:
  caddy_config:

Wichtig: Das Image-Tag main ist kein stabiler Release-Tag und kann Breaking Changes enthalten. Für Produktivbetrieb empfiehlt sich ein versioniertes Tag (z. B. opensign/opensign:v2.39.0). Mehr zur Strategie in der Anleitung Docker-Container automatisch aktualisieren: Diun, WUD und Renovate im Vergleich.

Verifizieren:

docker compose -f /opt/opensign/compose.yaml config
# Muss die vollständige interpolierte Konfiguration ohne Fehler ausgeben

Schritt 5: Stack starten und Images ziehen

Jetzt startest du alle vier Container. Beim ersten Start werden die Images heruntergeladen (ca. 2,5 GB); das kann einige Minuten dauern.

cd /opt/opensign
docker compose pull        # Images vorab ziehen (empfohlen)
docker compose up -d       # Alle Container im Hintergrund starten

Verfolge den Start-Fortschritt mit:

docker compose logs -f server
# Warte auf: "Parse LiveQuery Server started" oder "Listening on port 8080"

Verifizieren:

docker compose ps

# Erwartete Ausgabe (alle 4 Container "Up"):
# NAME                        IMAGE                          STATUS
# OpenSign-container          opensign/opensign:main         Up
# OpenSignServer-container    opensign/opensignserver:main   Up
# caddy-container             caddy:latest                   Up
# mongo-container             mongo:latest                   Up

Zeigt ein Container Restarting oder Exit, prüfe: docker compose logs server. Häufigste Ursache: falscher MASTER_KEY oder MONGODB_URI in der .env.prod.

Schritt 6: Erstzugang im Browser und Admin-Account anlegen

Öffne im Browser https://localhost:3001. Da Caddy bei Localhost-Betrieb ein selbstsigniertes Zertifikat verwendet, zeigt Chrome oder Firefox eine Sicherheitswarnung. Klicke auf „Erweitert" → „Weiter zu localhost" – das ist normal und einmalig nötig.

Auf der OpenSign-Startseite:

  1. Klicke auf „Sign Up" und lege deinen Admin-Account an.
  2. Bestätige die E-Mail-Adresse (nur wenn E-Mail-Versand konfiguriert ist; andernfalls direkt einloggen).
  3. Lade ein Test-PDF hoch, füge ein Signaturfeld hinzu und sende die Signaturanfrage an dich selbst.
  4. Überprüfe nach der Signatur, dass das fertige PDF einen Audit-Trail enthält (Download → PDF-Eigenschaften im Viewer).

Verifizieren:

# Erreichbarkeit prüfen (erwartet: HTTP/2 200 oder 302)
curl -k -I https://localhost:3001

# API-Endpunkt prüfen (erwartet: JSON-Antwort des Parse Servers)
curl -s http://localhost:8080/app/health | head -c 200

Schritt 7: HTTPS mit eigener Domain einrichten (Caddy + Let's Encrypt)

Für Custom-Domain-Betrieb (z. B. sign.example.com) werden drei Voraussetzungen benötigt: DNS-A-Record auf die Server-IP, Ports 80 und 443 in der Firewall freigegeben, und HOST_URL gesetzt. Einen soliden Einstieg gibt es in der Anleitung Caddy als Reverse Proxy einrichten: Anfänger-Anleitung mit automatischem HTTPS.

cd /opt/opensign

# HOST_URL setzen
echo "HOST_URL=https://sign.example.com" > .env

# PUBLIC_URL in .env.prod ebenfalls anpassen:
# PUBLIC_URL=https://sign.example.com
# (REACT_APP_SERVERURL bleibt auf http://localhost:8080/app – intern!)

docker compose down
docker compose up -d

Caddy bezieht automatisch ein Let's-Encrypt-Zertifikat, sobald DNS korrekt gesetzt ist und Port 80/443 erreichbar sind.

Verifizieren:

curl -I https://sign.example.com
# Erwartet: HTTP/2 200, kein Zertifikatsfehler

docker compose logs caddy | grep -i "tls\|cert\|error"

Schritt 8: E-Mail konfigurieren (SMTP oder Mailgun)

Ohne funktionierende E-Mail-Konfiguration startet OpenSign fehlerfrei – aber Unterzeichner erhalten nie eine Einladungs-E-Mail. Für Produktivbetrieb ist dieser Schritt unverzichtbar. Passe deine .env.prod an:

# Option A: SMTP (empfohlen für IONOS, Hetzner Mail, eigenen Postfix)
SMTP_ENABLE=true
SMTP_HOST=smtp.ionos.de
SMTP_PORT=587
SMTP_USER_EMAIL=noreply@example.com
SMTP_PASS=DEIN_SICHERES_SMTP_PASSWORT

# Option B: Mailgun
# SMTP_ENABLE=false
# MAILGUN_API_KEY=key-xxxxxxxxxxxxx
# MAILGUN_DOMAIN=mg.example.com
# MAILGUN_SENDER=noreply@example.com

Nach der Änderung an .env.prod die betroffenen Container neu starten:

cd /opt/opensign
docker compose up -d --force-recreate server client

Hinweis zu Gmail: Gmail erfordert ein App-Passwort, kein normales Konto-Passwort. SMTP_PORT=587 mit STARTTLS ist der korrekte Wert. Der in einigen Quellen genannte Port 443 ist für SMTP unüblich – verwende immer den tatsächlichen Port deines Mail-Providers.

Verifizieren: Sende eine Test-Signaturanfrage an eine echte E-Mail-Adresse. Bei Problemen: docker compose logs server | grep -i "mail\|smtp\|error".

Schritt 9: Signaturzertifikat (PFX) einrichten

Für kryptografisch eingebettete PDF-Signaturen benötigst du ein PFX/P12-Zertifikat als Base64-Wert. Ein selbst erzeugtes Zertifikat reicht für interne Zwecke; für AATL-konforme Signaturen (Adobe Acrobat zeigt „vertrauenswürdig") ist ein kommerzielles Zertifikat nötig.

# Schlüssel und Zertifikat erzeugen
openssl genrsa -out private.key 2048
openssl req -new -key private.key -out cert.csr \
  -subj "/CN=OpenSign/O=MeinUnternehmen/C=DE"
openssl x509 -req -days 3650 -in cert.csr \
  -signkey private.key -out certificate.crt

# PFX-Datei erzeugen
openssl pkcs12 -export -out certificate.pfx \
  -inkey private.key -in certificate.crt \
  -passout pass:DEINE_PASSPHRASE

# Base64-Wert für .env.prod erzeugen
base64 -w 0 certificate.pfx

Den Ausgabe-String in .env.prod eintragen:

PFX_BASE64=<langer-base64-string>
PASS_PHRASE=DEINE_PASSPHRASE

Verifizieren: Nach docker compose up -d --force-recreate server prüfen: docker compose logs server | grep -i "pfx\|cert\|sign". Testdokument hochladen, signieren, Signatur-Badge im PDF-Viewer prüfen.

Schritt 10: Backup und Updates

Für eine solide Backup-Strategie empfiehlt sich die Anleitung 3-2-1-Backup-Strategie umsetzen: Anleitung mit Restic, USB-Disk und S3-Cloud. Für OpenSign konkret:

# MongoDB-Daten sichern (laufender Container)
docker exec mongo-container mongodump \
  --db OpenSignDB \
  --out /tmp/opensign-backup-$(date +%F)

docker cp mongo-container:/tmp/opensign-backup-$(date +%F) \
  /opt/backups/opensign/

# Update einspielen
cd /opt/opensign
docker compose pull
docker compose up -d

Kritisch: Führe niemals docker compose down -v im Produktivbetrieb aus. Das Flag -v löscht alle benannten Volumes – Dokumente, Nutzer und Signaturen sind dann unwiederbringlich verloren.

Verifizieren: Nach dem Update prüft docker compose ps alle vier Container auf Status Up. Browser-Oberfläche öffnen und prüfen, dass bestehende Dokumente noch vorhanden sind.

Troubleshooting / Typische Fehler

  1. Container server startet immer wieder neu (Restarting): Verbindungsfehler zur MongoDB. Prüfe: docker compose logs server | grep "MongoServerError\|ECONNREFUSED". Stelle sicher, dass MONGODB_URI=mongodb://mongo-container:27017/OpenSignDB korrekt ist und der Container-Name übereinstimmt.
  2. Browser-Warnung „Verbindung nicht sicher": Bei Localhost-Betrieb normal. Klicke auf „Erweitert" → „Weiter zu localhost (unsicher)". Das selbstsignierte Caddy-Zertifikat für Localhost löst diese Warnung immer aus – einmalig akzeptieren.
  3. Signaturanfragen kommen nie an: E-Mail nicht konfiguriert oder SMTP-Credentials falsch. Prüfe: docker compose logs server | grep -i "mail\|smtp\|error".
  4. Frontend zeigt „Cannot connect to server": REACT_APP_SERVERURL ist auf einen externen URL gesetzt. Der interne Wert muss http://localhost:8080/app bleiben. Externe URL nur für SERVER_URL im server-Container via HOST_URL setzen.
  5. Caddy startet, aber Port 3001 nicht erreichbar: Caddyfile fehlt oder liegt nicht im selben Verzeichnis wie compose.yaml. Prüfe: docker compose logs caddy | grep -i "error\|caddyfile".
  6. PDF-Signatur in Adobe Acrobat als „nicht vertrauenswürdig": Selbst generierte Zertifikate sind nicht in der Adobe Approved Trust List (AATL). Für AATL-Compliance ist ein kommerzielles Zertifikat nötig. Für interne Zwecke ist der Audit-Trail dennoch kryptografisch gültig.
  7. Breaking Changes nach docker compose pull: Das main-Tag ist kein stabiler Release. Pinne auf versionierte Tags (z. B. v2.39.0) in der compose.yaml und aktualisiere bewusst.
  8. CORS-Fehler beim Hochladen (S3/DO Spaces): Nur bei USE_LOCAL=false. Am Storage-Bucket eine CORS-Regel konfigurieren, die den OpenSign-Hostnamen als Origin erlaubt.

Häufige Fragen

Ist OpenSign DSGVO-konform?

Ja – beim Self-hosting bleiben alle Daten (Dokumente, Signaturen, personenbezogene Daten der Unterzeichner) ausschließlich auf deinem Server. Es werden keine Daten an externe Dienste übertragen, solange kein Cloud-Storage konfiguriert ist. Eine Datenschutzerklärung und Auftragsverarbeitungsverträge für E-Mail-Dienstleister sind dennoch erforderlich.

Kann ich OpenSign ohne eigene Domain lokal oder im Heimnetz betreiben?

Ja. Ohne HOST_URL ist die App unter https://localhost:3001 erreichbar. Für LAN-Zugriff setze HOST_URL=https://192.168.1.100 (eigene Server-IP) und akzeptiere das selbstsignierte Zertifikat im Browser einmalig. Eine öffentliche Domain ist nur für Let's-Encrypt-HTTPS zwingend nötig.

Wie erzeuge ich das PFX-Zertifikat für PFX_BASE64?

Schritt für Schritt per OpenSSL: (1) openssl genrsa -out private.key 2048, (2) openssl req -new -key private.key -out cert.csr, (3) openssl x509 -req -days 3650 -in cert.csr -signkey private.key -out certificate.crt, (4) openssl pkcs12 -export -out certificate.pfx -inkey private.key -in certificate.crt, (5) base64 -w 0 certificate.pfx liefert den Wert für PFX_BASE64. Das erzeugte Zertifikat ist nicht AATL-zertifiziert; für Acrobat-vertrauenswürdige Signaturen benötigst du ein kommerzielles Zertifikat.

Wie spiele ich Updates ein?

docker compose pull zieht neue Images; anschließend docker compose up -d startet die Container neu. MongoDB-Daten bleiben durch das persistente Volume erhalten. Erstelle vor jedem Update ein Mongodump-Backup und pin nach Möglichkeit auf versionierte Image-Tags.

Kann OpenSign eine externe MongoDB-Instanz verwenden?

Ja. Setze MONGODB_URI in .env.prod auf den externen Connection-String (z. B. mongodb+srv://user:pass@cluster.mongodb.net/OpenSignDB) und entferne den mongo-Service aus der compose.yaml.

Welche SMTP-Anbieter funktionieren?

Jeder SMTP-kompatible Anbieter: IONOS, Strato, Hetzner Mail, eigener Postfix-Server. Gmail erfordert ein App-Passwort. Port 587 mit STARTTLS ist der Standardwert; der in der offiziellen Vorlage gezeigte Port 443 ist unüblich – verwende immer den tatsächlichen Port deines Providers.

Sind die Signaturen eIDAS-konform?

OpenSign erzeugt elektronische Signaturen mit kryptografischem Audit-Trail, die als „einfache elektronische Signaturen" im Sinne der eIDAS-Verordnung gelten. Für den Großteil geschäftlicher Verträge (NDAs, Angebote, Dienstleistungsverträge) ist das rechtlich ausreichend. Für qualifizierte elektronische Signaturen (QES) – erforderlich z. B. für notarielle Akte – ist ein zugelassener Vertrauensdiensteanbieter nötig.

Fazit

OpenSign ist eine ausgereifte, produktionstaugliche Alternative zu DocuSign und Adobe Sign. Der Docker-Stack aus vier Containern ist in 20 Minuten betriebsbereit, und der ROI ist ab dem ersten Tag positiv – verglichen mit SaaS-Kosten ab 10 EUR pro Nutzer und Monat. Die wichtigsten Punkte für den sicheren Betrieb: MASTER_KEY vor dem ersten Start ändern, MongoDB-Port niemals ins Internet exponieren, das persistente Volume niemals mit -v löschen und E-Mail für Signatur-Einladungen konfigurieren. Wer auch Dokumentenverwaltung und OCR-Archivierung benötigt, findet in Paperless-ngx mit Docker einrichten die perfekte Ergänzung.

Weiterführende Anleitungen und Quellen

  1. Caddy als Reverse Proxy einrichten: Anfänger-Anleitung mit automatischem HTTPS
  2. Docker und Docker Compose auf Linux installieren (Ubuntu/Debian): die Self-Hosting-Grundlage
  3. Paperless-ngx mit Docker einrichten: papierlose Dokumentenverwaltung mit deutscher OCR
  4. Stirling-PDF mit Docker: der lokale PDF-Werkzeugkasten
  5. Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only für den Produktivbetrieb

Offizielle Quellen: OpenSign Self-Hosting-Dokumentation | OpenSign GitHub Repository | OpenSign ENV-Variablen-Referenz

Passende Anleitungen auf S-EDV

  1. OpenSSL: Neun Schwachstellen im Sicherheitsrelease vom 9. Juni 2026, darunter Hi
  2. netcup Local Block Storage bestellen, einrichten und unter Linux einbinden
  3. Linux-Kernel CVE-2026-23111: Ein-Zeichen-Fehler in nf_tables ermöglicht lokale R