Coolify v4 auf Hetzner selbst hosten: Das komplette Produktions-Setup mit Backups und Monitoring

#coolify hetzner setup
Sandor Farkas - Founder & Lead Developer at Wolf-Tech

Sandor Farkas

Gründer & Lead Developer

Experte für Softwareentwicklung und Legacy-Code-Optimierung

Coolify ist für europäische Teams, die Vercel-artige Deploys auf eigener Hardware wollen, zur Standardantwort geworden, und Hetzner ist der Ort, an dem die meisten davon laufen. Die Installation selbst dauert fünfzehn Minuten. Ein produktionsreifes Coolify-Setup auf Hetzner dauert eher einen Tag, denn produktionsreif heißt: Das Dashboard ist nicht aus dem öffentlichen Internet erreichbar, die Datenbank-Backups haben mindestens eine Restore-Übung überstanden, und irgendetwas weckt dich, wenn um 2 Uhr nachts die Platte vollläuft.

Dieser Leitfaden deckt genau diesen Arbeitstag mit Coolify 4.x ab. Wenn du noch überlegst, ob Coolify überhaupt die richtige Plattform ist, hilft unser Vergleich von Coolify, Dokploy und Kamal bei der Entscheidung. Hier gehen wir davon aus, dass die Entscheidung gefallen ist, und arbeiten alles ab, was zwischen "leerer Hetzner-Account" und "Kunden laufen darauf" liegt.

Was ein produktives Coolify-Setup auf Hetzner umfasst

Sechs Dinge trennen eine Wochenend-Installation von einem Setup, das du gegenüber einem Kunden vertreten kannst: ein Server, der für deine tatsächliche Last dimensioniert ist, eine Firewall, die das Dashboard versteckt, TLS auf jedem Hostnamen inklusive der Coolify-Oberfläche selbst, Datenbank-Backups, die vom Server weg in S3-kompatiblen Speicher wandern, Monitoring mit einem Alarmpfad, der auch dann funktioniert, wenn der ganze Server down ist, und automatische Deploys aus GitHub. Wir gehen sie in dieser Reihenfolge durch und schließen mit den Einstellungen ab, die sich zwischen Symfony- und Next.js-Anwendungen auf derselben Instanz unterscheiden.

Den richtigen Hetzner-Server auswählen

Hetzner hat seine Cloud-Pläne im Juni 2026 neu sortiert und die Preise angepasst, also prüfe die aktuelle Preistabelle, bevor du dich festlegst. Die Planfamilien sind aber stabil: CX-Pläne sind kostenoptimiertes, geteiltes x86, CPX-Pläne laufen auf AMD mit gleichmäßigerer Leistung, und CAX-Pläne laufen auf Ampere-Arm-Kernen mit dem besten Preis pro Kern im Angebot.

PlanAusstattungPasst für
CX222 vCPU, 4 GB RAMEine kleine App plus Coolify selbst. Wird eng, sobald Postgres dazukommt.
CX324 vCPU, 8 GB RAMDer Sweet Spot für ein kleines SaaS: App, Worker, Postgres, Redis.
CAX318 Arm-Kerne, 16 GB RAMMehrere Apps oder Staging plus Produktion auf einer Maschine, zu einem niedrigeren Preis pro Kern.

Zwei Einschränkungen. Coolify selbst frisst mit Proxy und Hilfscontainern rund 1 GB RAM, bevor deine erste App überhaupt startet. Deshalb wird der CX22 so schnell eng. Und die CAX-Reihe ist arm64, also muss jedes Image, das du deployst, für Arm oder als Multi-Arch-Image gebaut sein. Die offiziellen Images für Postgres, Redis und Node sind es alle; deine eigenen Dockerfiles brauchen einen passenden Build-Schritt. Wenn deine CI auf x86-Runnern baut und du auf CAX deployst, aktiviere entweder Multi-Arch-Builds mit buildx oder lass Coolify direkt auf dem Server bauen.

