Betrieb
Eine Installation ist ihre Datenbank und ihre .env. Wer beides sichert, kann sie auf einem anderen Host wieder hinstellen. Dazu: was zu überwachen ist, wie man wieder hineinkommt, wenn niemand mehr Mail empfängt, und was im Alltag schiefgehen kann.
Sichern
Zwei Dinge, jede Nacht: ein Dump der Datenbank und eine Kopie der .env.
#!/bin/sh
# /etc/cron.daily/heinzel-pro-backup
set -eu
dir=/var/backups/heinzel-pro
install -d -m 700 "$dir"
cd /opt/heinzel-pro
docker compose exec -T db pg_dump -U heinzel -Fc heinzel_pro \
> "$dir/heinzel-pro-$(date +%F).dump"
cp .env "$dir/env-$(date +%F)"
# Danach beides dorthin kopieren, wo der Host nicht ist: ein anderer Host, ein Bucket, ein Band.Die Datei muss ausführbar sein, und die Zeile #!/bin/sh muss ganz oben stehen, sonst überspringt cron sie mit „Exec format error“. Prüfen Sie sie einmal so, wie cron sie aufruft:
$ sudo chmod 755 /etc/cron.daily/heinzel-pro-backup
$ sudo run-parts --verbose --regex '^heinzel-pro-backup$' /etc/cron.daily
$ ls -l /var/backups/heinzel-proMit Ihrer eigenen PostgreSQL gehört der Dump in deren Sicherung; mit der mitgebrachten ist das Volume pgdata die Datenbank, und der Dump ist der Weg, nicht eine Kopie des Volumes im Lauf.
Wiederherstellen
Auf einem neuen Host nach der Installationsanleitung bis einschließlich der Compose-Datei, dann:
Die gesicherte
.envnach/opt/heinzel-pro/.envlegen. Mit derselbenHEINZEL_VERSION, mit der der Dump gezogen wurde; ein Upgrade kommt danach.Nur die Datenbank starten und den Dump einspielen.
$ cd /opt/heinzel-pro $ sudo docker compose up -d db $ sudo docker compose exec -T db pg_restore -U heinzel -d heinzel_pro --clean --if-exists \ < /var/backups/heinzel-pro/heinzel-pro-2026-10-24.dumpDie Anwendung starten und prüfen.
$ sudo docker compose up -d $ curl -s http://127.0.0.1:4000/healthAnmelden, einen Server testen: Meldet sich Heinzel an, sind die Schlüssel lesbar, und die Wiederherstellung ist vollständig.
Den DNS-Namen auf den neuen Host umstellen, den Proxy einrichten, und die VPN-Verbindungen: Nach Weg 1 melden sich die Gegenstellen von selbst wieder, sobald der Name auflöst; nach Weg 2 ruft Heinzel den Router an.
Den Vault-Schlüssel rotieren
- Neuen Schlüssel erzeugen:
openssl rand -base64 32 - In der
.envden alten Schlüssel nachHEINZEL_VAULT_KEY_RETIREDverschieben undHEINZEL_VAULT_KEY_RETIRED_IDauf die alte Id setzen (bisher1); den neuen alsHEINZEL_VAULT_KEYmitHEINZEL_VAULT_KEY_ID=2eintragen. - Neu starten, dann jedes Geheimnis neu verschlüsseln:
sudo docker compose exec app bin/rotate-vault-key - Die
RETIRED-Zeilen entfernen und noch einmal starten. Die.envneu sichern.
Überwachen
GET /health liefert status, version, rules_version, database und pending_migrations und antwortet nur dann mit 200, wenn die Datenbank erreichbar ist und keine Migration aussteht. Ein Monitor, der alle Minute von außen https://heinzel.example.com/health auf 200 prüft, reicht für die Frage „läuft es“. Anfragen auf localhost bleiben auch mit FORCE_SSL unverschlüsselt, für die Probe vom Host.
In der Anwendung sagt Installation, Protokoll im Kasten „Betrieb“ dasselbe und mehr: Lizenz, Mailversand, Not-Aus und die Hintergrundjobs (wartend, geplant, läuft, wird wiederholt, aufgegeben). Ein wachsender Zähler bei „wird wiederholt“ ist ein Mailserver oder ein Webhook, der nicht annimmt.

