tva
← Analyses

Auto-héberger Windmill en 2026 : workers, PostgreSQL, isolation et mises à niveau sûres

Un article de suivi actuel et orienté production, qui traduit la documentation des éditeurs en contrôles opérationnels, décisions de migration et critères de mise en service vérifiables.

Ce qui a changé en 2026

Nous revenons sur ce sujet parce que les limites opérationnelles ont évolué. Les principes durables restent pertinents, mais les versions actuelles rendent certains anciens raccourcis incomplets ou risqués. Ce suivi part de la documentation des éditeurs disponible au 14 juillet 2026, distingue les faits des choix locaux et traite chaque modification de configuration comme une intervention contrôlée en production.

Sources primaires actuelles

Comment exploiter cette mise à jour

Lisez d’abord les sources, consignez les versions réellement déployées et définissez le résultat observable avant de modifier un paramètre. Testez la plus petite intervention réversible dans un environnement représentatif. Une commande réussie ne constitue pas le critère d’acceptation : l’état du service, l’intégrité des données, la latence, les limites de sécurité et le délai de retour à la version précédente le sont. Lorsque l’ancien guide propose une séquence de diagnostic utile, nous la conservons ci-dessous comme socle opérationnel ; les exemples propres à une version doivent toutefois être vérifiés dans la documentation actuelle.

Avant la mise en service, conservez un relevé des différences de configuration, une sauvegarde ou un instantané dont la restauration a été testée au moins une fois, ainsi que les commandes nécessaires pour annuler l’intervention. Désignez une personne pour observer la première fenêtre de production et une autre pour autoriser l’escalade si les indicateurs attendus évoluent dans le mauvais sens. Les alertes doivent décrire le risque visible pour l’utilisateur, pas seulement le composant qui les a émises. Pendant la période de vérification après action, comparez les taux d’erreur, la longueur des files d’attente, la saturation des ressources, la latence de traitement et l’exhaustivité des données à la référence convenue. Examinez les moyennes et les valeurs extrêmes, car une moyenne stable peut masquer des échecs touchant une part réduite mais importante des opérations. Ne clôturez le changement qu’après l’achèvement des tâches différées, des nouvelles tentatives, des tâches planifiées et des exportations en aval. Consignez toute intervention manuelle effectuée pendant la récupération : une mesure de secours non documentée indique que la procédure d’exploitation est encore incomplète. Cette discipline de mise en service produit des éléments vérifiables réutilisables lors de la prochaine mise à niveau, au lieu d’obliger l’équipe à redécouvrir les mêmes dépendances.

Socle opérationnel

Les plateformes d’automatisation des flux de travail sont essentielles pour les équipes de développement modernes, mais les solutions cloud comme Windmill Cloud peuvent devenir coûteuses à mesure que l’utilisation augmente. Nous vous montrons comment configurer votre propre instance Windmill sur Ubuntu avec Docker Compose et l’intégration Traefik, en surmontant les problèmes critiques d’authentification PostgreSQL qui peuvent faire échouer votre installation.

Ce que vous allez construire

À la fin de ce tutoriel, vous disposerez de :

  • ✅ Une installation Windmill entièrement fonctionnelle avec HTTPS
  • ✅ Certificats SSL automatiques délivrés par Let’s Encrypt via Traefik
  • ✅ Base de données PostgreSQL prête pour la production avec authentification correctement configurée
  • ✅ Configuration des workers optimisée pour l’utilisation des ressources
  • ✅ Configuration prête pour la production pour l’automatisation professionnelle des flux de travail

Coût mensuel : à partir de 5,99 € HT, avec une adresse IPv4 principale incluse (Hetzner CX23, 4 Go de RAM, en octobre 2026) + frais de domaine – la même infrastructure peut gérer plusieurs outils d’automatisation

Prérequis

  • Serveur Ubuntu 24.04 LTS avec Docker et Docker Compose installés
  • Configuration existante du proxy inverse Traefik (voir notre guide de configuration n8n pour la configuration Traefik)
  • Nom de domaine pointant vers l’IP de votre serveur
  • Au moins 4 Go de RAM et 2 vCPU recommandés
  • Accès SSH et connaissances de base en ligne de commande

