← Übersicht  ·  Skripte & Dateien  ·  cloud-host · Grundlage

Server-Basis

Der einmalige Teil, den alle anderen Anleitungen voraussetzen: Hetzner-Konto und 2FA, API-Token, hcloud CLI (Command-Line Interface) und Kontext, SSH-Key hinterlegen, das Firewall-Prinzip und das cloud-init-Grundmuster. Danach macht jede Dienst-Anleitung nur noch ihren Teil – die passende cloud-init-Zeile und den eigenen Stack. Der Abbau (Snapshot, löschen, Kill-Switch) steht in Server-Snapshot & Restore.

Stand: 30. August 2026 Windows-Laptop → Hetzner Cloud einmalig ~20 Min

Platzhalter einsetzen – nur im Browser

Einmalig / pro Projekt / pro Server

Waswie oft
Hetzner-Konto, 2FA, Zahlungsart, hcloud CLI + Kontext, SSH-Key auf dem Laptop, die Skripte kloneneinmal
Projekt anlegen, API-Token, SSH-Key bei Hetzner hinterlegen, Firewall(s) anlegenpro Projekt (prod / staging / Wegwerf getrennt)
cloud-init schreiben, cloud.ps1/snapshot.ps1 konfigurieren, Server erstellen, DNS (Domain Name System) setzenpro Server / Dienst

Diese Anleitung deckt Zeile 1 und 2 ab und zeigt das Muster für Zeile 3. Die konkrete cloud-init-Zeile und den Stack liefert die jeweilige Dienst-Anleitung.

1 Konto, 2FA, Projekt

  1. Konto auf console.hetzner.com, Zahlungsart hinterlegen (sonst schlägt server create mit „not verified“ fehl).
  2. 2FA anschalten: Security Two Factor Auth – das Hetzner-Konto steuert echtes Geld.
  3. Projekt anlegen (oben links). Ein Projekt ist ein abgeschotteter Ressourcen-Topf mit eigenem Token. Empfehlung: eigenes Projekt heimlabor für Wegwerf-Server, getrennt von allem Dauerhaften.
Kein Ausgabenlimit

Hetzner hat keine Kostenobergrenze. Der wichtigste Schutz ist der Kill-Switch aus Server-Snapshot & Restore – und die Grundausstattung-Checkliste.

2 API-Token

Das Passwort, mit dem hcloud Server erstellt und löscht. Pro Projekt einer.

  1. Im Projekt: Security API (Application Programming Interface) Tokens Generate API token → Berechtigung Read & Write.
  2. Sofort kopieren – wird nur einmal gezeigt. In den Passwortmanager, nicht ins Repo.
  3. Verloren? Neuen erzeugen, alten löschen.

3 hcloud CLI & Kontext

Laptop · PowerShell
winget install HetznerCloud.CLI
# Terminal neu oeffnen, damit hcloud im PATH ist

hcloud context create heimlabor     # fragt nach dem Token aus Schritt 2
hcloud context list                     # der aktive hat einen *
Prüfen

OK wenn: hcloud server list eine (leere) Tabelle zeigt statt einer Fehlermeldung. Mehr Projekte → hcloud context create <name> und hcloud context use <name>.

4 Werkzeuge je nach Ziel

Du willst…zusätzlich
Container (Podman/Docker) fernsteuernwinget install RedHat.Podman oder Docker Desktop
Kubernetes (k3s)winget install Kubernetes.kubectl Helm.Helm, optional Derailed.k9s
OpenShift/OKD (auch OKD Single-Node)oc von mirror.openshift.com, für OKD Single-Node zusätzlich wsl --install
Nur Web-Dienste (WordPress, Nextcloud, Mail …)nichts extra – alles läuft per SSH (Secure Shell) auf dem Server
Dateien synchron haltenwinget install cwRsync (sonst tar+ssh, unter Windows 10 dabei)

ssh.exe, scp.exe, tar.exe sind unter Windows 10/11 eingebaut – nichts zu installieren.

5 SSH-Key hinterlegen

Der private Teil bleibt auf dem Laptop, der öffentliche wird von Hetzner in den root-Account jedes neuen Servers gelegt.

Laptop · PowerShell
# nur falls noch keiner existiert:
ssh-keygen -t ed25519 -f $env:USERPROFILE\.ssh\id_ed25519

# bei Hetzner hinterlegen (Name "laptop" -- taucht in jedem "server create" wieder auf)
hcloud ssh-key create --name laptop --public-key-from-file $env:USERPROFILE\.ssh\id_ed25519.pub
Pro Projekt

