Warpgate mit Docker Compose: SSH-, HTTP- und Datenbank-Bastion ohne Client-Agent
Warpgate leitet SSH-, HTTP-, MySQL- und PostgreSQL-Verbindungen über einen zentralen Bastion-Host, ohne Software auf den Clients. Die Anleitung zeigt Einrichtung mit Docker Compose, Ziele, Rollen, Backup, Restore und Update.
Geprüft am 09.10.2026 · für Warpgate 0.29.2, PostgreSQL 17.11
Mit KI erstellt – redaktionelle Prüfung ausstehend
WerbelinksMit * 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

Verteilte SSH-Schlüssel, offene Datenbank-Ports und VPN-Konten, die niemand mehr überblickt: Warpgate ersetzt das durch einen einzelnen Bastion-Host, der SSH, HTTP(S), MySQL, PostgreSQL, Kubernetes, RDP und VNC weiterreicht, Benutzer zentral prüft und Sitzungen aufzeichnet. Auf den Clients läuft nichts Zusätzliches, Admins nutzen ssh, psql oder den Browser. Diese Anleitung richtet Warpgate 0.29.2 mit Docker Compose ein, bindet ein SSH-, ein Web- und ein PostgreSQL-Ziel an und zeigt Rollen, Backup, Restore und Update.
Voraussetzungen
Warpgate ist schlank: Nach Einrichtung, drei Zielen und einigen Sitzungen belegte das Datenverzeichnis im Test 4,5 MB.
- Linux-Server mit Docker Engine und Compose v2, 2 CPU-Kerne und 2 GB RAM inklusive Testzielen.
- x86_64 oder ARM64: Das Image
ghcr.io/warp-tech/warpgatewird fürlinux/amd64undlinux/arm64gebaut. - Ein DNS-Name wie
bastion.example.de; er bestimmt die Cookie-Domain (Schritt 3). - Freie Ports: 8888 (Weboberfläche und HTTP-Ziele, nur HTTPS), 2222 (SSH) und 55432 (PostgreSQL). MySQL nutzt 33306, Kubernetes 8443, RDP 3389 und VNC 5900, jeweils nur wenn bei der Einrichtung aktiviert.
- Netzwerkzugriff vom Warpgate-Host auf die internen Ziele, die selbst nicht öffentlich erreichbar sein müssen.
- Speicherplatz für Sitzungsaufzeichnungen unter
/data/recordings.
Schritt 1: Projektordner, compose.yaml und .env anlegen
Am 09.10.2026 zeigten die Tags 0.29.2, 0.29 und latest auf denselben Digest. Pinnen Sie trotzdem die volle Version, damit Updates bewusst passieren. Der GitHub-Release heißt v0.29.2, der Image-Tag hat kein v.
mkdir -p /opt/warpgate/data && cd /opt/warpgate
# Das Image läuft als Benutzer warpgate mit UID 1000
chown 1000:1000 data
Die compose.yaml enthält Warpgate und drei Testziele ohne eigene Ports: OpenSSH, einen kleinen Webdienst und PostgreSQL 17. Sie sind nur über Warpgate erreichbar.
services:
warpgate:
image: ghcr.io/warp-tech/warpgate:${WARPGATE_VERSION:-0.29.2}
restart: unless-stopped
environment:
WARPGATE_ADMIN_PASSWORD: ${WARPGATE_ADMIN_PASSWORD:?Admin-Passwort in .env setzen}
ports:
- "8888:8888"
- "2222:2222"
- "55432:55432"
volumes:
- ./data:/data
stdin_open: true
tty: true
# Testziele für den ersten Durchlauf, später durch echte Server ersetzen
ssh-ziel:
image: lscr.io/linuxserver/openssh-server:latest
environment:
PUID: "1000"
PGID: "1000"
USER_NAME: deploy
PASSWORD_ACCESS: "true"
USER_PASSWORD: ${ZIEL_SSH_PASSWORT:?}
web-ziel:
image: traefik/whoami:latest
db-ziel:
image: postgres:17
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: ${ZIEL_DB_PASSWORT:?}
POSTGRES_DB: app
Die .env im selben Ordner (Rechte 600). Die Beispielwerte sind Platzhalter:
WARPGATE_VERSION=0.29.2
WARPGATE_ADMIN_PASSWORD=bitte-langes-zufallspasswort-setzen
ZIEL_SSH_PASSWORT=nur-fuer-das-testziel
ZIEL_DB_PASSWORT=nur-fuer-das-testziel
Verifizieren: docker compose config --quiet läuft ohne Ausgabe durch. Fehlt das Admin-Passwort, bricht Compose ab mit required variable WARPGATE_ADMIN_PASSWORD is missing a value: Admin-Passwort in .env setzen.
Schritt 2: Warpgate einrichten und starten
Ohne Einrichtung endet der Container in einer Neustartschleife mit configuration file "/data/warpgate.yaml" not found. Statt des interaktiven setup nutzen Sie unattended-setup, das das Admin-Passwort aus WARPGATE_ADMIN_PASSWORD liest:
docker compose run --rm warpgate unattended-setup \
--data-path /data \
--http-port 8888 \
--ssh-port 2222 \
--postgres-port 55432 \
--record-sessions \
--external-host bastion.example.de
docker compose up -d
Der Assistent schreibt /data/warpgate.yaml, legt die SQLite-Datenbank unter /data/db/, ein selbstsigniertes TLS-Zertifikat, SSH-Schlüssel und den Benutzer admin an. Für MySQL ergänzen Sie --mysql-port 33306 samt Port-Mapping.
Verifizieren: docker compose logs warpgate zeigt Warpgate version=v0.29.2 und je eine Zeile Binding listener für SSH, HTTP und PostgreSQL. docker compose ps meldet nach wenigen Sekunden healthy; das Image bringt mit warpgate healthcheck einen eigenen Healthcheck mit. curl -k -o /dev/null -w "%{http_code}" https://localhost:8888/@warpgate liefert 200.
Schritt 3: Anmelden und den Hostnamen richtig setzen
Die Oberfläche liegt unter https://bastion.example.de:8888/@warpgate, die Verwaltung unter /@warpgate/admin. Port 8888 spricht nur HTTPS; curl http://localhost:8888/ endet mit Received HTTP/0.9 when not allowed.
Wichtiger ist der Hostname: Warpgate setzt das Sitzungs-Cookie für die Domain aus external_host (Log: Cookie domain configured: .bastion.example.de). Im Test lieferte die Anmeldung über einen anderen Namen 201, jede folgende Anfrage aber 401. Rufen Sie Warpgate deshalb immer über den eingetragenen Namen auf, nie per IP. Geändert wird der Wert in data/warpgate.yaml mit anschließendem Neustart.
Verifizieren: Die Anmeldung als admin führt in die Verwaltung; unter Config sind Targets, Users, Access roles und Admin roles sichtbar.
Schritt 4: SSH-, HTTP- und PostgreSQL-Ziele anlegen
Unter Config, Targets, Add a target legen Sie je Ziel einen Namen, den Typ und die Verbindungsdaten an. Für die Testziele:
- ssh-ziel (SSH): Host
ssh-ziel, Port2222, Benutzerdeploy, Passwort aus der.env. Für echte Server empfiehlt die Doku Warpgates öffentliche Schlüssel aus Config, SSH keys in derauthorized_keysdes Zielbenutzers. - web-ziel (HTTP): URL
http://web-ziel:80, TLS-Modus Disabled. - db-ziel (PostgreSQL): Host
db-ziel, Port5432, Benutzerappmit Passwort aus der.env.