Comprendre Windmill

Windmill est un moteur de flux de travail open source qui fournit :

  • Éditeur visuel de flux de travail prenant en charge TypeScript/Python/Go
  • Planification de tâches et gestion de l’exécution
  • Fonctionnalités d’intégration d’API
  • Fonctionnalités de collaboration en équipe
  • Auto-hébergeable, avec des exécutions illimitées dans la Community Edition gratuite

Contrairement à l’approche par nœuds de n8n, Windmill se concentre sur les flux de travail conçus autour du code avec un puissant environnement de développement.

Étape 1 : préparation du serveur et structure des répertoires

Tout d’abord, préparons notre environnement serveur. Nous utiliserons une convention de nommage basée sur la nourriture pour les instances Windmill afin d’éviter les conflits :

# Create Windmill directory (first instance: "pizza")
mkdir -p /opt/windmill-pizza
cd /opt/windmill-pizza

# Create required subdirectories
mkdir -p postgres-data windmill-data lsp-cache

# Verify directory structure
ls -la

Convention de nommage : utilisez des noms de plats simples pour les différentes instances Windmill :

  • Première instance : pizza
  • Instances supplémentaires : pasta, salad, soup, burger, etc.
  • Cela évite les conflits et facilite la gestion

Étape 2 : configuration de l’environnement

Créez un fichier d’environnement sécurisé avec des identifiants adéquats :

# Generate a secure hex password (no special characters!)
SECURE_PASSWORD=$(openssl rand -hex 16)

# Create environment file
cat > /opt/windmill-pizza/.env << EOF
# Windmill Image Version (pin a release; change it deliberately when you update)
WM_IMAGE=ghcr.io/windmill-labs/windmill:1.767.0

# Database Configuration - SECURE PASSWORDS
DATABASE_URL=postgresql://postgres:${SECURE_PASSWORD}@windmill-db:5432/windmill_pizza?sslmode=disable
POSTGRES_PASSWORD=${SECURE_PASSWORD}
POSTGRES_DB=windmill_pizza
POSTGRES_USER=postgres

# Windmill Configuration
BASE_URL=https://windmill.yourdomain.com
RUST_LOG=info

# Worker Configuration
WORKER_GROUP=default
KEEP_JOB_DIR=false

# Instance Identifier
INSTANCE_NAME=pizza
EOF

# The file holds the database password: make it readable by its owner only
chmod 600 /opt/windmill-pizza/.env

Critique : remplacez windmill.yourdomain.com par votre véritable domaine !

Étape 3 : configuration de Docker Compose

Créez la configuration principale de Docker Compose :

cat > /opt/windmill-pizza/docker-compose.yml << 'EOF'
services:
  # PostgreSQL Database for Windmill
  windmill-db:
    image: postgres:16
    container_name: windmill-pizza-db
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
    networks:
      - proxy
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Windmill Server
  windmill-server:
    image: ${WM_IMAGE}
    container_name: windmill-pizza-server
    restart: unless-stopped
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - BASE_URL=${BASE_URL}
      - RUST_LOG=${RUST_LOG}
      - MODE=server
    networks:
      - proxy
    depends_on:
      windmill-db:
        condition: service_healthy
    volumes:
      - ./windmill-data:/tmp/windmill
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.windmill-pizza.rule=Host(`windmill.yourdomain.com`)"
      - "traefik.http.routers.windmill-pizza.entrypoints=https"
      - "traefik.http.routers.windmill-pizza.tls.certresolver=letsencrypt"
      - "traefik.http.services.windmill-pizza.loadbalancer.server.port=8000"

  # Windmill Worker
  windmill-worker:
    image: ${WM_IMAGE}
    container_name: windmill-pizza-worker
    restart: unless-stopped
    environment:
      - DATABASE_URL=${DATABASE_URL}
      - BASE_URL=${BASE_URL}
      - RUST_LOG=${RUST_LOG}
      - MODE=worker
      - WORKER_GROUP=${WORKER_GROUP}
      - KEEP_JOB_DIR=${KEEP_JOB_DIR}
    networks:
      - proxy
    depends_on:
      windmill-db:
        condition: service_healthy
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./windmill-data:/tmp/windmill
      - worker_dependency_cache:/tmp/windmill/cache
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 2G

