← Übersicht  ·  Skripte & Dateien  ·  Heimnetz-Setup · Container auslagern

Container-Host auf Hetzner

Dein Windows-Laptop bleibt reiner Client – ein kleiner Cloud-Server trägt die Container. Gleicher Workflow wie lokal (podman run, podman composedocker run, docker compose), nur die Rechenlast wandert weg. Abrechnung stundenweise: Server löschen = Kosten weg.

Stand: 1. September 2026 ca. 15 Minuten Windows-Laptop → Hetzner Cloud

Wähle deine Engine – alle Befehle, die cloud-init-Datei und das Skript unten passen sich an. Podman: daemonlos, rootless möglich, kein Hintergrunddienst. Docker: vertrautester Standard, riesiges Oekosystem, Daemon läuft als root.

Platzhalter einsetzen – werden in allen Befehlen unten ersetzt, nur im Browser, nichts wird gesendet

Das Prinzip

Der podman-Befehl auf dem Laptop spricht über einen SSH-Tunnel mit dem podman.socket auf dem Server – das ist die Schnittstelle, über die Podman Container verwaltet. Es wird kein Podman-Port ins Internet geöffnet: nur SSH (Port 22), und den sperrst du auf deine eigene IP (Internet Protocol). Der Laptop rechnet nichts, er schickt nur Kommandos.

Der docker-Befehl auf dem Laptop verbindet sich per SSH mit dem Docker-Daemon auf dem Server (ein sog. docker context). Es wird kein Docker-Port ins Internet geöffnet: nur SSH (Port 22), gesperrt auf deine eigene IP. Der Laptop rechnet nichts, er schickt nur Kommandos.

Dein Laptop podman-Clientdocker-Client · hcloud CLI (Command-Line Interface)
steuert nur, rechnet nicht
Hetzner-Server podman.socket (rootful)Docker-Daemon
Container laufen hier
Blauer Streifen = auf deinem Laptop (PowerShell) Roter Streifen = auf dem Server (bash, erst ssh root@…)
Was sich 2026 geändert hat

Namen: Die x86-Sparserie heißt seit der Gen3-Umstellung CPX22 / CPX32 / CPX42 / CPX52 statt CPX22 / CPX32. Die ARM-Reihe (CAX11 / CAX21 / CAX31) ist meist noch etwas günstiger und für Container top, solange deine Images arm64 können (fast alle offiziellen).

Preise: 2026 gab es zwei Erhöhungsrunden (April und Juni) wegen des RAM-/SSD-Preißchocks. Die Tabelle unten sind Richtwerte – den echten Preis zeigt hcloud server-type describe CPX22 bzw. die Console.

IPv4 (Internet Protocol Version 4) kostet extra (~0,50 €/Monat). Wer ohne öffentliche IPv4 auskommt, hängt --without-ipv4 an hcloud server create.

01 Voraussetzung: Server-Basis

Konto, API-Token, hcloud CLI, SSH-Key, Firewall-Prinzip und die Skripte – der einmalige Teil steht in einer eigenen Anleitung, damit er nicht in jedem Guide steht.

Einmal einrichten

Server-Basis durcharbeiten. Werkzeuge für diese Anleitung: winget install RedHat.Podmanwinget install Docker.DockerCLI (Server-Basis, Abschnitt 4). Firewall: nur Port 22 – cloud.ps1 setzt die Regel bei jedem up auf deine aktuelle IP.

Ab hier nur noch der Container-Teil: cloud-init-Zeile, Erstellen, die Podman-Docker-Verbindung und der Betrieb.

02 cloud-init-Datei schreiben

cloud-init ist ein Standardmechanismus, der beim allerersten Boot einer VM (virtuelle Maschine) einmalig ein kleines Setup-Skript ausführt. Wir lassen den Server damit Podman installieren und den podman.socket aktivierenDocker installieren und starten – ganz ohne manuelle Handgriffe. Die Datei muss mit der Zeile #cloud-config beginnen, und die Einrueckung (2 Leerzeichen) ist Pflicht.

Datei · cloud-init.yaml
#cloud-config
package_update: true
packages:
  - podman
runcmd:
  - systemctl enable --now podman.socket
Datei · cloud-init.yaml
#cloud-config
package_update: true
packages:
  - docker.io
  - docker-compose-v2
# Docker startet nach der Installation von selbst und kommt bei jedem Boot wieder.

Die Datei im aktuellen Verzeichnis speichern – dort, wo du gleich hcloud server create aufrufst.

Im Repo

