windmill
| Field |
Value |
| Service |
windmill |
| Purpose |
Self-hosted developer platform for scripts, flows, schedules, and webhooks |
| Criticality |
Tier 1 |
| Owner |
Platform owner |
| Clusters |
local |
| Namespace |
windmill |
| Exposure |
internet |
| Stateful |
yes |
| Backup class |
snapshot |
| RPO / RTO |
Daily backup target, 2 to 4 hours to restore after the backup path is validated |
| Last reviewed |
2026-08-10 |
1. Service Overview
Windmill is a workflow/script automation platform. This first deployment brings
up a light production-shape standalone stack on the local cluster: server,
two worker groups (default and native), LSP, and a bundled Postgres. It starts
empty — no jobs or flows are migrated.
Summary
If Windmill is unavailable, operators cannot author or run flows on it. No other
service depends on Windmill at this stage.
Dependencies
| Dependency |
Type |
Why it matters |
| Traefik |
ingress |
External HTTPS access to the UI and API |
| Postgres |
database |
Persistent Windmill state (jobs, flows, users, schedules) |
| local-path |
storage |
PVC provisioning for Postgres on layer7-vps1 |
2. Architecture Diagram
[Operator / CLI / API client]
-> [Traefik IngressRoute]
-> [windmill-server Deployment] (MODE=server)
-> [windmill-postgres PVC]
[windmill-worker-default] (MODE=worker, WORKER_GROUP=default, privileged)
[windmill-worker-native] (MODE=worker, WORKER_GROUP=native, NATIVE_MODE)
[windmill-lsp] (windmill-extra image, editor autocomplete)
All pods are pinned to the layer7-vps1 node via nodeAffinity on
kubernetes.io/hostname. Full-text search (the tantivy-based indexer) is
Enterprise-Edition only and is not deployed on the Community-Edition image; the
server falls back to database search.
3. Deployment Specifications
| Item |
Value |
| Source path |
windmill/base and windmill/overlays/local |
| Deployment model |
Kustomize plus Fleet bundle |
| Namespace |
windmill |
| Workload kind |
Deployments (server, 2 workers, lsp) plus Postgres StatefulSet |
| Images |
ghcr.io/windmill-labs/windmill:1.768.0, ghcr.io/windmill-labs/windmill-extra:1.768.0, postgres:16-alpine |
| Storage |
local-path, Postgres 20Gi, single-node (layer7-vps1) |
| Probes |
server HTTP GET / :8000; LSP TCP :3001; Postgres pg_isready; workers have no probe on CE (Ready when running) |
| Node scheduling |
nodeAffinity on kubernetes.io/hostname=layer7-vps1 (no custom node labels) |
| RBAC |
No dedicated RBAC; ServiceAccount token automount disabled |
| Config files |
base/kustomization.yaml, overlays/local/kustomization.yaml, fleet.yaml |
Cluster mapping
| Cluster |
Overlay path |
Notes |
| local |
windmill/overlays/local |
Current standalone deployment |
4. Configuration Guide
Worker groups
| Group |
Privileged |
Mode |
Purpose |
default |
yes |
subprocess jobs (Python/Deno/bash) |
runs job subprocesses with PID-namespace unsharing (FAVOR_UNSHARE_PID=true) |
native |
no |
in-process (NATIVE_MODE=true) |
lightweight in-process jobs, unprivileged |
The privileged default worker is a deliberate, documented exception to the
repository non-root posture: it matches the upstream Helm chart default for the
non-nsjail community-edition worker group. The native worker is unprivileged.
Environment variables
| Variable |
Source |
Purpose |
Secret? |
BASE_URL |
ConfigMap windmill-config |
Public URL (https://windmill.mutana.fr) |
no |
RUST_LOG |
ConfigMap windmill-config |
Log level (info) |
no |
JSON_FMT |
ConfigMap windmill-config |
Structured JSON logs |
no |
DATABASE_URL |
Deployment env expansion |
Postgres connection string, assembled as postgres://$(USER):$(PASSWORD)@windmill-postgres:5432/$(DB) |
yes |
POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB |
Secret windmill-secrets |
Postgres bootstrap and connection values |
yes |
MODE |
Deployment env |
server/worker/indexer |
no |
WORKER_GROUP |
Deployment env |
default or native |
no |
NATIVE_MODE, SLEEP_QUEUE |
Deployment env |
native worker behaviour |
no |
FAVOR_UNSHARE_PID |
Deployment env |
PID-namespace unsharing on the default worker |
no |
DATABASE_URL is assembled by Kubernetes environment-variable expansion, so
POSTGRES_PASSWORD must be URI-safe, or plan a follow-up that stores a
pre-encoded connection string in the Secret.
ConfigMaps
| Resource |
Path |
Purpose |
windmill-config |
windmill/overlays/local/windmill-configmap.yaml |
Non-secret runtime URL, log level, JSON logging |
Secrets management
- Secret name:
windmill-secrets in namespace windmill.
- Required keys:
POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB.
- Source of truth: manually created Kubernetes Secret from an out-of-band env
file based on
windmill-secrets.env.example.
- Rotation trigger: operator-initiated rotation, incident response, or Postgres
credential rotation.
- Recovery note: recreate
windmill-secrets before starting Windmill or
Postgres pods.
5. Access Protocols
| Path |
URL or endpoint |
Audience |
Auth |
TLS terminates at |
| Internal |
windmill-server.windmill.svc.cluster.local:8000 |
Cluster workloads and diagnostics |
namespace access plus Windmill auth |
none internally |
| External |
https://windmill.mutana.fr |
Operators, CLI, API tokens |
Windmill auth (UI login + API tokens) |
Traefik |
Authelia forward auth is intentionally not placed in front of Windmill so that
Windmill's own authentication, API tokens, CLI, and machine-identity flows
remain direct. This matches the Infisical precedent.
6. Operations and Observability
- Primary health indicators: server Deployment ready and
GET / returning 200,
default worker ready, Postgres StatefulSet ready, PVC bound.
- Dashboards or alerts: shared cluster monitoring and ingress health.
- Log locations:
deploy/windmill-server, deploy/windmill-worker-default,
deploy/windmill-worker-native, deploy/windmill-lsp,
statefulset/windmill-postgres.
- Known failure modes: missing
windmill-secrets, URI-unsafe Postgres password
breaking DATABASE_URL, PVC provisioning failure on layer7-vps1, server
blocked on database migration, default worker failing to start without
privilege.
7. Backup and Recovery Notes
- Backup method: snapshot the Postgres PVC and preserve
windmill-secrets.
- Restore prerequisites: restored Postgres PVC data, matching Secret values,
local-path availability on layer7-vps1, and the Traefik route.
- Backup gap: a tested restore drill has not been completed yet.
- Related runbook: ../runbooks/windmill.md
8. Release and Change Notes
- Current deployed app version:
ghcr.io/windmill-labs/windmill:1.768.0.
- Current chart version: N/A (plain Kustomize, chart used only as architecture reference).
- Last significant change: initial standalone local deployment with server, two
worker groups, indexer, LSP, bundled Postgres, Traefik exposure, manual Secret
contract, and node affinity on layer7-vps1.
- Rollback reference: remove or revert the
windmill/ Fleet path and workload
manifests; preserve the Postgres PVC snapshot and Secret values for recovery.