[{"data":1,"prerenderedAt":262},["ShallowReactive",2],{"seo-verification":3,"blog-windmill-workflow-engine-vps-fr":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-windmill-workflow-engine-vps-fr",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":27,"featuredImage":29,"bgImage":30,"posterImage":31,"relatedSolution":32,"intro":34,"sections":35,"ctaTitle":198,"ctaBody":199,"ctaButton":200,"ctaUrl":201,"relatedPosts":202},438,"windmill-workflow-engine-vps",{"fr":10,"en":12,"ar":13,"es":14},"windmill-on-vps-typescriptpython-workflows-without-lock-in","محرك-سير-العمل-windmill-على-vps-python-typescript","windmill-en-vps-workflows-typescriptpython-sin-dependencias","Windmill sur VPS : orchestration TypeScript\u002FPython sans lock-in","Déployez Windmill v1.830 sur VPS en moins d'une heure : workflows TypeScript\u002FPython, crons, webhooks et UI intégrée, sans dépendre de n8n ou Make.",11,0,false,"2026-10-13T00:00:00+00:00","2026-10-13T14:10:28+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},2,"Automatisation","automatisation","bg-brand-action\u002F10 text-brand-action",[28],{"id":23,"name":24,"slug":25,"color":26,"icon":25},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fwindmill-workflow-engine-vps-poster.svg",{"categorySlug":25,"appSlug":33},"windmill","n8n 3.0, sorti en octobre 2026, impose Docker comme seule voie de déploiement et supprime plus de 30 nœuds historiques. Pour les équipes qui évaluent leurs options, Windmill s'impose comme l'alternative la plus directe : vous écrivez du TypeScript ou du Python natif, vous exécutez depuis l'éditeur web, et vous orchestrez des dizaines de workers sur un seul VPS. Pas de plan payant pour les variables secrètes, pas de nœuds proprietaires — juste du code versionné dans un workspace Git. Ce guide vous amène à une instance Windmill v1.830 en production en moins d'une heure.",[36,41,51,55,63,89,93,101,105,113,118,122,130,134,143],{"type":37,"title":38,"body":39,"items":40},"h2","Pourquoi Windmill plutôt que n8n ou Make en 2026","n8n 3.0 marque un tournant : Docker obligatoire, 30+ nœuds supprimés, et les nœuds Code qui ne peuvent plus lire les variables d'environnement. Make reste un SaaS fermé avec des limites d'opérations par mois. Windmill prend une direction opposée : tout votre code est un script de première classe, versionné, testable unitairement, et exécutable depuis un terminal comme depuis l'UI. La licence AGPLv3 garantit que la version self-hosted reste fonctionnellement identique à l'offre cloud — pas de features réservées à l'entreprise pour l'usage courant.",[],{"type":42,"title":43,"items":44,"body":5},"ul","Bénéfices concrets pour les équipes DevOps et agences",[45,46,47,48,49,50],"**TypeScript et Python natifs** — vos scripts s'exécutent dans un worker Node.js ou Python sans transpilation ni couche de nœuds intermédiaires ; les dépendances npm\u002Fpip sont résolues automatiquement par Windmill à la première exécution.","**Éditeur web avec exécution directe** — écrivez, testez et relancez un script depuis le navigateur en quelques secondes, sans avoir à pousser un commit ou redémarrer un service.","**Multilocataire intégré** — un seul déploiement supporte plusieurs workspaces isolés, idéal pour une agence gérant plusieurs clients ou une équipe avec des environnements dev\u002Fstaging\u002Fprod.","**Jobs cron et webhooks sans plugin** — planifier un job `0 9 * * 1-5` ou exposer un endpoint webhook `\u002Fapi\u002Fw\u002F\u003Cworkspace>\u002Fjobs\u002Frun\u002Fp\u002F\u003Cpath>` est une opération native, pas un add-on.","**Variables secrètes chiffrées** — les secrets sont chiffrés en base et jamais exposés dans les logs ; chaque workspace a son propre périmètre de secrets.","**Pas de lock-in** — tous les scripts, flows et ressources sont exportables en JSON\u002FYAML et importables dans n'importe quel autre déploiement Windmill.",{"type":37,"title":52,"body":53,"items":54},"Prérequis chiffrés","Windmill s'appuie sur PostgreSQL pour la persistance et sur un ou plusieurs workers pour l'exécution. Le serveur HTTP lui-même est léger ; c'est la charge des workers qui dimensionne le VPS. Comptez 1 worker par vCPU disponible et environ 1 à 2 Go de RAM par worker Python actif (les dépendances pip sont installées en sandbox et mises en cache sur disque).",[],{"type":42,"title":56,"items":57,"body":5},"Configuration minimale et recommandée",[58,59,60,61,62],"**Minimum absolu** — 2 vCPU, 4 Go de RAM, 20 Go de disque SSD ; convient à un workspace solo avec 1 worker et des jobs occasionnels.","**Petite équipe (recommandé)** — 4 vCPU, 8 Go de RAM, 40 Go SSD ; permet 3 workers simultanés et PostgreSQL sur le même hôte sans saturation mémoire.","**Équipe ou multi-clients** — 8 vCPU, 16 Go de RAM, 80 Go SSD ; supporte 6 à 8 workers, plusieurs workspaces actifs et des jobs Python avec dépendances lourdes.","**OS** — Ubuntu 22.04 LTS ou Debian 12 ; Docker Engine 24+ et Docker Compose v2 requis.","**Réseau** — une IPv4 dédiée et un nom de domaine pour le certificat TLS ; Windmill expose par défaut le port 8000 derrière un reverse proxy.",{"type":64,"title":65,"steps":66,"body":5,"items":88},"steps","Déploiement Docker Compose en 7 étapes",[67,70,73,76,79,82,85],{"title":68,"body":69},"Installer Docker et Docker Compose v2","Sur Ubuntu 22.04 ou Debian 12 : `curl -fsSL https:\u002F\u002Fget.docker.com | sh && docker compose version`. Vérifiez que la commande retourne `Docker Compose version v2.x.x` (sans tiret). Si votre système propose encore `docker-compose` (v1), désinstallez-le : `apt remove docker-compose`.",{"title":71,"body":72},"Récupérer le docker-compose.yml officiel","Créez un répertoire dédié et récupérez la configuration de référence : `mkdir -p \u002Fopt\u002Fwindmill && cd \u002Fopt\u002Fwindmill && curl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002Fwindmill-labs\u002Fwindmill\u002Fmain\u002Fdocker-compose.yml -o docker-compose.yml`. Ce fichier déclare quatre services : `db` (PostgreSQL 16), `windmill_server`, `windmill_worker` et `lsp` (serveur de complétion de code).",{"title":74,"body":75},"Créer le fichier .env","Windmill attend deux variables obligatoires. Générez une clé aléatoire : `openssl rand -hex 32`. Puis créez `\u002Fopt\u002Fwindmill\u002F.env` avec : `WM_BASE_URL=https:\u002F\u002Fwindmill.votre-domaine.com` et `WINDMILL_SECRET_KEY=\u003Cclé générée>`. Ne commitez jamais ce fichier — ajoutez `.env` à votre `.gitignore` si vous versionnez la configuration.",{"title":77,"body":78},"Ajuster le nombre de workers","Par défaut, `docker-compose.yml` démarre 1 replica du service `windmill_worker`. Pour en démarrer 3 : `docker compose up -d --scale windmill_worker=3`. Sur un VPS 4 vCPU \u002F 8 Go, 2 ou 3 workers est le bon équilibre. Vous pouvez ajuster à chaud sans redémarrer le serveur : `docker compose up -d --no-recreate --scale windmill_worker=2`.",{"title":80,"body":81},"Configurer Nginx en reverse proxy avec TLS","Installez Nginx et Certbot : `apt install -y nginx certbot python3-certbot-nginx`. Créez `\u002Fetc\u002Fnginx\u002Fsites-available\u002Fwindmill` avec un bloc `server` écoutant le port 80, un `proxy_pass http:\u002F\u002F127.0.0.1:8000;` et les en-têtes `X-Real-IP`, `X-Forwarded-For`, `Upgrade` et `Connection` (pour les WebSockets). Obtenez le certificat : `certbot --nginx -d windmill.votre-domaine.com`. Certbot modifie automatiquement le vhost pour écouter en HTTPS.",{"title":83,"body":84},"Démarrer la stack et créer le workspace initial","Lancez la stack : `cd \u002Fopt\u002Fwindmill && docker compose up -d`. Attendez 30 secondes que PostgreSQL soit prêt, puis ouvrez `https:\u002F\u002Fwindmill.votre-domaine.com` dans un navigateur. L'interface vous propose de créer un workspace — choisissez un identifiant court (`prod`, `acme-client`) — et de définir le compte administrateur. Ce compte est local à Windmill ; vous pourrez connecter un fournisseur SSO (GitHub, OIDC) depuis `Settings → Authentication`.",{"title":86,"body":87},"Activer le redémarrage automatique et vérifier les logs","Ajoutez la politique de redémarrage à la stack : dans `docker-compose.yml`, assurez-vous que chaque service a `restart: unless-stopped`. Rechargez si nécessaire : `docker compose up -d`. Vérifiez les logs du serveur : `docker compose logs -f windmill_server`. La ligne `Windmill server started on port 8000` confirme que l'instance est opérationnelle. Pour les workers : `docker compose logs -f windmill_worker`.",[],{"type":37,"title":90,"body":91,"items":92},"Configuration : workspace, variables secrètes et crons","Une fois l'instance démarrée, trois zones de configuration sont à maîtriser avant de créer vos premiers workflows.",[],{"type":42,"title":94,"items":95,"body":5},"Les réglages essentiels post-installation",[96,97,98,99,100],"**Workspace et permissions** — dans `Settings → Workspace`, définissez le fuseau horaire (utilisé pour les crons) et activez le mode `Auto-approve executions` uniquement si tous les membres sont de confiance. Par défaut, les scripts créés par des utilisateurs non-admin passent en mode de revue avant exécution en production.","**Variables et ressources** — `Variables` stocke des clés scalaires (tokens, URLs) chiffrées AES-256. `Resources` stocke des objets structurés (connexions de bases de données, credentials OAuth) avec un schéma JSON typé. Préférez les ressources pour tout ce qui contient plusieurs champs : moins d'erreurs de copier-coller.","**Schedules (crons)** — dans l'éditeur d'un script, cliquez `Add schedule`. La syntaxe acceptée est le format cron standard à 5 champs. Le timezone par workspace s'applique automatiquement : `0 8 * * 1-5` déclenche bien à 8h00 heure du workspace, pas UTC.","**Webhooks** — chaque script expose un endpoint de la forme `\u002Fapi\u002Fw\u002F\u003Cworkspace>\u002Fjobs\u002Frun\u002Fp\u002F\u003Cchemin-du-script>`. Authentifiez les appels entrants avec un token généré dans `Settings → Tokens`. Passez les paramètres du script en corps JSON POST.","**Synchronisation Git** — dans `Settings → Git Sync`, connectez un dépôt Git pour pousser automatiquement tous les scripts, flows et ressources à chaque modification. Idéal pour la traçabilité et le déploiement entre environnements.",{"type":37,"title":102,"body":103,"items":104},"Exemple de workflow Python complet","Voici un script Python concret : il interroge une API externe, filtre les résultats et insère les lignes dans une base PostgreSQL via une ressource Windmill. Créez un nouveau script de type `Python 3.11`, collez le code ci-dessous et exécutez-le directement depuis l'éditeur pour valider.",[],{"type":42,"title":106,"items":107,"body":5},"Script Python : import API → filtre → PostgreSQL",[108,109,110,111,112],"**Déclaration des dépendances** — les lignes `# requirements:` en tête du script indiquent à Windmill les packages pip à installer dans le sandbox isolé : `# requirements:\\n# httpx\\n# psycopg2-binary`. Windmill gère le cache de ces dépendances entre exécutions.","**Signature de la fonction principale** — Windmill appelle toujours la fonction `def main(...)`. Les paramètres sont injectés depuis l'UI, le cron ou le corps du webhook : `def main(api_url: str, db: dict) -> dict:`. Le type `dict` pour `db` correspond à une ressource PostgreSQL.","**Appel HTTP avec httpx** — `import httpx; resp = httpx.get(api_url, timeout=10); resp.raise_for_status(); data = resp.json()`. Windmill capture les exceptions non gérées et les affiche dans le journal d'exécution avec la stack trace complète.","**Filtrage et insertion** — `rows = [r for r in data if r.get('active')]; conn = psycopg2.connect(**db); cur = conn.cursor(); cur.executemany('INSERT INTO items(id, name) VALUES (%(id)s, %(name)s) ON CONFLICT DO NOTHING', rows); conn.commit()`. La ressource `db` est passée comme dictionnaire Python — les clés correspondent aux paramètres de `psycopg2.connect`.","**Valeur de retour** — `return {'inserted': len(rows), 'source': api_url}`. La valeur retournée est affichée dans l'UI et accessible aux étapes suivantes d'un Flow.",{"type":114,"title":115,"body":116,"items":117},"tip","Durcissement et sécurité","Limitez l'accès réseau au VPS : fermez le port 8000 dans UFW (`ufw deny 8000\u002Ftcp`) — seul Nginx doit y accéder depuis localhost. Activez les headers de sécurité dans Nginx : `add_header X-Frame-Options SAMEORIGIN; add_header X-Content-Type-Options nosniff; add_header Referrer-Policy strict-origin-when-cross-origin`. Configurez les sauvegardes PostgreSQL : `docker exec windmill-db-1 pg_dump -U windmill windmill | gzip > \u002Fbackups\u002Fwindmill-$(date +%Y%m%d).sql.gz`. Planifiez ce dump avec un cron systemd ou… un job Windmill lui-même. Activez la politique de mots de passe dans `Settings → Security` et forcez 2FA pour les comptes admin. Limitez les permissions des workers non-root : Windmill supporte les `Worker Groups` avec des images Docker restreintes pour les scripts non fiables.",[],{"type":37,"title":119,"body":120,"items":121},"Dépannage — erreurs fréquentes","Voici les cinq problèmes rencontrés le plus souvent lors d'un premier déploiement Windmill, avec leurs causes réelles et leurs corrections.",[],{"type":42,"title":123,"items":124,"body":5},"5 erreurs réelles et leurs correctifs",[125,126,127,128,129],"**`connection refused` au démarrage du serveur** — le conteneur `windmill_server` démarre avant que PostgreSQL soit prêt. Ajoutez un `healthcheck` sur le service `db` et une clause `depends_on: db: condition: service_healthy` sur `windmill_server`. Sans cela, le serveur tente de se connecter à PostgreSQL pendant son initialisation et abandonne. Vérifiez : `docker compose logs db | grep 'ready to accept'`.","**Workers qui restent `IDLE` indéfiniment** — cause classique : la variable `DATABASE_URL` dans l'environnement des workers pointe vers `localhost` au lieu du nom du service Docker (`db`). Dans `docker-compose.yml`, la valeur correcte est `postgresql:\u002F\u002Fwindmill:windmill@db\u002Fwindmill`. `localhost` depuis un conteneur ne résout pas le service PostgreSQL de la stack.","**Scripts Python qui échouent avec `ModuleNotFoundError`** — Windmill résout les dépendances pip au premier lancement du script dans un cache local. Si le worker n'a pas d'accès internet (pare-feu restrictif), l'installation silencieuse échoue. Vérifiez : `docker exec \u003Cworker-id> pip install httpx`. Ouvrez le port 443 sortant pour `pypi.org` et `files.pythonhosted.org`, ou montez un miroir pip interne via la variable `PIP_INDEX_URL`.","**Webhook retourne 403 Forbidden** — le token passé en header `Authorization: Bearer \u003Ctoken>` est correct, mais le script est en mode `Require approval`. Désactivez ce mode dans l'éditeur du script (`Settings → Execution policy → Direct execution`) ou utilisez un token de service avec le rôle `executor`.","**Cron qui ne se déclenche pas à l'heure prévue** — le fuseau horaire du workspace est UTC par défaut. Si votre workspace est en `Africa\u002FCasablanca` (UTC+1 en hiver, UTC+0 en été selon DST), une expression `0 9 * * *` déclenche à 9h00 du fuseau du workspace. Vérifiez le timezone dans `Settings → Workspace → Timezone` et relancez le scheduler : `docker compose restart windmill_server`.",{"type":37,"title":131,"body":132,"items":133},"Vers la production : checklist finale","Avant d'exposer Windmill à du trafic réel ou à des jobs critiques, parcourez cette liste. Elle couvre les points qui passent le plus souvent à la trappe lors d'un premier déploiement.",[],{"type":42,"title":135,"items":136,"body":5},"Points de validation avant mise en production",[137,138,139,140,141,142],"**TLS valide et HSTS** — vérifiez que `https:\u002F\u002Fwindmill.votre-domaine.com` répond sans avertissement de certificat et ajoutez `Strict-Transport-Security: max-age=31536000` dans le vhost Nginx.","**Sauvegardes testées** — faites un dump PostgreSQL, restaurez-le dans un conteneur de test et vérifiez que l'interface Windmill se connecte. Une sauvegarde non testée n'existe pas.","**Monitoring des workers** — la page `Admin → Workers` affiche l'état en temps réel. Branchez une alerte (Grafana, UptimeRobot, ou un job Windmill lui-même) si le nombre de workers actifs passe sous 1.","**Rotation des secrets** — les variables Windmill sont chiffrées avec la `WINDMILL_SECRET_KEY`. Si vous perdez cette clé, les secrets chiffrés en base sont irrécupérables. Sauvegardez la clé dans un gestionnaire de secrets (Vaultwarden, Bitwarden) séparé du VPS.","**Version fixée dans docker-compose.yml** — remplacez `image: ghcr.io\u002Fwindmill-labs\u002Fwindmill:latest` par `image: ghcr.io\u002Fwindmill-labs\u002Fwindmill:1.830.0` pour éviter les mises à jour automatiques non contrôlées. Mettez à jour délibérément en consultant le CHANGELOG.","**Git Sync activé** — connectez un dépôt privé pour versionner tous vos scripts et flows. En cas de perte du VPS, vous restaurez la base et réimportez depuis Git.",{"type":144,"title":145,"headers":146,"rows":151,"body":5,"items":197},"comparison","Windmill vs n8n vs Temporal",[147,148,149,150],"Critère","Windmill 1.830","n8n 3.x","Temporal Cloud\u002FSelf-hosted",[152,157,162,167,172,177,182,187,192],[153,154,155,156],"Langage des workflows","TypeScript, Python, Go, Bash","JavaScript (nœuds) + Code nodes limités","Go, Java, Python, TypeScript via SDK",[158,159,160,161],"Modèle de déploiement","Docker Compose, 1 image unique","Docker obligatoire depuis v3.0","Docker ou Temporal Cloud SaaS",[163,164,165,166],"Licence","AGPLv3 (self-host complet)","Sustainable Use License (restrictions agences)","MIT (core) + offre cloud payante",[168,169,170,171],"Variables secrètes self-hosted","Inclus, chiffrées AES-256","Inclus","Inclus (Temporal Namespace)",[173,174,175,176],"Éditeur web intégré","Oui — IDE complet avec autocomplétion","Oui — canvas nodal","Non — développement en local uniquement",[178,179,180,181],"Multilocataire","Oui — workspaces isolés natifs","Partiel — instances séparées recommandées","Oui — Namespaces Temporal",[183,184,185,186],"RAM minimale","4 Go (1 worker + PostgreSQL)","2 Go (SQLite), 4 Go (PostgreSQL)","4 Go (self-hosted) \u002F N\u002FA (cloud)",[188,189,190,191],"Durée max d'un workflow","Sans durée limite (jobs longue durée)","Limitée par le timeout des nœuds","Sans limite (durabilité des activités)",[193,194,195,196],"Courbe d'apprentissage","Faible — code Python\u002FTS standard","Faible — canvas visuel","Élevée — modèle d'activités\u002Fsignaux",[],"Un VPS prêt pour Windmill en quelques minutes","ServOrbit propose des VPS avec accès root, IPv4 dédiée et choix d'OS Ubuntu\u002FDebian. Montez votre stack Windmill avec Docker Compose dès le premier accès SSH.","Déployer Windmill","\u002Fmarketplace\u002Fautomatisation\u002Fwindmill",[203,221,244],{"id":204,"slug":205,"slugs":206,"title":210,"excerpt":211,"readTime":212,"views":23,"isPinned":19,"publishedAt":213,"updatedAt":214,"category":215,"categories":216,"featuredImage":29,"bgImage":30,"posterImage":218,"relatedSolution":219},3,"installer-n8n-vps",{"fr":205,"en":207,"ar":208,"es":209},"install-n8n-on-vps-with-docker-complete-2026-guide","تثبيت-n8n-على-vps-مع-docker-دليل-شامل-2026","instalar-n8n-en-vps-con-docker","Installer n8n sur VPS avec Docker : guide complet 2026","Déployez n8n sur VPS avec Docker, reverse proxy et HTTPS. Crash V8, 502 nginx, migration npm vers Docker et sécurisation des exécutions persistées (advisory août 2026).",16,"2026-06-05T00:00:00+00:00","2026-09-23T15:23:17+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":25},[217],{"id":23,"name":24,"slug":25,"color":26,"icon":25},"\u002Fblog\u002Fcovers\u002Finstaller-n8n-vps-poster.svg",{"categorySlug":25,"appSlug":220},"n8n",{"id":222,"slug":223,"slugs":224,"title":228,"excerpt":229,"readTime":230,"views":18,"isPinned":19,"publishedAt":231,"updatedAt":232,"category":233,"categories":239,"featuredImage":29,"bgImage":30,"posterImage":241,"relatedSolution":242},359,"construire-stack-ia-open-source-vps",{"fr":223,"en":225,"ar":226,"es":227},"open-source-ai-stack-vps-ollama-openwebui-n8n","بيئة-ذكاء-اصطناعي-ذاتية-الاستضافة-vps","stack-ia-open-source-vps-ollama-openwebui-n8n","Stack IA open source sur VPS : Ollama, Open WebUI et n8n","Assemblez Ollama, Open WebUI et n8n sur un seul VPS : moteur LLM local, interface chat et automatisation, 100 % self-hosted sans API cloud.",8,"2026-09-18T00:00:00+00:00","2026-09-21T15:22:03+00:00",{"id":234,"name":235,"slug":236,"color":237,"icon":238},1,"Intelligence Artificielle","intelligence-artificielle","bg-purple-500\u002F10 text-purple-400","ia",[240],{"id":234,"name":235,"slug":236,"color":237,"icon":238},"\u002Fblog\u002Fcovers\u002Fconstruire-stack-ia-open-source-vps-poster.svg",{"categorySlug":238,"appSlug":243},"open-webui",{"id":245,"slug":246,"slugs":247,"title":250,"excerpt":251,"readTime":17,"views":18,"isPinned":19,"publishedAt":252,"updatedAt":21,"category":253,"categories":259,"featuredImage":29,"bgImage":30,"posterImage":261,"relatedSolution":29},436,"deployer-laravel-vps-octane",{"fr":246,"en":248,"ar":249,"es":248},"laravel-octane-vps-frankenphp-docker-traefik","laravel-octane-على-vps-frankenphp-docker-traefik","Laravel Octane sur VPS : FrankenPHP, Docker et Traefik","Migrer vers Laravel Octane avec FrankenPHP en Docker Compose derrière Traefik : cycle de vie partagé, checklist compatibilité et zero-downtime en production.","2026-10-12T00:00:00+00:00",{"id":254,"name":255,"slug":256,"color":257,"icon":258},4,"Développement","developpement","bg-warning\u002F10 text-warning","dev",[260],{"id":254,"name":255,"slug":256,"color":257,"icon":258},"\u002Fblog\u002Fcovers\u002Fdeployer-laravel-vps-octane-poster.svg",1791900996153]