Standardmäßig liegen Zielpasswörter im Klartext in der Datenbank. Seit 0.28 verschlüsselt sie WARPGATE_ENCRYPTION_KEY (aus openssl rand -base64 32). Warpgate speichert den Schlüssel nirgends; geht er verloren, sind alle Zielpasswörter neu einzugeben.
Verifizieren: Die Zielliste zeigt alle drei Einträge mit dem richtigen Protokoll.
Schritt 5: Rollen und Benutzer anlegen
Zugriffsrollen (Access roles) legen fest, welche Ziele ein Benutzer erreicht; Admin-Rollen geben Teilrechte in der Verwaltung. Legen Sie die Zugriffsrolle betrieb an, aktivieren Sie sie bei allen Zielen unter „Allow access for roles“ und weisen Sie sie dem neuen Benutzer lisa mit eigenem Passwort zu.

Gegenprobe: Ein Benutzer gast ohne Rolle bekam beim SSH-Ziel Permission denied (publickey,keyboard-interactive), im Log steht der Grund Target ssh-ziel not authorized for user gast. Die Verwaltungs-API antwortet lisa ohne Admin-Rolle mit 401.
Verifizieren: Nach der Anmeldung als lisa zeigt die Startseite genau die freigegebenen Ziele.
Schritt 6: Über Warpgate verbinden
Der Zielname steckt im Benutzernamen. Für SSH trennt ein Doppelpunkt Benutzer und Ziel, für Datenbanken wahlweise # oder ::
ssh -p 2222 lisa:ssh-ziel@bastion.example.de
psql "host=bastion.example.de port=55432 user=lisa#db-ziel dbname=app sslmode=require"
# HTTP-Ziel im Browser
https://bastion.example.de:8888/?warpgate-target=web-ziel
Beim ersten SSH-Zugriff fragt Warpgate: There is no trusted ssh-ed25519 key for this host. Trust this key? (y/n). Nach y speichert es den Schlüssel; prüfen Sie den Fingerabdruck. Abgefragt wird das Warpgate-Passwort von lisa, nicht das des Zielservers.