Umgekehrt nimmt Heinzel Pro Alarme Ihres Monitorings an und sieht auf dem betroffenen Server nach, siehe Alarme aus dem Monitoring.
Logs
sudo docker compose logs app zeigt das Log der Anwendung; LOG_LEVEL in der .env stellt es von info auf debug oder warning. Was Benutzer tun, steht nicht darin, sondern im Audit-Protokoll in der Datenbank: je Mandant eine Kette, für die Installation eine eigene. Beide lassen sich als CSV exportieren und prüfen:
$ sudo docker compose exec app bin/heinzel_pro eval HeinzelPro.Release.verify_auditSoll das Protokoll in ein SIEM, gibt ein Administrator der Installation einem Mandanten unter Einstellungen, Anbindungen einen HTTPS-Endpunkt; jedes Ereignis geht dann binnen einer Minute als eine Zeile JSON dorthin, mit Position und Hash in der Kette. Die Aufbewahrung steht je Mandant unter Einstellungen, Allgemein; das Löschen nach Frist ist der einzige Weg, Zeilen zu entfernen, und wird selbst protokolliert.
Ausgesperrt
Kommt keine Mail mehr an, oder kennt niemand mehr das Passwort des einzigen Administrators, erzeugt ein Operator mit Shell-Zugang auf dem Host einen Anmeldelink für jedes Konto:
$ sudo docker compose exec app bin/login-link admin@example.comDer Link gilt einmal und 15 Minuten. Danach unter Konto Passwort oder zweiten Faktor neu einrichten. Hat jemand sein Gerät mit dem Passkey oder der Authenticator-App verloren, setzt ein Administrator der Installation unter Installation, Konten Passkeys und zweiten Faktor dieses Kontos zurück oder schickt einen Anmeldelink. Dort lässt sich auch eine Person in einen Mandanten setzen, dessen einziger Administrator ausgesperrt ist.
Mail später ändern
Mail ist in der .env eingerichtet, weil sie funktionieren muss, bevor sich jemand anmelden kann. Ein neuer Weg heißt: Zeilen ändern, sudo docker compose up -d, dann unter Installation, Mailversand eine Testmail. Die Seite zeigt, was gerade gilt.