Wähle einen deutschen Standort (Falkenstein oder Nürnberg), wenn Datenresidenz Teil deines Angebots an Kunden ist. Diese eine Entscheidung erledigt in DSGVO-Gesprächen eine Menge Arbeit. Warum das so ist, haben wir in unserem Leitfaden zum SaaS-Hosting in Deutschland beschrieben.

Coolify 4 installieren

Auf einem frischen Ubuntu-24.04-Server erledigt das offizielle Installationsskript die ganze Arbeit:

curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash

Es installiert Docker, startet die Coolify-Container und bringt einen Traefik-Proxy hoch, der später TLS für alles übernimmt. Wenn es fertig ist, lauscht das Dashboard auf Port 8000, und ein Schritt darf nicht warten: Öffne das Dashboard und lege sofort den Admin-Account an. Solange dieser Account nicht existiert, kann sich jeder, der den Port findet, als Besitzer der Instanz registrieren. Account anlegen, dann den Port schließen. Das bringt uns zur Firewall.

Firewall: Das Dashboard hat im öffentlichen Netz nichts verloren

Nutze die Hetzner Cloud Firewall statt iptables auf der Maschine. Sie filtert den Traffic am Netzwerkrand, überlebt Server-Neuaufbauten, und du kannst die gesamte Policy auf einem Bildschirm lesen. Das Regelwerk für einen Coolify-Host:

Inbound 80, 443   from 0.0.0.0/0     (deine Apps)
Inbound 22        from your IPs only (SSH)
Inbound 8000      from your IPs only (Coolify-Dashboard)
Inbound 6001-6002 from your IPs only (Coolify Realtime und Terminal)

Wenn dein Team keine feste Büro-IP hat, setz ein VPN davor, statt die Ports weit zu öffnen. Tailscale ist die Variante mit wenig Aufwand: auf dem Server installieren, und das Dashboard ist von jedem eingebundenen Laptop über die Tailscale-Adresse des Servers erreichbar, bleibt für das Internet aber unsichtbar. Schließ die Arbeit auf der SSH-Seite ab: nur Key-basierter Login, Passwort-Authentifizierung aus.

Eine Sache, die das kaputt macht: GitHub kann keine Webhooks an einen durch die Firewall gesperrten Port 8000 zustellen. Die Lösung steht weiter unten im Deploy-Abschnitt, und sie ist ein Grund, die Instanz-Domain zu konfigurieren, bevor du GitHub anbindest.

Domains und TLS

Richte für jede App einen A-Record auf den Server ein, trage die Domain in den Anwendungseinstellungen ein, und Traefik beantragt und erneuert Let's-Encrypt-Zertifikate von allein. Es gibt keinen certbot, den du betreuen musst.

Mach dasselbe für Coolify selbst. Setze unter den Einstellungen eine Instanz-Domain wie deploy.example.com, und das Dashboard wandert hinter Traefik mit einem ordentlichen Zertifikat auf Port 443. Zusammen mit der Firewall von oben bekommst du die Anordnung, die du eigentlich willst: Die Dashboard-URL löst öffentlich auf, damit Webhooks und OAuth-Callbacks ankommen, aber die Login-Seite liegt hinter HTTPS, und die Ports 8000 sowie 6001 bis 6002 bleiben zu. Wenn du Preview-Deployments nutzen willst, lege einmal einen Wildcard-Record wie *.preview.example.com an, und jeder Pull Request bekommt ohne weiteren Aufwand seinen eigenen Hostnamen mit Zertifikat.

Backups in den Hetzner Object Storage

Ein Datenbank-Backup, das auf derselben Platte liegt wie die Datenbank, verschwindet mit ihr. Schick Backups vom ersten Tag an vom Server weg. Hetzner Object Storage ist S3-kompatibel und sitzt in denselben Rechenzentren, also ist er das naheliegende Ziel: Bucket in deiner Region anlegen, Zugangsdaten erzeugen und in Coolify unter S3-Storages mit Endpoint, zum Beispiel https://fsn1.your-objectstorage.com, plus Key, Secret und Bucket-Name registrieren.