networks:
  proxy:
    external: true

volumes:
  worker_dependency_cache:
    driver: local
EOF

Important : mettez à jour le domaine dans les étiquettes Traefik pour qu’il corresponde à votre configuration !

Étape 4 : le problème des mots de passe PostgreSQL (problème critique)

C’est ici que la plupart des installations Windmill échouent, et il a fallu un important travail de diagnostic pour en identifier la cause :

Le problème : les caractères spéciaux dans les mots de passe

Lors de l’utilisation de la commande openssl rand -base64 32 pour générer des mots de passe, le résultat peut contenir +, / et =. Dans DATABASE_URL, ces caractères doivent être encodés en pourcentage ; sans cet encodage, ils peuvent perturber l’analyse de l’URL et se manifester par des échecs d’authentification PostgreSQL. Les mots de passe hexadécimaux évitent entièrement cette étape d’encodage.

Exemple de mot de passe problématique :

# Unless percent-encoded, the "/" in this password breaks DATABASE_URL:
PASSWORD="305t6m9KrChkvbyN/FLEYQ6pqAGlApn9rbJPH3D5y9g="

La solution : des mots de passe hexadécimaux uniquement

Utilisez des mots de passe hexadécimaux qui ne contiennent aucun caractère spécial :

# This WORKS reliably:
PASSWORD=$(openssl rand -hex 16)
# Example result: 5781b14ec0ec1bc184653ffa5e379411

Problèmes de configuration PostgreSQL supplémentaires

  • Configuration utilisateur : utilisez le superutilisateur postgres, comme dans la configuration d’exemple de Windmill. Un utilisateur personnalisé ne fonctionne qu’après l’attribution des rôles windmill_admin et windmill_user nécessaires aux migrations de Windmill (voir la documentation d’auto-hébergement de Windmill)
  • Persistance des volumes : postgreSQL ignore les variables d’environnement POSTGRES_PASSWORD lorsque les volumes de données existants contiennent des identifiants différents
  • Format d’URL : incluez ?sslmode=disable dans l’URL de la base de données lorsque celle-ci n’est accessible que sur le réseau Docker interne, comme dans la configuration d’exemple de Windmill ; utilisez un mode SSL tel que require pour les bases de données accessibles via d’autres réseaux

Étape 5 : installation et démarrage

Installons maintenant Windmill avec notre configuration corrigée :

cd /opt/windmill-pizza

# Verify configuration syntax
docker compose config --quiet

# Pull images
docker compose pull

# Start services
docker compose up -d

# Check status
docker compose ps

Vous devriez voir une sortie comme :

NAME                    STATUS                    PORTS
windmill-pizza-db       Up (healthy)              5432/tcp
windmill-pizza-server   Up                        8000/tcp
windmill-pizza-worker   Up                        8000/tcp

Étape 6 : résolution des problèmes courants

Problème 1 : échecs d’authentification PostgreSQL

Symptômes :

windmill-pizza-server | Error: password authentication failed for user "postgres"

Solution : la réinitialisation de la base de données supprime toutes les données de Windmill. Ne l’effectuez que sur une nouvelle installation ou après une sauvegarde vérifiée.

# WARNING: this deletes all Windmill data (fresh install or verified backup only)
cd /opt/windmill-pizza

# Stop containers
docker compose down --volumes

