tva
← Insights

Self-Hosting Windmill in 2026: Workers, PostgreSQL, Isolation, and Safe Upgrades

A current, production-oriented follow-up that turns vendor guidance into operating controls, migration decisions, and verifiable release criteria.

What changed in 2026

We revisited this subject because the operating boundary has moved. The durable principles remain useful, but current versions make several old shortcuts incomplete or unsafe. This follow-up starts with the vendor documentation available on 14 July 2026, separates facts from local choices, and treats every configuration change as a controlled production intervention.

Current primary sources

How we use the update

Read the sources first, record the versions actually deployed, and define the observable result before changing a setting. Test the smallest reversible intervention in a representative environment. A successful command is not the acceptance criterion: service health, data integrity, latency, security boundaries, and rollback time are. Where the earlier guide offers a useful diagnostic sequence, we retain it below as an operating foundation; version-specific examples must still be checked against the current documentation.

Before release, capture a configuration diff, a backup or snapshot that has been restored at least once, and the commands needed to reverse the intervention. Assign one person to observe the first production window and another to approve escalation if the expected indicators move in the wrong direction. Alerts should describe the user-visible risk, not merely the component that emitted them. During the readback window, compare error rates, queue depth, resource saturation, processing latency, and data completeness with the agreed baseline. Review both averages and tail behaviour, because a stable average can conceal failures affecting a small but important share of work. Close the change only after delayed jobs, retries, scheduled tasks, and downstream exports have completed. Record any manual action taken during recovery; an undocumented rescue step is evidence that the runbook is not yet complete. This release discipline creates evidence that can be reused at the next upgrade instead of forcing the team to rediscover the same dependencies.

Operating foundation

Workflow automation platforms are essential for modern development teams, but cloud solutions like Windmill Cloud can become expensive as usage grows. We’ll show you how to set up your own Windmill instance on Ubuntu with Docker Compose and Traefik integration, overcoming critical PostgreSQL authentication issues that can derail your installation.

What You’ll Build

By the end of this tutorial, you’ll have:

  • ✅ Fully functional Windmill installation with HTTPS
  • ✅ Automatic SSL certificates via Let’s Encrypt through Traefik
  • ✅ Production-ready PostgreSQL database with proper authentication
  • ✅ Resource-optimized worker configuration
  • ✅ Integrated with existing Docker infrastructure
  • ✅ Production-ready setup for professional workflow automation

Monthly cost: €4.51 (CX11 server) + domain costs – same infrastructure that can handle multiple automation tools

Prerequisites

  • Ubuntu 24.04 LTS server with Docker and Docker Compose installed
  • Existing Traefik reverse proxy setup (see our n8n setup guide for Traefik configuration)
  • Domain name pointing to your server IP
  • At least 4GB RAM and 2 vCPUs recommended
  • SSH access and basic command line knowledge

Understanding Windmill

Windmill is an open-source workflow engine that provides:

  • Visual workflow editor with TypeScript/Python/Go support
  • Job scheduling and execution management
  • API integration capabilities
  • Team collaboration features
  • Self-hostable with no usage limits

Unlike n8n’s node-based approach, Windmill focuses on code-first workflows with a powerful development environment.

Step 1: Server Preparation and Directory Structure

First, let’s prepare our server environment. We’ll use a food-based naming convention for Windmill instances to avoid conflicts:

Naming Convention: Use simple food names for multiple Windmill instances:

  • First instance: pizza
  • Additional instances: pasta, salad, soup, burger, etc.
  • This avoids conflicts and makes management easier

Step 2: Environment Configuration

Create a secure environment file with proper credentials:

Critical: Replace windmill.yourdomain.com with your actual domain!

Step 3: Docker Compose Configuration

Create the main Docker Compose configuration:

Important: Update the domain in the Traefik labels to match your setup!

Step 4: The PostgreSQL Password Problem (Critical Issue)

Here’s where most Windmill installations fail, and it took considerable troubleshooting to identify the root cause:

The Problem: Special Characters in Passwords

When using openssl rand -base64 32 to generate passwords, you often get special characters like =, @, #, %, etc. These characters cause PostgreSQL authentication failures in Docker environments, even when properly escaped.

Example of a problematic password:

The Solution: Hex-Only Passwords

Use hex-only passwords that contain no special characters:

Additional PostgreSQL Configuration Issues

  • User Configuration: Use postgres as the default user, not custom users like windmill_user
  • Volume Persistence: PostgreSQL ignores POSTGRES_PASSWORD environment variables when existing data volumes contain different credentials
  • URL Format: Include ?sslmode=disable in the database URL for Docker environments

Step 5: Installation and Startup

Now let’s install Windmill with our corrected configuration:

You should see output like:

Step 6: Troubleshooting Common Issues

Issue 1: PostgreSQL Authentication Failures

Symptoms:

Solution:

Issue 2: Container Won’t Start

Symptoms:

  • Container exits immediately
  • Resource allocation errors

Solution:

Issue 3: SSL Certificate Issues

Symptoms:

  • HTTPS not working
  • Certificate errors

Solution:

Step 7: Access and Initial Setup