PostgreSQL nimmt Warpgate nur mit TLS an, sonst kommt FATAL: SSL connection required. Das HTTP-Ziel liefert ohne Anmeldung 401; danach reicht Warpgate Anfragen durch und ergänzt die Header X-Warpgate-Username und X-Warpgate-Authentication-Type.

Verifizieren: ssh -p 2222 lisa:ssh-ziel@bastion.example.de hostname gibt den Hostnamen des Ziels aus, psql beantwortet select current_user; mit app, und unter Status, Sessions stehen die Verbindungen mit Benutzer, Ziel und Befehl.
Schritt 7: Reverse Proxy, TLS und Härtung
Das selbstsignierte Zertifikat ersetzen Sie in data/tls.certificate.pem und data/tls.key.pem oder setzen einen Reverse Proxy vor Port 8888. Im Test lief die Oberfläche hinter einem TLS-Proxy mit Ziel https://localhost:8888. Dazu gehört trust_x_forwarded_headers: true im Abschnitt http der warpgate.yaml; für das Web-Terminal braucht der Proxy Websockets:
location / {
proxy_pass https://127.0.0.1:8888;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_http_version 1.1;
proxy_read_timeout 3600s;
}
SSH und PostgreSQL laufen nicht über den HTTP-Proxy; öffnen Sie diese Ports nur für die Netze, die sie brauchen. Die Produktions-Checkliste des Projekts nennt zudem: eigenes Konto pro Admin, Zwei-Faktor-Pflicht (seit 0.29 global schaltbar), Login-Schutz gegen Brute Force und Admin-Freigabe für sensible Ziele.
Verifizieren: Der Aufruf über den Proxy-Namen zeigt ein gültiges Zertifikat, und nach der Anmeldung bleiben Verwaltung und Zielliste ohne erneute Abfrage erreichbar.
Schritt 8: Backup und Restore
Bei Docker mit SQLite liegen Konfiguration, Datenbank, Zertifikate und Aufzeichnungen in data; einen Verschlüsselungsschlüssel sichern Sie getrennt. Am einfachsten ist eine kalte Sicherung, denn die Datenbank läuft im WAL-Modus:
cd /opt/warpgate
docker compose exec warpgate warpgate version > backup/VERSION
docker compose stop warpgate
tar czf backup/warpgate-data-$(date +%F).tgz -C data .
docker compose start warpgate
Für den laufenden Betrieb nennt die Doku sqlite3 db.sqlite3 ".backup ...". Der Restore braucht dieselbe Warpgate-Version wie das Backup:
docker compose stop warpgate
mv data data.defekt && mkdir data
tar xzf backup/warpgate-data-2026-10-09.tgz -C data
chown -R 1000:1000 data
docker compose start warpgate
Im Test wurde vor der Sicherung ein Benutzer backup-marker angelegt, danach gelöscht und das Datenverzeichnis entfernt. Nach dem Restore war der Marker zurück, und SSH über Warpgate lief ohne erneute Host-Key-Rückfrage.
Verifizieren: docker compose exec warpgate sqlite3 /data/db/db.sqlite3 "select username from users;" listet alle Benutzer inklusive Marker, und eine Testverbindung zu einem SSH-Ziel gelingt.
Schritt 9: Update und Rollback
Ein Update ist ein Image-Tausch: Version in der .env anheben, docker compose pull, docker compose up -d; Migrationen laufen beim Start. Sichern Sie vorher, denn zurück geht es nur per Backup. Im Test hing 0.28.2 auf einer von 0.29.2 migrierten Datenbank in einer Neustartschleife mit Migration file of version 'm00087_drop_null_target_options' is missing, this migration has been applied but its file is missing. Mit 0.29.2 lief die Instanz sofort wieder.
Verifizieren: Nach dem Update nennt das Log die neue Version, docker compose ps meldet healthy und eine Testverbindung gelingt.
Troubleshooting
- Neustartschleife mit
configuration file "/data/warpgate.yaml" not found: Entweder fehlt die Einrichtung aus Schritt 2, oder das Datenverzeichnis gehört nicht UID 1000. Im Test löste einroot-eigenes, auf700gesetztesdatagenau diese irreführende Meldung aus. Abhilfe:chown -R 1000:1000 data. - Anmeldung klappt, danach sofort wieder abgemeldet: Der Aufrufname passt nicht zu
external_host, das Cookie wird verworfen. Mit dem eingetragenen Namen aufrufen oder den Wert anpassen. Permission denied, please try again.beim SSH-Login: falsches Warpgate-Passwort. BeiPermission denied (publickey,keyboard-interactive)nach erfolgreicher Anmeldung fehlt die Zugriffsrolle oder der Zielname ist falsch geschrieben.SSL connection requiredbeipsql: Im Clientsslmode=requiresetzen.driver failed programming external connectivity ... port is already allocated: Ein anderer Dienst belegt einen der veröffentlichten Ports. Dienst stoppen oder das linke Port-Mapping ändern, danachdocker compose up -d --force-recreate warpgate.- Admin-Passwort vergessen:
docker compose exec -it warpgate warpgate recover-accesssetzt laut Doku ein neues Passwort und deaktiviert die Zwei-Faktor-Pflicht für diesen Benutzer.
Häufige Fragen
Brauchen die Mitarbeitenden einen Client oder Agenten?
Nein. SSH, psql, mysql, kubectl und der Browser reichen. Für SSH und RDP gibt es zusätzlich Clients im Browser, die sich global abschalten lassen.
Worin unterscheidet sich Warpgate von JumpServer?
JumpServer ist eine umfangreiche PAM-Plattform aus mehreren Diensten, siehe unsere JumpServer-Anleitung. Warpgate ist ein einzelnes Programm mit SQLite und passt, wenn ein kleines Team schnell einen kontrollierten Einstiegspunkt braucht.
Ersetzt Warpgate ein VPN?
Für Admin-Zugriffe auf einzelne Dienste oft ja. Für vollen Netzzugriff bleibt ein VPN wie WireGuard mit wg-easy passender; kombiniert ist Warpgate nur aus dem VPN erreichbar.
Gibt es kostenpflichtige Funktionen?
Nein. Warpgate steht unter Apache-2.0; laut Projektseite kostet nur Support der Entwickler.
Sind die Befehlsprotokolle revisionssicher?
Nein. Die Doku nennt die Erkennung einzelner Shell-Befehle selbst eine Hilfe für das Audit und keine Sicherheitsgrenze. Die vollständige Aufzeichnung der Sitzung ist belastbarer als die Befehlsliste.
Warpgate entfernen
Warnung: Das folgende Vorgehen löscht Benutzer, Ziele, gespeicherte Zugangsdaten, Host-Schlüssel und alle Aufzeichnungen unwiderruflich. Sichern Sie vorher wie in Schritt 8 und entfernen Sie Warpgates öffentliche Schlüssel aus den authorized_keys der Zielserver.
cd /opt/warpgate
docker compose down
rm -rf /opt/warpgate/data
Fazit
Warpgate bringt zentrale Benutzer, Rollen und Sitzungsaufzeichnung ohne Client-Software in einen einzelnen Container. Im Test liefen SSH, HTTP und PostgreSQL nach wenigen Minuten, die Rollen griffen, und der Restore stellte alles wieder her. Beachten Sie drei Punkte: Der Hostname bestimmt die Cookie-Domain, data muss UID 1000 gehören, und ein Update ist ohne Backup eine Einbahnstraße.
| Eckdaten | Wert |
|---|---|
| Image | ghcr.io/warp-tech/warpgate:0.29.2 (amd64, arm64) |
| Ports | 8888 HTTPS, 2222 SSH, 55432 PostgreSQL, optional 33306, 8443, 3389, 5900 |
| Volume | /data (Konfiguration, SQLite, TLS, Aufzeichnungen) |
| Benutzer im Container | warpgate, UID 1000 |
| Wichtige Variablen | WARPGATE_ADMIN_PASSWORD (Einrichtung), WARPGATE_ENCRYPTION_KEY (optional) |
| Healthcheck | im Image enthalten: warpgate healthcheck |
| Lizenz | Apache-2.0 |
Weiterführende Anleitungen und Quellen
- JumpServer mit Docker: Bastion-Host und Privileged Access Management
- WireGuard mit wg-easy und Docker
- Caddy als Reverse Proxy mit automatischem HTTPS
- Warpgate-Doku: Einrichtung mit Docker
- Warpgate-Doku: SSH-Ziele
- Warpgate-Doku: PostgreSQL-Ziele
- Warpgate-Doku: Backup und Restore
- Warpgate-Doku: Updates
- Warpgate-Doku: Checkliste für den Produktivbetrieb
- Release-Hinweise zu Warpgate 0.29.2 auf GitHub