# Remove old data
rm -rf /opt/windmill-pizza/postgres-data/*

# Regenerate hex password and write it to both variables
NEW_PASSWORD=$(openssl rand -hex 16)
sed -i "s/^POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$NEW_PASSWORD/" .env
sed -i "s|^DATABASE_URL=postgresql://postgres:[^@]*@|DATABASE_URL=postgresql://postgres:$NEW_PASSWORD@|" .env

# Restart
docker compose up -d

Problème 2 : le conteneur ne démarre pas

Symptômes :

  • Le conteneur s’arrête immédiatement
  • Erreurs d’allocation de ressources

Solution :

# Check container logs
docker logs windmill-pizza-server
docker logs windmill-pizza-db

# Check system resources
docker stats
free -h

Problème 3 : problèmes de certificat SSL

Symptômes :

  • HTTPS ne fonctionne pas
  • Erreurs de certificat

Solution :

# Check Traefik logs
docker logs traefik

# Verify DNS resolution
nslookup windmill.yourdomain.com

# Restart Traefik if needed
docker restart traefik

Étape 7 : accès et configuration initiale

Une fois l’installation terminée :

  • Accédez à Windmill : https://windmill.yourdomain.com
  • Identifiants par défaut :

E-mail : [email protected]

  • Mot de passe : changeme
  • Terminez la configuration :

Changez le mot de passe de l’administrateur

  • Configurez l’URL de base
  • Créez les comptes utilisateurs

Étape 8 : optimisation des ressources

Allocation de mémoire (pour un serveur de 8 Go)

Notre configuration alloue les ressources efficacement :

  • Serveur Windmill : ~800 Mo
  • Worker Windmill : 2 Go (limité)
  • PostgreSQL : ~500 Mo
  • Réserve système : ~4,7 Go

Allocation de CPU (pour un serveur de 4 vCPU)

  • Worker : 1 vCPU (limité)
  • Autres services : 3 vCPU (partagés)

Règle de dimensionnement : 1 worker par vCPU avec 1-2 Go de RAM chacun

Étape 9 : renforcement pour la production

Créer un script de sauvegarde

cat > /opt/windmill-pizza/backup.sh << 'EOF'
#!/bin/bash
set -euo pipefail
umask 077

# docker compose needs the project directory, also when run from cron
cd /opt/windmill-pizza

DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE=/opt/backups/windmill_pizza_${DATE}.sql
mkdir -p /opt/backups

if ! docker compose exec -T windmill-db pg_dump -U postgres windmill_pizza > "$BACKUP_FILE" || [ ! -s "$BACKUP_FILE" ]; then
  rm -f "$BACKUP_FILE"
  echo "Backup FAILED" >&2
  exit 1
fi
echo "Backup created: $BACKUP_FILE"
EOF

chmod +x /opt/windmill-pizza/backup.sh

Configurer la supervision

cd /opt/windmill-pizza

# Monitor container health
docker compose ps

# Check resource usage
docker stats

# Monitor logs
docker compose logs -f windmill-server

Configurer les mises à jour automatisées

cat > /opt/windmill-pizza/update.sh << 'EOF'
#!/bin/bash
set -euo pipefail
cd /opt/windmill-pizza

# Back up first; stop here if the backup fails
./backup.sh

# Pull and start the images set in .env (raise WM_IMAGE there to update Windmill)
docker compose pull
docker compose up -d
EOF

chmod +x /opt/windmill-pizza/update.sh

Étape 10 : configuration avancée

Intégration avec un serveur SMTP existant

Si vous disposez d’un serveur de messagerie (comme dans notre configuration n8n), intégrez-le :

# Add to docker-compose.yml environment for windmill-server:
- SMTP_HOST=mailserver
- SMTP_PORT=25
- [email protected]
# Only if your mail server requires authentication:
# - SMTP_USERNAME=...
# - SMTP_PASSWORD=...

Plusieurs instances Windmill

Pour les équipes qui ont besoin d’environnements isolés :

# Create second instance from the configuration files only (not the data)
mkdir -p /opt/windmill-pasta/{postgres-data,windmill-data,lsp-cache}
cp /opt/windmill-pizza/{.env,docker-compose.yml,backup.sh,update.sh} /opt/windmill-pasta/
chmod 600 /opt/windmill-pasta/.env
cd /opt/windmill-pasta

# Update names, paths and domain
sed -i 's/pizza/pasta/g' .env docker-compose.yml backup.sh update.sh
sed -i 's/windmill.yourdomain.com/pasta.yourdomain.com/g' .env docker-compose.yml

# Generate new password and write it to both variables
NEW_PASSWORD=$(openssl rand -hex 16)
sed -i "s/^POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$NEW_PASSWORD/" .env
sed -i "s|^DATABASE_URL=postgresql://postgres:[^@]*@|DATABASE_URL=postgresql://postgres:$NEW_PASSWORD@|" .env

# Start the new instance
docker compose up -d

Considérations de sécurité

Isolation réseau

  • PostgreSQL n’est accessible que depuis les conteneurs de son réseau Docker ; si ce réseau est partagé avec le proxy inverse et d’autres services, utilisez un réseau interne distinct pour une isolation plus stricte
  • Aucun port de base de données n’est exposé à l’extérieur
  • La terminaison HTTPS est assurée par Traefik

Limites de ressources

  • Les conteneurs workers ont des limites de CPU et de mémoire
  • Les limites de ressources réduisent l’impact des tâches incontrôlées et des tentatives d’épuisement des ressources
  • Configurable selon la capacité du serveur

Sécurité SSL

  • Certificats Let’s Encrypt automatiques
  • Redirections HTTP vers HTTPS
  • Configuration TLS moderne

Supervision et maintenance

Contrôles hebdomadaires de l’état des services

cd /opt/windmill-pizza

# Container status
docker compose ps

# Resource usage
docker stats --no-stream

# Log analysis
docker compose logs | grep -i error

Maintenance mensuelle

# Back up and update containers (update.sh runs backup.sh first)
cd /opt/windmill-pizza
./update.sh

# Clean unused images, containers and networks
docker system prune -f

Répartition des coûts et comparaison

Coûts mensuels

Configuration auto-hébergée :

  • Hetzner CX23 (4 Go de RAM) : 5,99 €/mois HT, avec une adresse IPv4 principale incluse (en octobre 2026)
  • Frais de domaine : ~1 €/mois
  • Total : ~7 €/mois HT

Comparaison avec Windmill Cloud :

  • Cloud : 20 $/mois par siège de développeur, 10 $/mois par opérateur (en octobre 2026)
  • Économies : plus de 250 $ par an dès que deux développeurs ou plus ont besoin d’un siège

Avantages en matière de performances

Avantages de l’auto-hébergement :

  • Exécutions illimitées de flux de travail
  • Aucune limite de débit externe
  • Contrôle total des données
  • Intégrations personnalisées
  • Souplesse de dimensionnement des ressources

Référence de dépannage

Diagnostics rapides

cd /opt/windmill-pizza

# Container health
docker compose ps | grep -E "(healthy|Up)"

# Network connectivity
docker network inspect proxy

# Database connection
docker compose exec windmill-db psql -U postgres -d windmill_pizza -c "SELECT version();"

# Log analysis
docker compose logs --tail 50 windmill-server | grep -E "(ERROR|WARN)"

Erreurs courantes

  • « password authentication failed » → Utilisez des mots de passe hexadécimaux ; ne videz les volumes qu’après une sauvegarde ou sur une nouvelle installation.
  • « connection refused » → Vérifiez la configuration réseau.
  • « certificate errors » → Vérifiez le DNS et la configuration de Traefik.
  • « out of memory » → Ajustez les limites de ressources des workers.

Montée en charge de votre infrastructure Windmill

Montée en charge horizontale

Pour les environnements traitant de gros volumes :

# Add additional workers (under services: in docker-compose.yml)
windmill-worker-2:
  image: ${WM_IMAGE}
  container_name: windmill-pizza-worker-2
  restart: unless-stopped
  environment:
    - DATABASE_URL=${DATABASE_URL}
    - MODE=worker
    - WORKER_GROUP=heavy
  networks:
    - proxy
  depends_on:
    windmill-db:
      condition: service_healthy
  deploy:
    resources:
      limits:
        cpus: '2'
        memory: 4G

Montée en charge verticale

Augmentez les ressources du serveur (tarifs Hetzner HT, avec une adresse IPv4 principale incluse en octobre 2026) :

  • CX33 (8 Go de RAM) : 8,99 €/mois pour les charges de travail lourdes
  • CX43 (16 Go de RAM) : 16,49 €/mois pour un usage en entreprise

Intégration à l’infrastructure existante

Utilisation avec n8n

Si vous utilisez déjà n8n (présenté dans nos tutoriels précédents) :

  • Windmill gère les flux de travail conçus autour du code
  • n8n gère les automatisations visuelles et simples
  • Les deux partagent le même proxy Traefik
  • Des bases de données séparées évitent les conflits

Services partagés

Exploitez l’infrastructure existante :

  • Traefik : gère le SSL pour tous les services
  • Serveur de messagerie : SMTP partagé pour les notifications
  • Supervision : journalisation et métriques unifiées
  • Sauvegardes : stratégie de sauvegarde centralisée

Conclusion

L’auto-hébergement de Windmill fournit une automatisation des flux de travail de niveau entreprise à une fraction des coûts d’hébergement cloud. La clé du succès est de comprendre comment les identifiants d’authentification PostgreSQL sont transmis et conservés, et d’utiliser des mots de passe hexadécimaux uniquement pour éviter les problèmes d’encodage d’URL qui peuvent faire échouer les installations.

Principaux avantages de cette configuration

  • Rentable : économisez plusieurs centaines par an par rapport aux solutions cloud
  • Prêt pour la production : gère de manière fiable les charges de travail en entreprise
  • Sécurisé : HTTPS, aucun port de base de données exposé et limites de ressources
  • Évolutif : ajoutez facilement des workers et des ressources selon les besoins
  • Privé : votre code et vos données restent sur votre infrastructure, sauf si vos flux de travail les envoient à des services externes

Cette configuration a été testée dans des environnements de production et offre la fiabilité nécessaire pour l’automatisation des flux de travail critiques. Les étapes de dépannage répondent aux problèmes rencontrés en conditions réelles lors du déploiement, en particulier les problèmes d’authentification PostgreSQL qui affectent de nombreuses installations auto-hébergées.

Pour des besoins complexes en matière de flux de travail ou des déploiements d’entreprise, envisagez une consultation professionnelle pour optimiser votre cas d’utilisation spécifique et assurer une allocation optimale des ressources.

Prochaines étapes

  • Explorez les techniques de dépannage des webhooks applicables à Windmill
  • Consultez l’optimisation des charges utiles pour la gestion de grands ensembles de données
  • Envisagez l’intégration avec les installations n8n existantes

À propos de tva

tva assure la gestion complète de l’infrastructure des systèmes de bases de données, des environnements cloud et des chaînes d’approvisionnement mondiales. Notre approche méthodique combine des protocoles de sécurité rigoureux avec l’optimisation des performances, tandis que nos services de conseil stratégique permettent une coordination précise des capacités numériques et des actifs physiques – en maintenant les normes les plus élevées d’excellence opérationnelle et de conformité dans toutes nos missions.

Consultez tva.sg pour en savoir plus sur nos services et découvrir d’autres tutoriels d’automatisation.

De la configuration à la décision opérationnelle

La question pratique n’est pas de savoir si une plateforme peut être configurée. Il s’agit de déterminer si l’équipe peut expliquer qui en est responsable, détecter les dérives, rétablir le service sans improviser et démontrer que le changement a amélioré le résultat visé. Nous associons donc chaque configuration à un responsable, une référence initiale, une procédure de retour à la version précédente et une période de vérification après action. Une correction ponctuelle devient ainsi une capacité opérationnelle. Le dossier de production doit indiquer la raison du changement, les éléments examinés, le périmètre exact et la personne autorisée à l’arrêter ou à l’annuler. Après la mise en service, comparez les indicateurs convenus à la référence initiale et conservez le résultat dans le dossier du changement. Si l’amélioration attendue n’est pas au rendez-vous, le retour à la version précédente constitue un résultat valable plutôt qu’un échec. Cette discipline compte davantage que toute valeur de configuration prise isolément. Le même dossier offre au prochain opérateur un point de départ fiable et fait de l’optimisation ultérieure une décision fondée sur des mesures plutôt qu’une nouvelle série de suppositions.

Analyses connexes

Pour aller plus loin