Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Cloud / Hosting 26.06.2026 · 10 min Lesezeit Geprüft 14.10.2026

OpenSign mit Docker installieren: E-Signaturen selbst hosten

OpenSign selbst hosten: Docker-Compose-Stack mit Caddy und MongoDB, eigene Secrets, keine offenen Datenbankports, HTTPS, SMTP, Signaturzertifikat, Backup und Updates, dazu die Grenzen einfacher E-Signaturen.

Werbung Mit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Titelbild: OpenSign mit Docker installieren, Signieren, Vorlagen, Nachweis

OpenSign ist eine quelloffene Plattform für elektronische Signaturen (Lizenz AGPL-3.0) mit Audit-Trail, Workflows für mehrere Unterzeichner und Vorlagen. Selbst gehostet bleiben Dokumente und Unterzeichnerdaten auf Ihrem Server. Diese Anleitung richtet sich an Administratoren in KMU und Kanzleien und führt Sie vom Docker-Compose-Stack über HTTPS und E-Mail bis zu Signaturzertifikat, Backup und Updates.

Voraussetzungen

  • Linux-Server oder VM mit Docker Engine und dem Compose-Plugin v2, siehe Docker und Docker Compose auf Linux installieren
  • Mindestens 2 GB RAM und 10 GB freier Speicher für Images, Datenbank und Dokumente
  • Für HTTPS mit Let's Encrypt: eigene Domain mit A-Record auf den Server, Ports 80 und 443 erreichbar
  • SMTP-Postfach für Signatur-Einladungen
  • Linux-Kernel passend zu MongoDB 8.0: Prüfen Sie mit uname -r die Kernel-Version des Hosts. Auf Ubuntu zeigt uname -r nur 7.0.0-…, die zugrunde liegende Upstream-Version nennt cat /proc/version_signature. Unter 6.19 läuft mongo:8.0 ohne Einschränkung. Von 6.19 bis 7.0.13 beendet sich MongoDB 8.0 beim Start mit „MongoDB cannot start: Linux kernel versions 6.19 and newer has a known incompatibility“ (SERVER-121912). Ab Kernel 7.0.14 beziehungsweise 7.1 startet MongoDB ab 8.0.30 wieder (Kompatibilitätstabelle in SERVER-125742). Ubuntu-Kernel der Reihe 7.0.0-… erkennt die Startprüfung bis einschließlich 8.0.34 nicht als korrigiert (SERVER-136848), die Ausnahme ist laut SERVER-131779 in 8.0.35 enthalten. Auf einem betroffenen Host tragen Sie bei einer Neuinstallation in der docker-compose.yml mongo:7.0 ein (Support laut MongoDB bis 31.08.2027). Vorhandene 8.0-Daten lassen sich nicht direkt mit 7.0 öffnen, weil MongoDB Community Edition kein Binär-Downgrade unterstützt.
  • Optional: Signaturzertifikat im Format PFX/P12; für Signaturen, die Adobe Acrobat als vertrauenswürdig anzeigt, ein Zertifikat aus der Adobe Approved Trust List (AATL)

Schritt 1: Eckdaten und Stack-Überblick

KomponenteImageFunktion
Frontendopensign/opensignReact-Oberfläche
Backendopensign/opensignserverNode.js / Parse Server API
Datenbankmongo:8.0Dokumente, Nutzer, Audit-Trails
Reverse Proxycaddy:2.11TLS, Weiterleitung an Frontend und /api
Port (Host)ContainerZweckÖffentlich?
3001CaddyZugang ohne eigene DomainNur intern bzw. per Firewall begrenzt
80 / 443CaddyHTTP-Weiterleitung, HTTPS mit eigener DomainJa
3000, 8080, 27017Frontend, Backend, MongoDBnur im Docker-NetzNein, kein Host-Port
VolumeZweckKritisch?
data-volume:/data/dbMongoDB-DatenJa
opensign-files:/usr/src/app/filesPDF-Dateien bei USE_LOCAL=trueJa
caddy_data:/dataTLS-ZertifikateEmpfohlen
caddy_config:/configCaddy-KonfigurationEmpfohlen

docker compose version meldet Version 2.x. MongoDB läuft im Stack ohne Authentifizierung; ihr Port darf deshalb nie auf dem Host veröffentlicht werden.

Schritt 2: Projektordner anlegen und Konfigurationsdateien herunterladen

docker-compose.yml und Caddyfile müssen im selben Verzeichnis liegen, weil Caddy die Datei relativ einbindet.

sudo mkdir -p /opt/opensign && cd /opt/opensign

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