Der SSH-Key ist projektgebunden – in jedem neuen Projekt einmal hcloud ssh-key create mit demselben .pub.

6 Firewall-Prinzip

Eine Hetzner Cloud Firewall filtert schon im Netz, vor dem Server. Regel: nur die nötigen Ports, nur von deiner IP (Internet Protocol).

Wer darf womit reden – und warum die Firewall vor dem Server sitzt und nicht darauf.

Zeichnung aus Diagramme: Hetzner & CRC (02).

Internet jeder, auch Scanner Dein Anschluss eine einzige IP Cloud-Firewall eigenes Objekt, nicht am Server 80 + 443 0.0.0.0/0 und ::/0 8443 Verwaltung nur eigene IP /32 22 SSH nur eigene IP /32 alles Uebrige: gesperrt Erlaubnisliste, keine Reihenfolge, keine Prioritäten Server ufw / nftables optional darauf – zweite Schicht, nicht die erste Docker umgeht ufw! TCP 80 / 443 TCP 22 und 8443 durchgelassen durchgelassen Tailnet – geht an der Firewall vorbei, ohne einen Port zu öffnen WireGuard über UDP · von innen aufgebaut, deshalb braucht es keine eingehende Regel
Die Firewall filtert im Netz, bevor der Verkehr den Server erreicht – sie kostet deshalb keine Rechenleistung und wirkt weiter, wenn auf dem Server etwas kaputt ist. Sie ist eine reine Erlaubnisliste ohne Reihenfolge. Der grüne Weg ist der interessante: das Tailnet baut die Verbindung von innen nach außen auf, also braucht es dafür gar keine eingehende Regel.
Laptop · PowerShell – einmal pro Projekt
$ip = (Invoke-RestMethod 'https://ipv4.icanhazip.com').Trim()

hcloud firewall create --name podman-host-fw
hcloud firewall add-rule podman-host-fw --direction in --protocol tcp --port 22 --source-ips "$ip/32"
# je nach Dienst zusaetzlich: 6443 (kube-API), 80/443 (Web) -- steht in der Dienst-Anleitung
Empfohlen: die Skripte machen das

cloud.ps1 / snapshot.ps1 setzen bei jedem up die SSH-Regel auf deine aktuelle IP – kein Nachjustieren, wenn die Heim-IP wechselt. Noch besser: Tailscale rein und Port 22 ganz zu.

7 cloud-init: Grundmuster

cloud-init.yaml läuft einmalig beim ersten Boot. Jede Dienst-Anleitung ergänzt hier ihre eine Zeile (k3s-Install, Podman, Docker …) – der Rahmen ist immer gleich.

Datei · cloud-init.yaml (Muster)
#cloud-config
package_update: true
package_upgrade: true
packages: [ ca-certificates, curl, fail2ban, unattended-upgrades ]
runcmd:
  # --- HIER die Zeile aus der jeweiligen Dienst-Anleitung ---
  # Container:  - curl -fsSL https://get.docker.com | sh
  # k3s:        - curl -sfL https://get.k3s.io | sh -s - server --write-kubeconfig-mode 644 --tls-san "$(curl -s http://169.254.169.254/hetzner/v1/metadata/public-ipv4)"
  - printf '%s\n' '{ "log-driver":"json-file","log-opts":{"max-size":"10m","max-file":"3"} }' > /etc/docker/daemon.json
  - systemctl restart docker 2>/dev/null || true
write_files:
  - path: /etc/apt/apt.conf.d/20auto-upgrades
    content: |
      APT::Periodic::Update-Package-Lists "1";
      APT::Periodic::Unattended-Upgrade "1";

Wichtig: cloud-init läuft nur beim allerersten up (aus dem Basis-Image). Danach bootet der Server aus dem Snapshot und alles ist schon eingerichtet – siehe Server-Snapshot & Restore.

8 Die Skripte konfigurieren

Repo klonen (Link in der Übersicht), dann oben in der passenden .ps1 die Konfiguration anpassen.

Skriptwofürwichtigste Felder
cloud.ps1ein Server, einfacher An/Aus$Server, $Type (CPX32), $SshKey, $Firewall, optional $DnsZone/$DnsNames
snapshot.ps1mehrere Server / Cluster, feste IP optionalje Server ein @{ name; type; firewall; ddnsZone; ddnsNames; preDown; postUp }
dienste-stack.ps1Compose-Stacks auf dem konsolidierten Server$Server (SSH-Alias), $StacksDir, $UpOrder
DNS automatisch