Dann aktivierst du auf jeder Datenbank-Ressource geplante Backups: ein Cron-Ausdruck, das S3-Ziel und eine Aufbewahrungsanzahl. Für ein typisches B2B-SaaS sind nächtliche Dumps mit 14 Tagen Aufbewahrung auf Produktion und keine auf Staging ein vernünftiger Startpunkt. Coolify verschickt eine Benachrichtigung, wenn ein Backup fehlschlägt, aber nur, wenn du einen Benachrichtigungskanal konfigurierst. Richte also unter den Einstellungen E-Mail oder Telegram ein und schalte Backup-Fehler ein. Ein Backup-Job, der seit sechs Wochen still fehlschlägt, ist eine Geschichte, die wir in Code-Audits schon öfter gehört haben.

Der Schritt, den fast alle überspringen: einmal wiederherstellen. Leg auf Staging ein Wegwerf-Postgres an, hol den gestrigen Dump aus dem Bucket, lade ihn und lass deine App dagegen laufen. Bis du das getan hast, weißt du nicht, ob deine Backups funktionieren, du weißt nur, dass Dateien in einem Bucket auftauchen. Notiere, wie lange der Restore gedauert hat; diese Zahl ist deine echte Wiederherstellungszeit, und Kunden werden in Sicherheitsfragebögen danach fragen.

Die Datenbankfrage

Für Postgres in Produktion hast du drei realistische Optionen. Die erste ist ein von Coolify verwalteter Datenbank-Container auf demselben Server, und damit sollten die meisten kleinen Teams anfangen: Die Latenz ist ein Loopback-Interface, die Kosten sind null über den Server hinaus, und der S3-Dump-Zeitplan von oben deckt den Katastrophenfall ab. Die Grenzen sind ehrliche Grenzen. Du bekommst nächtliche Dumps statt Point-in-Time-Recovery, und die Datenbank konkurriert mit deinen Apps um RAM.

Die zweite Option ist ein zweiter Hetzner-Server, auf dem nur Postgres läuft, weiterhin selbst verwaltet, aber isoliert. Das lohnt sich, sobald ein außer Kontrolle geratener App-Prozess, der die Datenbank beeinträchtigt, zu einem echten Risiko wird.

Die dritte ist ein Managed-Anbieter. Hetzner selbst bietet kein Managed Postgres an, also heißt managed hier Drittanbieter: Ubicloud verkauft Managed Postgres auf Hetzner-Hardware in Deutschland, und Supabase, Neon und Aiven haben alle EU-Regionen. Du bezahlst vor allem für Point-in-Time-Recovery, Failover und dafür, nicht die Person zu sein, die autovacuum tunt. Wechsle hierhin, wenn der Verlust von bis zu 24 Stunden Daten nicht mehr akzeptabel ist, und halte die Datenbank in derselben Region wie den Server, denn jede Abfrage überquert diese Strecke.

Monitoring mit Grafana Cloud

Coolify bringt grundlegende Metriken mit: CPU, RAM und Platte pro Container, sichtbar im Dashboard. Das beantwortet "Was passiert gerade", aber nachts schaut niemand auf ein Dashboard, und wenn der Server selbst stirbt, stirbt sein eigenes Monitoring mit. Du brauchst einen Alarmpfad, der woanders lebt.

Der kostenlose Tarif von Grafana Cloud reicht für ein Ein-Server-Setup. Installiere node_exporter auf dem Host, lass Grafana Alloy oder ein kleines Prometheus die Metriken per Remote-Write wegschreiben, und lege drei Alarme an: Plattenbelegung über 80 Prozent, Speicherdruck über 10 Minuten anhaltend und CPU über 15 Minuten am Anschlag. Die Platte ist es, die Coolify-Server tatsächlich lahmlegt, weil sich Docker-Images und Build-Caches ansammeln, bis Deploys fehlschlagen. Ein wöchentlicher docker system prune als geplante Aufgabe in Coolify plus der Platten-Alarm deckt das ab.