ls -l /opt/opensign zeigt beide Dateien mit einer Größe über 0 Byte; head -3 Caddyfile beginnt mit {$HOST_URL} {. Bricht curl mit 404 ab, hat sich der Dateiname im Repository geändert; prüfen Sie die aktuelle Self-Hosting-Dokumentation.

Schritt 3: Umgebungsvariablen konfigurieren (.env.prod)

Secrets, URLs und E-Mail stehen in .env.prod. Die Beispielkonfiguration im Repository enthält einen öffentlich bekannten MASTER_KEY (XnAadwKxxByMr); er erlaubt vollen Zugriff auf die Parse-API. Erzeugen Sie eigene Werte:

$ openssl rand -hex 20   # fuer MASTER_KEY
$ openssl rand -hex 20   # fuer PASS_PHRASE

Legen Sie /opt/opensign/.env.prod an:

# Oeffentliche URL (bei eigener Domain: https://sign.example.com)
PUBLIC_URL=https://localhost:3001
APP_ID=opensign
REACT_APP_APPID=opensign

# MongoDB im Docker-Netz (Service-Name aus docker-compose.yml)
MONGODB_URI=mongodb://mongo:27017/OpenSignDB
SERVER_URL=http://127.0.0.1:8080/app
PARSE_MOUNT=/app

# Secrets: eigene Werte eintragen
MASTER_KEY=IHR_MASTER_KEY
PASS_PHRASE=IHRE_PASSPHRASE

USE_LOCAL=true
GENERATE_SOURCEMAP=false

# E-Mail (Schritt 8)
SMTP_ENABLE=false
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER_EMAIL=noreply@example.com
SMTP_PASS=IHR_SMTP_PASSWORT
$ sudo chmod 600 /opt/opensign/.env.prod

grep -c XnAadwKxxByMr /opt/opensign/.env.prod gibt 0 aus.

Schritt 4: docker-compose.yml prüfen und anpassen

Die Vorlage veröffentlicht MongoDB (27018), Backend (8080) und Frontend (3000) auf allen Host-Interfaces und nutzt die Tags latest bzw. main. Passen Sie die Datei so an: Host-Ports nur noch für Caddy, feste Versionen für MongoDB und Caddy, Neustart-Richtlinie für alle Dienste.

services:
  server:
    image: opensign/opensignserver:main   # nach dem ersten Pull per Digest fixieren
    container_name: OpenSignServer-container
    restart: unless-stopped
    volumes:
      - opensign-files:/usr/src/app/files
    depends_on:
      - mongo
    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
  mongo:
    image: mongo:8.0
    container_name: mongo-container
    restart: unless-stopped
    volumes:
      - data-volume:/data/db
    networks:
      - app-network
  client:
    image: opensign/opensign:main         # nach dem ersten Pull per Digest fixieren
    container_name: OpenSign-container
    restart: unless-stopped
    depends_on:
      - server
    env_file: .env.prod
    networks:
      - app-network
  caddy:
    image: caddy:2.11
    container_name: caddy-container
    restart: unless-stopped
    ports:
      - "3001:3001"
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - 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:

OpenSign veröffentlicht auf Docker Hub nur die Tags main, staging und docker_beta, keine Versionsnummern. Fixieren Sie deshalb nach dem ersten Pull den Digest: docker image inspect --format '{{index .RepoDigests 0}}' opensign/opensign:main liefert opensign/opensign@sha256:…; tragen Sie diesen Wert (ebenso für opensignserver) als image: ein. Updates übernehmen Sie dann bewusst, siehe Docker-Container aktualisieren: Diun, WUD und Renovate.

docker compose config --quiet endet ohne Ausgabe; docker compose config | grep -A2 ports zeigt Ports nur beim Dienst caddy.

Schritt 5: Stack starten und Images ziehen

$ cd /opt/opensign
$ sudo docker compose pull
$ sudo docker compose up -d
$ sudo docker compose logs -f server   # Abbruch mit Strg+C

sudo docker compose ps zeigt alle vier Container mit Status Up; sudo ss -tlnp | grep -E ':(3000|8080|27017|27018)\b' liefert keine Zeile. Zeigt ein Container Restarting, prüfen Sie docker compose logs server; häufige Ursache ist eine falsche MONGODB_URI.

Schritt 6: Erstzugang im Browser und Admin-Account anlegen

Öffnen Sie https://localhost:3001 (bzw. per SSH-Tunnel vom Arbeitsplatz). Caddy verwendet ohne Domain ein Zertifikat seiner lokalen CA; der Browser warnt deshalb einmalig.

  1. Über „Sign Up“ das erste Konto anlegen; es wird Administrator.
  2. Ein Test-PDF hochladen, ein Signaturfeld setzen und die Anfrage an sich selbst senden.
  3. Nach der Signatur das fertige PDF herunterladen und den angehängten Audit-Trail prüfen.
$ curl -k -s -o /dev/null -w '%{http_code}\n' https://localhost:3001            # 200
$ curl -k -s https://localhost:3001/api/app/health                               # {"status":"ok"}

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

Voraussetzungen: A-Record auf die Server-IP, Ports 80 und 443 offen. Grundlagen zu Caddy: Caddy als Reverse Proxy mit automatischem HTTPS.

$ cd /opt/opensign
$ echo "HOST_URL=https://sign.example.com" | sudo tee .env
$ sudo sed -i 's|^PUBLIC_URL=.*|PUBLIC_URL=https://sign.example.com|' .env.prod
$ sudo docker compose up -d --force-recreate

Mit eigener Domain entfernen Sie anschließend den Host-Port 3001 aus dem Dienst caddy oder sperren ihn in der Firewall.

curl -sI https://sign.example.com liefert HTTP/2 200 ohne Zertifikatsfehler; docker compose logs caddy | grep -i "certificate obtained" zeigt die Ausstellung.

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

Ohne E-Mail startet OpenSign, Unterzeichner erhalten aber keine Einladung. Tragen Sie in .env.prod ein:

SMTP_ENABLE=true
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER_EMAIL=noreply@example.com
SMTP_PASS=IHR_SMTP_PASSWORT

# Alternativ Mailgun:
# MAILGUN_API_KEY=...
# MAILGUN_DOMAIN=mg.example.com
# MAILGUN_SENDER=noreply@example.com
$ sudo docker compose up -d --force-recreate server client

Verwenden Sie den Port Ihres Anbieters, meist 587 (STARTTLS); die Beispieldatei im Repository nennt 443, das ist für SMTP unüblich. Google-Konten verlangen ein App-Passwort.

Eine Signaturanfrage an eine externe Adresse kommt an; bei Fehlern zeigt docker compose logs server | grep -iE "mail|smtp" die Ursache.

Schritt 9: Signaturzertifikat (PFX) einrichten

OpenSign bettet die Signatur mit einem PFX-Zertifikat in das PDF ein. Ein selbst erzeugtes Zertifikat genügt für interne Zwecke; Adobe Acrobat zeigt es als „nicht vertrauenswürdig“ an.

openssl req -x509 -newkey rsa:3072 -nodes -days 1825 \
  -keyout private.key -out certificate.crt \
  -subj "/CN=OpenSign/O=Ihr Unternehmen/C=DE"
openssl pkcs12 -export -out certificate.pfx \
  -inkey private.key -in certificate.crt   # fragt die Export-Passphrase ab
base64 -w 0 certificate.pfx > certificate.b64
shred -u private.key

Tragen Sie in .env.prod PFX_BASE64= mit dem Inhalt von certificate.b64 und als PASS_PHRASE die Export-Passphrase ein. Bewahren Sie certificate.pfx getrennt vom Server sicher auf.

Nach docker compose up -d --force-recreate server ein Testdokument signieren; der PDF-Viewer zeigt im Signaturbereich das Zertifikat mit CN=OpenSign.

Schritt 10: Backup und Updates

Sichern Sie Datenbank und Dateien, bevor Sie aktualisieren. Die übergeordnete Strategie beschreibt 3-2-1-Backup-Strategie praktisch umsetzen.

cd /opt/opensign
D=$(date +%F)
sudo mkdir -p /opt/backups/opensign
sudo docker compose exec -T mongo mongodump --db OpenSignDB --archive --gzip \
  | sudo tee /opt/backups/opensign/opensign-$D.archive.gz >/dev/null
sudo docker run --rm -v opensign_opensign-files:/src:ro -v /opt/backups/opensign:/dst \
  alpine:3.22 tar czf /dst/files-$D.tar.gz -C /src .

Für ein Update tragen Sie neue Digests bzw. Versionen in docker-compose.yml ein und führen sudo docker compose pull && sudo docker compose up -d aus. Der Volume-Name opensign_opensign-files setzt den Projektordner opensign voraus; docker volume ls zeigt den tatsächlichen Namen.

Achtung: docker compose down -v löscht alle benannten Volumes und damit sämtliche Dokumente und Signaturen.

gunzip -t /opt/backups/opensign/opensign-$D.archive.gz meldet keinen Fehler; nach dem Update zeigt docker compose ps alle Container Up und bestehende Dokumente sind in der Oberfläche vorhanden.

Troubleshooting / Typische Fehler

Container server startet neu (Restarting)

MongoDB nicht erreichbar. docker compose logs server | grep -E "MongoServerError|ECONNREFUSED"; MONGODB_URI muss auf den Service-Namen mongo zeigen.

Browserwarnung bei localhost

erwartet, weil Caddy ohne Domain ein Zertifikat seiner lokalen CA nutzt.

Einladungen kommen nicht an

SMTP-Daten oder Port falsch, siehe Schritt 8.

Oberfläche meldet Verbindungsfehler zur API

HOST_URL in .env und PUBLIC_URL in .env.prod stimmen nicht überein; beide auf dieselbe Adresse setzen und neu erstellen.

Port 3001 nicht erreichbar

Caddyfile fehlt im Projektordner. docker compose logs caddy | grep -i caddyfile.

Acrobat zeigt „nicht vertrauenswürdig“

Selbst erzeugte Zertifikate stehen nicht in der AATL; für externe Empfänger ein AATL-Zertifikat nutzen.

Änderungen nach docker compose pull

Das Tag main ändert sich mit jeder Veröffentlichung; per Digest fixieren (Schritt 4).

CORS-Fehler beim Hochladen

nur bei USE_LOCAL=false mit S3-kompatiblem Speicher; im Bucket eine CORS-Regel für Ihre OpenSign-Adresse anlegen.

Häufige Fragen

Ist OpenSign DSGVO-konform?

Selbst gehostet bleiben Dokumente und Unterzeichnerdaten auf Ihrem Server, solange Sie keinen externen Speicher konfigurieren. Die DSGVO-Pflichten als Verantwortlicher bleiben: Datenschutzhinweise für Unterzeichner, Löschkonzept und ein Auftragsverarbeitungsvertrag mit Ihrem Hoster und E-Mail-Dienstleister.

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

Ja, unter https://localhost:3001 oder mit HOST_URL=https://192.168.1.100:3001 für das LAN. Caddy stellt dann ein Zertifikat der lokalen CA aus. Für Let's Encrypt brauchen Sie eine öffentliche Domain.

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

Mit den OpenSSL-Befehlen aus Schritt 9. Das Ergebnis ist selbst signiert und nicht AATL-zertifiziert.

Wie spiele ich Updates ein?

Backup anlegen, neue Digests eintragen, docker compose pull und docker compose up -d. Die Volumes bleiben erhalten.

Kann OpenSign eine externe MongoDB-Instanz verwenden?

Ja. Setzen Sie MONGODB_URI auf den externen Connection-String mit Benutzer und Passwort und entfernen Sie den Dienst mongo aus der Compose-Datei.

Welche SMTP-Anbieter funktionieren?

Jeder Anbieter mit SMTP-Zugang. Nutzen Sie Port und Verschlüsselung laut Anbieter, meist 587 mit STARTTLS.

Sind die Signaturen eIDAS-konform?

OpenSign erzeugt elektronische Signaturen im Sinne von Art. 3 Nr. 10 eIDAS-Verordnung, bei Einsatz eines Zertifikats unter Umständen fortgeschrittene Signaturen; qualifizierte elektronische Signaturen (QES) erzeugt es nicht. Wo das Gesetz Schriftform verlangt, ersetzt nur die QES sie (§ 126a BGB). Manche Erklärungen schließen die elektronische Form ganz aus, etwa die Kündigung eines Arbeitsverhältnisses (§ 623 BGB). Für Angebote, NDAs und viele Dienstleistungsverträge ohne Formvorschrift genügt eine einfache elektronische Signatur; klären Sie Zweifelsfälle rechtlich.

Fazit

OpenSign lässt sich mit vier Containern in kurzer Zeit selbst betreiben. Für den sicheren Betrieb zählen: eigener MASTER_KEY, keine Host-Ports für MongoDB und Backend, feste Image-Digests, funktionierende E-Mail und regelmäßige Backups. Für die Ablage signierter Dokumente mit Volltextsuche ergänzt Paperless-ngx mit Docker den Stack.

Weiterführende Anleitungen und Quellen

  1. Caddy als Reverse Proxy mit automatischem HTTPS
  2. Docker und Docker Compose auf Linux installieren
  3. Paperless-ngx mit Docker einrichten
  4. Stirling-PDF mit Docker
  5. Docker Compose absichern: Secrets, Healthchecks, Non-Root

Offizielle Quellen: OpenSign Self-Hosting-Dokumentation | OpenSign auf GitHub | OpenSign-Umgebungsvariablen | MongoDB SERVER-125742: Kernel-Kompatibilität | § 126a und § 623 BGB (gesetze-im-internet.de)

Passende Beiträge auf S-EDV

  1. OpenSSL: neun Schwachstellen im Sicherheitsrelease vom 9. Juni 2026
  2. netcup Local Block Storage bestellen und unter Linux einbinden
  3. Linux-Kernel CVE-2026-23111: Fehler in nf_tables ermöglicht lokale Root-Rechte