Ohne feste IP: $DnsZone/ddnsZone setzen, dann ruft das Skript beim up cf-dns.ps1 auf und zieht den A-Record auf die neue IP nach. Token einmal in $env:CF_API_TOKEN.

9 Erster Server

Laptop · PowerShell
.\scripts\cloud.ps1 up          # erstellt aus Basis-Image + cloud-init, setzt Firewall + Verbindung
.\scripts\cloud.ps1 status      # laeuft er? seit wann? ~Kosten
.\scripts\cloud.ps1 ssh         # SSH drauf (Host-Key wird vorher bereinigt)

Der erste SSH-Kontakt bestätigt automatisch den neuen Host-Key. Bei „resource_unavailable“ hat Hetzner keine Kapazität für den Typ – .\scripts\cloud.ps1 up -Type cpx42 (eine Nummer größer), einen anderen Standort (-Location hel1) oder – falls gerade frei – -Type cx33 / cax21 probieren.

Ab hier übernimmt die Dienst-Anleitung

Server steht. Jetzt zurück in die jeweilige Anleitung – ab dem Punkt „Container starten“ / „kubeconfig holen“ / „compose-Stack“.

10 Danach: was noch

Drei Wege hinein – und welcher noch funktioniert, wenn die anderen versagen.

Zeichnung aus Diagramme: Hetzner & CRC (08).

Server PermitRootLogin no PasswordAuthentication no SSH von der eigenen IP Firewall-Regel /32, Schlüssel Port 22, offen nur für /32 Tailnet von innen aufgebaut, kein Port WireGuard, ausgehend aufgebaut Hetzner-Konsole im Browser hängt am Bildschirm, nicht am Netz VNC am virtuellen Bildschirm – ohne Netz des Servers fällt aus, sobald der Anschluss eine neue Adresse bekommt (Zwangstrennung) fällt aus, wenn der Tailscale-Dienst auf dem Server nicht läuft funktioniert auch dann noch – der Rettungsweg
Wer SSH auf die eigene Adresse begrenzt, sperrt sich irgendwann selbst aus. Das ist kein Argument gegen die Regel – sondern eines dafür, den dritten Weg zu kennen, bevor man ihn braucht. Die Hetzner-Konsole hängt am virtuellen Bildschirm der Maschine und ist von Firewall, Netz und SSH-Konfiguration völlig unabhängig.
ThemaAnleitung
Server abbauen, Snapshot, löschen, Kill-Switch, Kosten stoppenServer-Snapshot & Restore
Kein offener Port mehr – SSH/kubectl/DB übers MeshTailscale
Mehrere Dienste hinter einem Reverse ProxyMehrere Dienste auf einem Server
Verschlüsselte Backups mit getestetem RestoreBackup & Restore
Erfahren, wenn etwas kaputt istMonitoring & Alerting
2FA, Recovery, Impressum, Log-Limits … die Dinge, die man vergisstGrundausstattung
Wo im Webpanel was liegtHetzner Cloud Console

+ Ohne Skripte (reine hcloud-Befehle)

Laptop · PowerShell
$ip = (Invoke-RestMethod 'https://ipv4.icanhazip.com').Trim()
hcloud firewall replace-rules podman-host-fw --rules-file rules.json   # [{"direction":"in","protocol":"tcp","port":"22","source_ips":["'+$ip+'/32"]}]

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

hcloud server ip podman-host
# ... arbeiten ...
hcloud server create-image --type snapshot --description podman-host podman-host
hcloud server delete podman-host

Die Firewall-Regeldatei ohne BOM schreiben ([IO.File]::WriteAllText, nicht Set-Content -Encoding utf8) – sonst scheitert der JSON-Parser von hcloud.

+ Mehrere Server & Projekte

  • Getrennte Projekte für prod / staging / Wegwerf – eigene Tokens, eigene Rechnung, kein versehentliches Löschen über Grenzen. Der Self-Destruct-Timer (cloud-init.selfdestruct.yaml) nur in einem reinen Wegwerf-Projekt.
  • Ein Server für viele Dienste statt vieler kleiner – Mehrere Dienste auf einem Server.
  • Cluster (mehrere Nodes): snapshot.ps1 mit mehreren $SERVERS-Einträgen, feste Primary-IPs optional.
  • Namenskonvention: <zweck>-host (podman-host, k3s-host), Firewall <zweck>-fw – die Skripte leiten das ab.
⌂ Cockpit