Beide Varianten liegen bei: scripts/cloud-init.yaml (Podman, Vorgabe) und scripts/cloud-init.docker.yaml. Für den Erst-up über die Skripte: .\scripts\cloud.ps1 up nimmt automatisch die Podman-Datei..\scripts\cloud.ps1 up -CloudInit cloud-init.docker.yaml. Danach kommt der Server aus dem Snapshot, die Datei wird nicht mehr gebraucht.

Image / Podman-Version Image

ubuntu-24.04 bringt Podman 4.9 – Quadlet (Schritt 10) funktioniert. Wer Podman 5.x will, nimmt debian-13 oder fedora-42. Die Schritte bleiben gleich. Debugging auf dem Server: cloud-init status --long, Log unter /var/log/cloud-init-output.log.

ubuntu-24.04 ist der einfachste Weg. Debugging auf dem Server: cloud-init status --long, Log unter /var/log/cloud-init-output.log. Alle Images: hcloud image list.

03 Server erstellen

Ein Befehl erzeugt die VM. Sie bootet in Sekunden, danach läuft cloud-init aus Schritt 5 noch etwa 30–90 Sekunden im Hintergrund (Paketinstallation).

Laptop · PowerShell
hcloud server create `
  --name podman-host `
  --type cpx22 `
  --image ubuntu-24.04 `
  --ssh-key laptop `
  --firewall podman-fw `
  --user-data-from-file cloud-init.yaml

hcloud server ip podman-host        # IP anzeigen -> oben ins Feld "Server-IP" eintragen
  • --name podman-host ist nur ein Label (auch bei Docker ok). Es taucht in allen weiteren Befehlen wieder auf.
  • --type: CPX22 = 2 vCPU / 4 GB (Gigabyte). Für mehrere Container eher CPX32 (4 / 8) oder CAX21 (ARM, gleiche Ausstattung, günstiger). Später ändern: hcloud server change-type podman-host cpx32.
  • --location (optional): nbg1/fsn1 (Deutschland), hel1 (Finnland), ash/hil (USA). Ohne Angabe wählt Hetzner.
  • Eine öffentliche IPv4 ist dabei (~0,50 €/Monat). Ohne: --without-ipv4 anhängen.

04 Server prüfen & Host-Key bestätigen

Der erste ssh-Kontakt fragt „The authenticity of host … can't be established. Continue?“ – das ist normal (dein Rechner kennt den neuen Server noch nicht). Mit yes bestätigen. Die Antwort wird gespeichert. Überspringst du das, scheitert die Verbindung in Schritt 8 stumm.

Laptop · PowerShell
ssh root@<IP> "systemctl is-active podman.socket"
Laptop · PowerShell
ssh root@<IP> "systemctl is-active docker"
Prüfen

OK wenn: die Ausgabe active ist. Kommt inactive, activating oder not-found, lief cloud-init noch nicht fertig – 30–60 Sekunden warten, nochmal. Genauer Stand: ssh root@<IP> "cloud-init status --long".

05 Podman-Verbindung anlegenDocker-Context anlegen

Jetzt sagst du dem podmandocker-Befehl auf dem Laptop einmalig, dass er über SSH auf dem Server arbeiten soll. Ab dann geht jeder Befehl automatisch dorthin – kein Umweg nötig.

Laptop · PowerShell
podman system connection add hetzner `
  --identity $env:USERPROFILE\.ssh\id_ed25519 `
  ssh://root@<IP>/run/podman/podman.sock

podman system connection default hetzner        # als Standard setzen
podman info --format "{{.Host.Hostname}}"        # muss den Server zeigen

Zwischen lokal und Cloud wechseln:

Laptop · PowerShell
podman system connection default podman-machine-default   # zurueck zu lokal
podman --connection hetzner ps                            # nur ein Befehl remote
podman system connection list                             # alle Verbindungen
Laptop · PowerShell
docker context create hetzner --docker "host=ssh://root@<IP>"

docker context use hetzner                    # als Standard setzen
docker info --format "{{.Name}}"              # muss "hetzner" zeigen

Zwischen lokal und Cloud wechseln:

Laptop · PowerShell
docker context use default        # zurueck zu lokal
docker --context hetzner ps       # nur ein Befehl remote
docker context ls                 # alle Contexts

Verbindet docker context nicht, fehlt meist der Schlüssel im SSH-Agent. Einmalig:

Laptop · PowerShell (nur bei Bedarf)
Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519

06 Container starten & Ports

Ganz normale Befehle – sie laufen dank Schritt 8 auf dem Server. podman composedocker compose funktioniert genauso. -p 8080:80 heißt: Port 80 im Container ist als Port 8080 auf dem Server erreichbar.