Once installation is complete:

  • Access Windmill: https://windmill.yourdomain.com
  • Default credentials:

Email: [email protected]

  • Password: changeme
  • Complete setup:

Change admin password

  • Configure base URL
  • Set up user accounts

Step 8: Resource Optimization

Memory Allocation (for 8GB server)

Our configuration allocates resources efficiently:

  • Windmill Server: ~800MB
  • Windmill Worker: 2GB (limited)
  • PostgreSQL: ~500MB
  • System Reserve: ~4.7GB

CPU Allocation (for 4 vCPU server)

  • Worker: 1 vCPU (limited)
  • Other services: 3 vCPUs (shared)

Scaling rule: 1 worker per vCPU with 1-2GB RAM each

Step 9: Production Hardening

Create Backup Script

Set Up Monitoring

Configure Automated Updates

Step 10: Advanced Configuration

Integration with Existing SMTP

If you have a mailserver (like from our n8n setup), integrate it:

Multiple Windmill Instances

For teams requiring isolated environments:

Security Considerations

Network Isolation

  • PostgreSQL only accessible within Docker network
  • No external database ports exposed
  • HTTPS termination at Traefik level

Resource Limits

  • Worker containers have CPU and memory limits
  • Prevents resource exhaustion attacks
  • Configurable based on server capacity

SSL Security

  • Automatic Let’s Encrypt certificates
  • HTTP to HTTPS redirects
  • Modern TLS configuration

Monitoring and Maintenance

Weekly Health Checks

Monthly Maintenance

Cost Breakdown and Comparison

Monthly Costs

Self-hosted setup:

  • Hetzner CX21 (4GB RAM): €8.46/month
  • Domain costs: ~€1/month
  • Total: ~€9.50/month

Windmill Cloud comparison:

  • Team plan: $30/month per user
  • Savings: $250+ annually for small teams

Performance Benefits

Self-hosted advantages:

  • Unlimited workflow executions
  • No external rate limits
  • Full data control
  • Custom integrations
  • Resource scaling flexibility

Troubleshooting Reference

Quick Diagnostics

Common Error Patterns

  • “password authentication failed” → Use hex passwords, clear volumes
  • “connection refused” → Check network configuration
  • “certificate errors” → Verify DNS and Traefik setup
  • “out of memory” → Adjust worker resource limits

Scaling Your Windmill Infrastructure

Horizontal Scaling

For high-volume environments:

Vertical Scaling

Upgrade server resources:

  • CX31 (8GB RAM): €16.07/month for heavy workloads
  • CX41 (16GB RAM): €29.75/month for enterprise usage

Integration with Existing Infrastructure

Working with n8n

If you’re already running n8n (from our previous tutorials):

  • Windmill handles code-first workflows
  • n8n handles visual, simple automations
  • Both share the same Traefik proxy
  • Separate databases prevent conflicts

Shared Services

Leverage existing infrastructure:

  • Traefik: Handles SSL for all services
  • Mailserver: Shared SMTP for notifications
  • Monitoring: Unified logging and metrics
  • Backups: Centralized backup strategy

Conclusion

Self-hosting Windmill provides enterprise-grade workflow automation at a fraction of cloud hosting costs. The key to success is understanding the PostgreSQL authentication requirements and using hex-only passwords to avoid special character issues that can derail installations.

Key Benefits of This Setup

  • Cost-effective: Save hundreds annually compared to cloud solutions
  • Production-ready: Handles enterprise workloads reliably
  • Secure: HTTPS, isolated networks, and resource limits
  • Scalable: Easy to add workers and resources as needed
  • Private: Your code and data never leave your infrastructure

This configuration has been tested in production environments and provides the reliability needed for business-critical workflow automation. The troubleshooting steps address real-world issues encountered during deployment, particularly the PostgreSQL authentication problems that affect many self-hosted installations.

For complex workflow requirements or enterprise deployments, consider professional consultation to optimize your specific use case and ensure optimal resource allocation.

Next Steps

  • Explore webhook troubleshooting techniques that apply to Windmill
  • Review payload optimization for handling large datasets
  • Consider integration with existing n8n installations

About tva

tva ensures comprehensive infrastructure management of database systems, cloud environments, and global supply chains. Our methodical approach combines rigorous security protocols with performance optimization, while strategic advisory services enable precise coordination of both digital capabilities and physical assets – maintaining the highest standards of operational excellence and compliance throughout all engagements.

Visit tva.sg for more information about our services and additional automation tutorials.

From configuration to an operating decision

The practical question is not whether a platform can be configured. It is whether the team can explain ownership, detect drift, recover without improvisation, and demonstrate that the change improved the intended outcome. We therefore pair configuration with an owner, a baseline, a rollback path, and a readback window. That turns a one-off fix into an operating capability. The production record should include the reason for the change, the evidence reviewed, the exact scope, and the person authorised to stop or reverse it. After release, compare the agreed indicators with the baseline and keep the result with the change record. If the expected improvement is absent, rollback is a valid outcome rather than a failure. This discipline matters more than any individual configuration value. The same record gives the next operator a trustworthy starting point and makes later optimisation a measured decision rather than another round of guesswork.

Related Insights

Further Reading