Der Not-Aus
Die Administratoren eines Mandanten haben ihn unter Einstellungen, Richtlinie, die der Installation unter Installation, Mandanten für alle Mandanten auf einmal. Er stoppt jede Session, nimmt jeden wartenden Befehl zurück, bricht laufende Befehle auf den Hosts ab, und von da an startet nichts, bis er aufgehoben wird, auch nach einem Neustart nicht. Er verlangt einen Grund, steht im Audit-Protokoll, und ein Banner auf jeder Seite zeigt, dass er an ist.
Was die Installation verlässt
Eine Installation öffnet Verbindungen zu diesen Stellen und zu keiner anderen. Es gibt keine Telemetrie, keine Nutzungszahlen und keine Lizenzprüfung nach außen; ein Test in der Testsuite des Produkts schlägt fehl, sobald der Code eine Verbindung öffnet, die hier nicht steht.
- Modellanbieter: die Adresse jedes Anbieters, den Sie anlegen, voreingestellt
api.anthropic.comoderapi.openai.com, oder ein Server im eigenen Netz. - Ihre Server: SSH zu den Hosts, die Sie anlegen, auf dem Port, den Sie angeben.
- VPN-Verbindungen: WireGuard zur Gegenstelle aus dem Block, den Sie eingefügt haben; eine Tailscale-Verbindung spricht mit dem Koordinationsserver und den Relays von Tailscale oder mit Ihrem Headscale.
- Mail: der Mailserver oder Maildienst, den Sie eingerichtet haben.
- Endpunkte, die Sie eintragen: der Webhook des Teams, der Kollektor für das Audit-Protokoll, das Monitoring, das Markierungen annimmt.
- Single Sign-on: der OpenID-Connect-Aussteller, den Sie einrichten.
- Regelwerk:
api.github.comundgithub.com, stündlich für die Prüfung auf ein neueres Regelwerk und beim Aktualisieren, ohne Konto und ohne Angaben über die Installation. Wer das automatische Update ausschaltet und das Archiv hochlädt, öffnet diese Verbindung nie.
Docker selbst holt das Image von ghcr.io, wenn Sie es ziehen.
Heinzel Pro entfernen
Für eine Installation nach der Installationsanleitung, etwa nach der Testphase. Die Daten stecken im Volume pgdata; die betreuten Server behalten Heinzels Zugang, bis Sie ihn dort entfernen.
Eine letzte Sicherung, wenn Sie die Daten behalten wollen. Das Skript aus Sichern einmal von Hand, dann Dump und
.envvom Host kopieren. Das Audit-Protokoll ist danach nur noch im Dump.Container, Datenbank und Images entfernen.
$ cd /opt/heinzel-pro $ sudo docker compose down -v --rmi all $ cd / && sudo rm -rf /opt/heinzel-pro /var/backups/heinzel-pro $ sudo rm -f /etc/cron.daily/heinzel-pro-backup-vlöscht das Volume mit der Datenbank, unwiderruflich.Den Proxy und das Zertifikat. Bei nginx die Seite entfernen und das Zertifikat löschen, bei Caddy den Block aus dem Caddyfile:
$ sudo rm /etc/nginx/sites-enabled/heinzel-pro /etc/nginx/sites-available/heinzel-pro $ sudo nginx -t && sudo systemctl reload nginx $ sudo certbot delete --cert-name heinzel.example.comDie Firewall und die Mail. Die Regeln aus der Installation wieder schließen, und wer Postfix auf dem Host angebunden hat, nimmt das Compose-Netz aus
mynetworks:$ sudo ufw delete allow 51900:51919/udp $ sudo ufw delete allow from 172.30.79.0/24 to any port 25 proto tcpAuf jedem Server, den Heinzel betreut hat. Die Schlüsselzeile, die auf
heinzel-proendet, ausauthorized_keyslöschen. Wer dafür den Benutzerheinzelangelegt hat, entfernt ihn mit seiner sudo-Regel:$ sudo deluser --remove-home heinzel $ sudo rm -f /etc/sudoers.d/heinzelVPN-Verbindungen auf Routern und Servern der Gegenseite bleiben stehen, bis Sie sie dort löschen.
Docker, wenn es nur für Heinzel Pro da war. Auf Debian
sudo apt purge docker.io docker-compose, dannsudo apt autoremove --purge, nachdemapt-get -s autoremovegezeigt hat, dass es nur Dockers Pakete nimmt./var/lib/dockerund/var/lib/containerdlöschen Sie von Hand. Die Firewall-Ketten, die Docker angelegt hat (DOCKER,DOCKER-USER), und die Weiterleitung (net.ipv4.ip_forward) räumt erst ein Neustart des Hosts ab.
Prüfen Sie am Ende, dass nichts mehr lauscht: ss -lntu | grep -E ':4000|:519' bleibt leer.
Fehlersuche im Alltag
| Was Sie sehen | Woran es liegt | Was zu tun ist |
|---|---|---|
| Ein Befehl steht auf „unterbrochen, Ergebnis unbekannt“ | Heinzel Pro wurde neu gestartet, während der Befehl im SSH-Kanal lief: ein Lesebefehl, oder ein Host ohne Home-Verzeichnis für den Job. | Den Befehl in der Session noch einmal vorschlagen lassen; ein Befehl, der etwas ändert, läuft als Job und wird abgeholt. Vor dem nächsten Neustart ankündigen. |
| Ein Server ist rot markiert: Host-Key geändert | Der Host wurde neu installiert, oder jemand steht dazwischen. | Erst nachfragen, warum. Dann auf der Serverseite „Neuem Host-Key vertrauen“. |
| Sessions starten, aber jeder Modellaufruf schlägt fehl | Der Schlüssel des Anbieters ist abgelaufen, das Kontingent aufgebraucht, oder das Modell wurde vom Anbieter abgeschaltet. | Einstellungen, Modellanbieter: Testen. Ein Modell auf dem Weg hinaus ist dort markiert, mit Nachfolger und einem Klick zum Umstellen. |
| Keine neuen Sessions, ein Banner nennt die Lizenz | Die Testphase oder der Schlüssel ist abgelaufen, die Kulanzfrist vorbei. | Neuen Schlüssel unter Installation, Einstellungen, Lizenz einfügen. Alles Aufgezeichnete bleibt lesbar. |
| Berichte und Einladungen bleiben aus; „wird wiederholt“ zählt hoch | Der Mailserver nimmt nicht an: Passwort geändert, Absender abgelehnt, Zertifikat abgelaufen. | Installation, Mailversand, Testmail; das Log nennt die Antwort des Servers. |
| Eine VPN-Verbindung steht nach einem Neustart erst nach Minuten wieder | Heinzel ruft die Gegenseite dort an, wo sie zuletzt war; hat sich deren Adresse geändert, muss sie sich selbst melden. | Warten. Dauert es länger, sudo wg show heinzel auf der Gegenseite. |
| Nach einem Upgrade fehlt ein Zugriff, den es gab | Ein Recht wurde in einer Version zu einem benannten Recht, das ein Administrator abgewählt hatte. | Benutzer, Rechte: die Zeile auf „ja“ oder „wie es steht“. Das Changelog der Version nennt solche Schritte. |
| Die Platte des Hosts läuft voll | Alte Images, oder die Datenbank wächst mit Audit-Protokoll und Sessions. | docker image ls und alte Versionen entfernen; die Aufbewahrung unter Einstellungen, Allgemein setzen. |
Für alles andere: support@heinzel-pro.de mit der Zeile aus dem Log und der Version aus /health.