Laptop · PowerShell (→ Server)
podman run -d --name web -p 8080:80 docker.io/library/nginx
podman ps
podman logs web
Laptop · PowerShell (→ Server)
docker run -d --name web -p 8080:80 nginx
docker ps
docker logs web

Der Port ist von außen aber erst erreichbar, wenn die Firewall ihn durchlaesst. Zwei Wege:

a) Nur privat testen – nichts öffnen, per SSH tunneln:

Laptop · PowerShell
ssh -L 8080:localhost:8080 root@<IP>
# Fenster offen lassen, dann im Browser:  http://localhost:8080

b) Öffentlich erreichbar – Port gezielt in der Firewall freigeben (dann http://<IP>:8080):

Laptop · PowerShell
hcloud firewall add-rule podman-fw --direction in `
  --protocol tcp --port 8080 --source-ips 0.0.0.0/0,::/0

07 Container neustart-fest machen

Ein einfach gestarteter Container ist nach einem Server-Neustart weg. Damit dauerhaft laufende Dienste automatisch wiederkommen – beim Booten und nach Abstuerzen:

Bei Docker reicht die Restart-Policy. Der Docker-Daemon startet solche Container beim Booten von selbst wieder. Einfach beim run mitgeben:

Laptop · PowerShell (→ Server)
docker run -d --name web --restart=always -p 8080:80 nginx

Läuft schon einer ohne Policy? Nachträglich setzen:

Laptop · PowerShell (→ Server)
docker update --restart=always web
Mehrere Container: compose

Für einen Stack aus mehreren Containern eine compose.yaml auf dem Server anlegen (ssh root@<IP>, dann Datei), mit restart: unless-stopped pro Service, und docker compose up -d. Auch dann startet alles nach einem Reboot von selbst.

Podman hat keinen Daemon – stattdessen übernimmt systemd (der Dienst-Verwalter von Linux) den Container. Man beschreibt ihn in einer kleinen Datei (Quadlet), systemd macht daraus einen echten Dienst.

1. Auf dem Server einloggen. Alle Befehle in diesem Schritt laufen danach dort (bash), nicht mehr in PowerShell:

Laptop · PowerShell
ssh root@<IP>
# der Prompt wird jetzt zu  root@podman-host:~#  -> du bist auf dem Server

2. Container-Datei anlegen. Der Block schreibt alles zwischen <<'EOF' und der Zeile EOF in die Datei /etc/containers/systemd/web.container (komplett einfügen, Enter):

Server · bash
cat > /etc/containers/systemd/web.container <<'EOF'
[Container]
Image=docker.io/library/nginx
PublishPort=8080:80

[Install]
WantedBy=multi-user.target
EOF

3. Aktivieren. Quadlet macht aus web.container automatisch einen Dienst namens web:

Server · bash
systemctl daemon-reload      # neue Datei einlesen
systemctl start web          # Container starten

systemctl status web         # laeuft er?
journalctl -u web            # Logs ansehen
exit                         # zurueck zum Laptop
Mehrere Container / Änderungen

Pro Container eine eigene *.container-Datei im selben Ordner. Optionen wie bei podman run: Volume=/host/pfad:/pfad, Environment=KEY=wert, Network=. Nach jeder Änderung: systemctl daemon-reload und systemctl restart web.

+ Kosten steuern

Preise sind Richtwerte. Hetzner hat 2026 zweimal erhöht (zuletzt 15. Juni: CX/CAX +30–40 %, CPX/CCX über 100 %). Aktuelle Server-Preise, alle Nebenposten, ein Rechner und Beispielrechnungen stehen zentral in Kosten & Budget.

Hetzner rechnet stundenweise ab, solange der Server existiert – herunterfahren spart nichts. Der Snapshot-Zyklus (sichern → löschen → neu, Snapshot ~0,0143 €/GB/Monat) steht in Server-Snapshot & Restore. cloud.ps1 macht ihn per up/down.

TypvCPURAM (Random Access Memory)Diskca. €/Monatca. €/Tagca. €/Std.
CPX2224 GB40 GB~19,5~0,64~0,027
CPX3248 GB80 GB~35,5~1,17~0,049
CPX42816 GB160 GB~69,5~2,28~0,095
CAX11 (ARM)24 GB40 GB~4~0,14~0,006
CAX21 (ARM)48 GB80 GB~10,5~0,34~0,014

Rechnungsposten pro Tag (Beispiel CPX32, 24 h Dauerbetrieb)

Posten€/Std€/Tag€/Monat
Server CPX32 (4 vCPU / 8 GB) – CX33/CAX21 ~8,5–10,5 falls frei~0,049~1,17~35,5
Primary-IP (IPv4)~0,0008~0,02~0,50
Snapshot (~4 GB Speicher)~0,002~0,06
zusammen, 24 h/Tag~0,050~1,19~36

.\scripts\cloud.ps1 down stoppt Server und IPv4-Uhr sofort – nur der Snapshot läuft weiter (~0,06 €/Monat). Eine typische 3-h-Session ist ~4 Cent, ein vergessener Tag ~33 Cent. Bei einem Mehr-Node-Cluster alles × Anzahl Nodes (Load Balancer extra, siehe Microservices-Guide).

Richtwerte Region Deutschland, 2026, ohne IPv4-Aufschlag (~0,50 €/Monat). Die Intel-cx-Linie ist bei Hetzner oft ausverkauft – cpx (AMD, x86, gleiche Nutzung) ist der Ausweg. ARM (Advanced RISC Machines) cax nur mit ARM-Snapshot. Stundenpreis wird bis zum Monatspreis gedeckelt. Aktuell: hcloud server-type describe <typ>.

+ Absicherung

Sobald der Aufbau steht – in Ruhe nachziehen.

  • Rootless statt root: einen normalen Linux-User anlegen, loginctl enable-linger <user> setzen (damit der User-Dienst ohne Login läuft), dann die Verbindung auf ssh://<user>@<IP>/run/user/<uid>/podman/podman.sock umstellen. Container laufen dann komplett ohne root – ein echter Podman-Vorteil.
  • Zum root-Daemon: Der Docker-Daemon läuft als root, und wer den Docker-Socket erreicht, ist praktisch root auf dem Server. Deshalb: Socket nie per TCP (Transmission Control Protocol) ins Netz öffnen (dieser Guide nutzt nur SSH – passt). Wer es rootless will, richtet Rootless Docker (dockerd-rootless-setuptool.sh install als non-root User) ein – oder nimmt gleich Podman.
  • Automatische Updates: apt install unattended-upgrades auf dem Server, dann laufen Sicherheitsupdates von selbst.
  • SSH: Passwort-Login ist bei Hetzner-Images ohnehin aus. PermitRootLogin prohibit-password (nur Key) so belassen.
  • Firewall-Default: alles Eingehende außer den bewusst geöffneten Ports bleibt zu – hier nichts weiter zu tun.
Für den Dauerbetrieb

Wenn der Server nicht bloss ein Wegwerf-Lab ist: Grundausstattung-Checkliste – v.a. 2FA aufs Hetzner-Konto, Tailscale (dann Port 22 zu), Backup außer Haus, Docker-Log-Limits (daemon.json) und Uptime-Monitoring.

+ Kill-Switch: Vergessen darf nichts kosten

Zuerst die Entwarnung

Ein CPX32 kostet ~1,17 €/Tag ≈ 35 €/Monat. Falls gerade ein CX33 frei ist ~8,5 €, ein CAX21 (ARM) ~10,5 € – beide aber meist ausverkauft, plan mit dem CPX-Preis. Einen Monat vergessen ≈ 8 € – ärgerlich, kein Notfall.

Die vier Schutz-Ebenen (Skript, Desktop-Verknüpfung, nächtliche Aufgabenplanung, serverseitige Selbstzerstörung) stehen komplett in Server-Snapshot & Restore. Hier nur:

Laptop · PowerShell
.\scripts\cloud.ps1 up       # aus letztem Snapshot, podmandocker-Verbindung gesetzt
.\scripts\cloud.ps1 down     # Snapshot + loeschen -> Kosten sofort gestoppt
.\scripts\cloud.ps1 status
  • cloud.ps1 liegt im Repo – Konfiguration oben: $Server='podman-host', $Firewall='podman-fw', $Connection='hetzner'.
  • Serverseitiger Self-Destruct (cloud-init.selfdestruct.yaml): nur in einem separaten Hetzner-Projekt – Details in Server-Snapshot & Restore.

+ Andere Anbieter

Der Remote-Ablauf aus dieser Anleitung (Podman oder Docker) funktioniert auf jeder Linux-VM – nur IP, Image-Name und die Firewall-/Security-Group-Syntax ändern sich. Es gibt zwei Familien:

  • VM mieten – du bekommst Root per SSH, richtest die Engine ein (Schritt 5), verbindest wie oben. Du pflegst das System (Updates, Backup). Tabelle A.
  • Serverless-Container – kein Server, kein SSH. Du baust ein Image, schiebst es in eine Registry und definierst einen Dienst. Skaliert bei Nichtnutzung auf null. Anderer Workflow, siehe unten.

Tabelle A VM-Anbieter – passen zu dieser Anleitung

AnbieterSitz4 vCPU / 8 GB, ca.Wofür / Haken
HetznerDE (Deutschland) / FI (Finnland) / US~7 €/MonDiese Anleitung. 20 TB (Terabyte) Traffic inkl., bester Preis in der EU (Europäische Union).
netcupDE / AT~8 €/MonSehr günstig, EU-Datenschutz. Kaum bekannt, gute Qualität.
ContaboDE~10 $/MonViel RAM fürs Geld, aber überbucht → schwankende Leistung.
OVHcloudFR / DE / CA / …ab ~6 €/MonGrößter EU-Anbieter, eigene Rechenzentren. VPS (Virtual Private Server) bis Bare-Metal.
ScalewayFR / NL / PL~15–20 €/MonFranzoesisch, ARM + x86, saubere API (Application Programming Interface). Teurer als Hetzner.
Oracle Cloud „Always Free“EU / US / …0 €Seit 15. Juni 2026 nur noch 2 ARM-Kerne / 12 GB gratis (vorher 4 / 24). ARM oft „Out of Capacity“. Zum Rumprobieren top.
AWS (Amazon Web Services) Lightsailglobal~44 $/MonFixpreis-VPS im AWS-Konto. Einfachster AWS-Weg für diese Anleitung.
AWS EC2 (Elastic Compute Cloud) t4g.largeglobal~49 $/Mon+ EBS-Platte + Egress. Spot-Instanz ~15 $/Mon, aber jederzeit abschaltbar.
Azure VM B4msglobal~60–70 $/Mon12 Monate B1s gratis (1 GB, zu klein). Sinnvoll, wenn schon Azure-Kunde.
Google Cloud e2-standard-2global~49 $/Mon+ Egress. e2-micro dauerhaft gratis (1 GB, zu klein), 300 $ Startguthaben / 90 Tage.
DigitalOcean / Vultr / Linodeglobal~48 $/MonEntwicklerfreundlich, gute Doku, Startguthaben. Preislich zwischen Hetzner und AWS.

Alle Beträge grobe Richtwerte, August 2026. ARM-Anbieter (Oracle, AWS t4g, Azure Dpls, teils Scaleway/Hetzner cax) brauchen arm64-Images – bei offiziellen Images fast immer vorhanden.

Tabelle B Serverless – kein run auf einem Server, Image in Registry

Ablauf hier: buildpush in eine Container-Registry → Dienst anlegen (mit podman oder docker). Kein SSH, kein Server. Vorteil: läuft nichts, zahlst (fast) nichts. Nachteil: Kaltstart 0,2–3 s und neuer Workflow.

DienstAnbieterAuf null?Bemerkung
Cloud RunGooglejaEinfachster Einstieg, großzügiger Free-Tier (2 Mio Requests/Mon). Gut für Web-Dienste.
Container AppsAzurejaCloud-Run-Pendant, auf KEDA/Dapr. ~63 $/vCPU/Mon unter Volllast.
Fargate / App RunnerAWSApp Runner: jaFargate ist die günstigste Dauerlast der Serverless-Riege (~30 $/vCPU/Mon), skaliert aber nicht selbst auf null.
Fly.ioFly.ioja (Auto-Stop)Firecracker-Mikro-VMs nah am Nutzer, fly launch aus einem Dockerfile. Gut für Apps mit Nutzern in mehreren Regionen.
Render / RailwayRender Free: jaPaaS: git push statt Image. Am wenigsten Konfiguration, am wenigsten Kontrolle.
Kurz-Entscheidung

Günstig + volle Kontrolle, EU: Hetzner. Alternativen netcup oder Contabo.

Gratis zum Üben: Oracle „Always Free“ (ARM, 2 Kerne / 12 GB) – mit den 2026er Einschraenkungen im Hinterkopf.

Keinen Server pflegen wollen, Dienst läuft nur zeitweise: Google Cloud Run.

Schon in AWS / Azure zuhause: Lightsail bzw. Azure Container Apps.

Bei allen Nicht-EU-Budget-Anbietern beachten

Egress kostet bei AWS / Azure / GCP (Google Cloud Platform) ~0,09–0,12 $/GB ausgehend – Image-Pulls, Backups und Traffic summieren sich. Hetzner/netcup/Contabo haben große Kontingente inklusive.

„Gestoppt“ heißt nicht „kostenlos“: bei EC2 und Azure-VMs läuft die Platte (EBS / Managed Disk) weiter auf der Rechnung. Sparen = Instanz terminieren + Snapshot behalten.

Serverless: zusätzlich Kosten für Registry-Speicher, Requests und ausgehenden Traffic.

⌂ Cockpit