Füge einen Uptime-Check von außerhalb der Maschine hinzu, ob als synthetischer Check in Grafana oder über irgendeinen externen Ping-Dienst, gerichtet auf einen Health-Endpoint deiner Haupt-App. Das ist der Alarm, der auch dann noch auslöst, wenn der ganze Server weg ist. Die Begründung für diesen minimalen Stack und was du mit wachsendem Team ergänzen solltest, findest du in unserem Beitrag zu Observability für kleine SaaS-Teams.

Automatische Deploys aus GitHub

Registriere aus Coolify heraus unter Sources eine GitHub App, gib ihr Zugriff auf die Repositories, die du deployst, und Pushes auf deinen Produktions-Branch lösen automatisch Builds aus. Weil die Webhooks über 443 an deiner Instanz-Domain ankommen, ist der gesperrte Dashboard-Port kein Hindernis, vorausgesetzt, du hast die Instanz-Domain zuerst gesetzt.

Schalte Preview-Deployments für die Repositories ein, bei denen sie sich lohnen. Jeder Pull Request bekommt dann einen Build auf seinem eigenen *.preview-Hostnamen, und der Link landet im PR. Auf einem CAX31 kannst du dir das für ein paar aktive Repositories leisten; auf einem CX22 kämpfen die Builds mit deiner Produktionslast, was genauso ein Argument für die Server-Größe wie eine Feature-Entscheidung ist.

Symfony und Next.js auf derselben Instanz

Beides auf einem Coolify-Server zu betreiben funktioniert gut, und die Konfiguration unterscheidet sich an vorhersehbaren Stellen.

Bei Next.js steckt die Arbeit im Build: Standalone-Output-Modus, die Trennung zwischen Build-Zeit- und Laufzeit-Umgebungsvariablen und ein Health-Check-Endpoint, damit Deploys den Traffic nur auf fertige Container umschalten. Die vollständige Checkliste haben wir in Next.js auf Coolify deployen beschrieben.

Symfony braucht drei Dinge, die Next.js nicht braucht. Das Image muss seinen eigenen Webserver enthalten, entweder FrankenPHP oder php-fpm hinter nginx, denn Traefik ist nur Proxy. Datenbank-Migrationen gehören in einen Post-Deployment-Befehl, php bin/console doctrine:migrations:migrate --no-interaction, damit sie genau einmal pro Release laufen. Und Messenger-Worker müssen als eigener Coolify-Service aus demselben Image mit einem messenger:consume-Befehl laufen, denn ein Worker im Web-Container stirbt unbemerkt. Geplante Console-Befehle gehören in die geplanten Aufgaben von Coolify statt in eine Crontab im Container, so bleiben sie an einem Ort sichtbar und protokolliert. Die Produktions-Fallstricke beim Containerisieren von Symfony gelten hier unverändert.

Der Tag nach dem Setup

Keiner der Schritte oben ist für sich genommen schwierig. Der Wert liegt darin, alle zu erledigen, bevor echter Traffic ankommt, denn jeder einzelne ist unter Druck lästig nachzurüsten: Teams neigen dazu, die Firewall nach dem Vorfall dichtzumachen und die Backups nach dem Datenverlust zu testen. Ein sauber umgesetztes Coolify-Setup auf Hetzner gibt einem kleinen Team das meiste von dem, was eine Managed-Plattform verkauft, für einen Bruchteil der monatlichen Rechnung und mit den Daten auf Servern, die du selbst ausgesucht hast.

Wenn du ein zweites Paar Augen auf dein Setup haben möchtest oder den Umzug weg von einer Managed-Plattform planst und die Migration langweilig verlaufen soll: Das ist Arbeit, die wir regelmäßig im Rahmen unserer Tech-Stack-Strategie und individuellen Softwareentwicklung übernehmen. Schreib an hello@wolf-tech.io oder besuche wolf-tech.io und bring deine aktuelle Architektur mit, wir sagen dir, was wir ändern würden.