Windmill verwandelt Skripte in Webhooks, Workflows, Cronjobs und interne Oberflächen - eine Open-Source-Alternative zu Retool und Temporal. Das Selbsthosting ist unkompliziert, mit einem Haken, den man vorher kennen sollte: Redis wird nicht verwendet, was immer eine Reihe von Anleitungen im Netz behauptet.
Warum Windmill selbst hosten?
Der Cloud-Tarif rechnet pro Nutzer und pro Ausführung ab. Selbsthosting entfernt beide Zähler, was bei einer Automatisierungsplattform besonders zählt: Genau die Jobs, die du am liebsten regelmäßig laufen lässt, würden sonst laufend Ausführungskosten anhäufen. Außerdem bleiben deine Skripte, Zugangsdaten und Job-Logs auf deiner eigenen Maschine - und diese Skripte enthalten üblicherweise API-Schlüssel für alles Übrige, was du betreibst.
Die Community Edition steht unter AGPL-3.0. Die Enterprise-Variante liegt hinter einem Lizenzschlüssel und einem anderen Image-Tag; für den Betrieb der Plattform brauchst du sie nicht.
Den richtigen VPS wählen
Windmill dimensioniert man pro Worker, nicht pro Anwendung. Als Faustregel gilt ein Worker je vCPU mit 1-2 GB RAM, zusätzlich zu Postgres und dem Server-Prozess.
| Anbieter | Tarif | vCPU / RAM / Speicher | Preis | Anmerkungen | Link |
|---|---|---|---|---|---|
| Contabo | Cloud VPS 4 | 4 / 8 GB / 100 GB SSD | 5,50 EUR/Mo netto | Vier Kerne bedeuten Parallelität für vier Worker | Contabo |
| Hetzner Cloud | CX23 | 2 / 4 GB / 40 GB NVMe | 5,49 EUR/Mo netto | Passt zum Standard-Stack mit zwei Workern | Hetzner |
| DigitalOcean | Basic 4 GB | 2 / 4 GB / 80 GB SSD | 24 USD/Mo | Gleiche Specs wie CX23 zum vierfachen Preis | DigitalOcean |
| Vultr | Regular 4 GB | 2 / 4 GB / 80 GB SSD | 20 USD/Mo | Größte Regionsauswahl | Vultr |
| Linode | Linode 4 GB | 2 / 4 GB / 80 GB SSD | 24 USD/Mo | Vorhersehbare Leistung | Linode |
Weil der Durchsatz mit der Worker-Anzahl steigt, zählt hier die Kernanzahl mehr als die Taktrate. Für einen ausführlichen Vergleich besuche unsere Seite vollständiger VPS-Vergleich.
Voraussetzungen
- Ein VPS mit Ubuntu 24.04 LTS, mindestens 2 vCPU und 4 GB RAM
- Docker Engine und Compose v2
- Eine auf den Server zeigende Domain, falls du TLS möchtest
Schritt 1: Den VPS vorbereiten
Verbinden und aktualisieren:
ssh root@deine-vps-ip
apt update && apt upgrade -y
Docker und das Compose-Plugin installieren:
apt install -y docker.io docker-compose-v2
systemctl enable --now docker
docker compose version
Die Ports freigeben, die Caddy nutzt:
ufw allow OpenSSH && ufw allow 80 && ufw allow 443
ufw enable
Schritt 2: Den offiziellen Compose-Stack holen
Schreibe für Windmill keine eigene Compose-Datei. Das Projekt veröffentlicht eine, und sie verdrahtet Worker, Indexer und Language Server korrekt:
mkdir -p ~/windmill && cd ~/windmill
curl -fsSL -o docker-compose.yml https://raw.githubusercontent.com/windmill-labs/windmill/main/docker-compose.yml
curl -fsSL -o .env https://raw.githubusercontent.com/windmill-labs/windmill/main/.env
curl -fsSL -o Caddyfile https://raw.githubusercontent.com/windmill-labs/windmill/main/Caddyfile
Der eben geladene Stack betreibt sieben Dienste:
db-postgres:16, die Datenbank und die Job-Queuewindmill_server- API und Web-UI auf Port 8000windmill_worker- führt Jobs auswindmill_worker_native- leichtgewichtige Jobs mit rund 0,1 CPU und 128 MBwindmill_indexer- Volltextsuche über die Job-Historiewindmill_extra- Language Server für den Editor im Browsercaddy- Reverse Proxy auf Port 80
In dieser Liste steht kein Redis, und in deiner sollte auch keines stehen.
Schritt 3: Passwort und Domain setzen
Die mitgelieferte .env enthält einen bewusst schwachen Standardwert:
DATABASE_URL=postgres://postgres:changeme@db/windmill?sslmode=disable
WM_IMAGE=ghcr.io/windmill-labs/windmill:main
Ändere changeme vor dem ersten Start in ein erzeugtes Geheimnis, denn die Datenbank wird bei genau diesem Start angelegt:
openssl rand -hex 24
Setze in derselben Datei BASE_URL auf deine Domain. Caddy liest sie, um ein Zertifikat anzufordern.
Schritt 4: Starten
docker compose up -d
docker compose ps
Der erste Start lädt mehrere Images und führt die Datenbankmigrationen aus, gib ihm also eine Minute. Rufe deine Domain auf und lege das erste Konto an - es wird Superadmin der Instanz.
Schritt 5: Worker ergänzen, wenn du sie brauchst
Das unterscheidet Windmill von den meisten selbst gehosteten Anwendungen. Du skalierst nicht, indem ein Prozess größer wird, sondern indem du Worker-Container hinzufügst. Kopiere den windmill_worker-Block in der docker-compose.yml, gib ihm einen neuen Dienstnamen, behalte dieselbe DATABASE_URL und MODE=worker und wende es an:
docker compose up -d
Die Worker stimmen sich über Postgres ab, sonst ändert sich nichts an der Konfiguration. Rechne je Worker grob mit einer vCPU und 1-2 GB RAM.
Schritt 6: Die Datenbank sichern
Alles Wesentliche - Skripte, Flows, Zeitpläne, Ressourcen, Job-Historie - liegt in Postgres. Das Volume mit dem Dependency-Cache sind abgeleitete Daten und baut sich selbst wieder auf.
docker compose exec db pg_dump -U postgres windmill | gzip > windmill-$(date +%F).sql.gz
Kopiere die Datei vom Server herunter. Beachte, dass Windmill Zugangsdaten für deine anderen Systeme speichert - behandle den Dump als Geheimnis und verschlüssele ihn im Ruhezustand.
Wo Leute hängen bleiben
Eine Redis-basierte Compose-Datei aus einem Blog kopieren. Windmill hat nie eine gebraucht. Der Container startet und liegt einfach brach, während du dich fragst, warum die Queue ihn nicht nutzt.
Nach dem Dauerbetrieb dimensionieren. Die Installation von Abhängigkeiten ist die Speicherspitze. Ein Python-Job, der pandas importiert, braucht beim ersten Lauf weit mehr RAM als bei jedem weiteren - ein Stack, der im Leerlauf gut aussieht, kann an einem kalten Job scheitern.
changeme stehen lassen. Es ist das Postgres-Passwort in der veröffentlichten .env und das Erste, was ein Gelegenheitsscan probiert, falls du Port 5432 jemals nach außen öffnest.
Windmill belohnt eine Maschine mit mehr Kernen statt mit schnelleren, was die günstigen europäischen Mehrkern-Tarife hier ungewöhnlich attraktiv macht. Dimensioniere nach der Zahl der Jobs, die gleichzeitig laufen sollen, lege den Postgres-Dump verschlüsselt an einem anderen Ort ab, und der Dienst ist pflegeleicht.
Weitere Projekte und Tipps rund ums Selbsthosting findest du in der Liste awesome-selfhosted und in der Community r/selfhosted.
Frequently asked questions
Brauche ich Redis, um Windmill selbst zu hosten?
Nein, und daran scheitern viele. Windmill nutzt PostgreSQL sowohl als Datenbank als auch als Job-Queue, deshalb enthält die offizielle Compose-Datei keinen Redis-Dienst und keine REDIS_URL. Mehrere fremde Anleitungen ergänzen trotzdem einen. Wer eine Compose-Datei mit Redis-Container kopiert hat, betreibt einen Dienst, mit dem Windmill nie spricht, und kann ihn gefahrlos entfernen.
Wie füge ich einer laufenden Windmill-Instanz weitere Worker hinzu?
Ergänze in der Compose-Datei einen weiteren windmill_worker-Dienst mit derselben DATABASE_URL und MODE=worker und führe docker compose up -d aus. Die Worker stimmen sich über Postgres ab, sonst muss nichts angepasst werden. Die praktische Grenze ist die Kernanzahl: Jeder Standard-Worker führt einen Job zur Zeit aus und will grob eine vCPU und 1-2 GB RAM.
Wie stelle ich Windmill auf HTTPS um?
Der Stack bringt Caddy bereits mit, das standardmäßig einfaches HTTP auf Port 80 ausliefert. Für automatisches TLS setzt du BASE_URL auf deine Domain und passt Caddyfile sowie den caddy-Dienst an, damit Port 443 freigegeben wird, wie es die Kommentare in der mitgelieferten .env beschreiben. Richte DNS vor dem Start auf den Server, damit das Zertifikat beim ersten Hochfahren ausgestellt werden kann.