Coolify auto-hébergé : le tutoriel complet, du VPS vide au déploiement continu
Du VPS vide à l'application Node.js qui se redéploie à chaque push : installation, durcissement, PostgreSQL, SSL automatique, sauvegardes S3 et supervision, sur Coolify v4.3.
Sommaire(19 sections)
- Ce que vous obtiendrez à la fin1
- Prérequis2
- Étape 1. Provisionner le VPS3
- Étape 2. Durcir le serveur avant d'exposer quoi que ce soit4
- Étape 3. Installer Coolify en une commande5
- Étape 4. Domaine, DNS wildcard et accès HTTPS au dashboard6
- Étape 5. Projet, environnement et serveur7
- Étape 6. Déployer l'application Node.js depuis GitHub8
- Étape 7. Provisionner PostgreSQL et brancher l'application9
- Étape 8. HTTPS automatique avec Traefik10
- Étape 9. Variables de build, variables runtime et secrets11
- Étape 10. Sauvegardes vers S3 et restauration testée12
- Étape 11. Déploiement continu à chaque push13
- Étape 12. Monitoring, logs et alertes14
- Étape 13. Le multi-serveurs, aujourd'hui15
- Vérifier que tout tient debout16
- Pièges fréquents17
- Où se situe Coolify18
- Pour aller plus loin19
Une facture de plateforme managée qui grimpe à chaque environnement de preview, un client qui exige que la base de données ne quitte pas un serveur européen, une équipe qui veut pouvoir ouvrir le capot : les raisons de reprendre la main sur son hébergement ne manquent pas. Le problème, c'est qu'on renonce rarement de gaieté de cœur au confort du « je pousse sur main, ça se déploie tout seul, avec le certificat qui va bien ». Coolify existe pour ne pas avoir à choisir : un PaaS open source, sous licence Apache-2.0, que vous installez sur votre propre serveur et qui rejoue ce confort chez vous.
Ce guide déroule une installation complète, du VPS vide jusqu'à une application Node.js qui se redéploie à chaque push, avec sa base PostgreSQL, son certificat renouvelé automatiquement, ses sauvegardes vers un bucket S3 et ses alertes en cas d'échec. Chaque étape indique ce qu'on cherche à obtenir, la manipulation, et ce que vous devez voir à l'écran pour passer à la suivante.
Tout ce qui suit s'appuie sur la branche Coolify v4.3, vérifiée sur la v4.3.7, dernière version stable au moment où ces lignes sont écrites, publiée le 17 août 2026 (page de release GitHub). Le projet publie plusieurs correctifs par semaine, huit rien qu'entre le 12 et le 17 août : le numéro exact aura bougé quand vous lirez ces lignes, les écrans décrits ici, non. Le détail compte quand même, parce que les libellés ont changé de place au fil de la branche v4, et qu'un pas à pas calé sur une version bien antérieure vous fait chercher des menus qui n'existent plus.
Ce que vous obtiendrez à la fin
À la dernière étape, votre serveur héberge une pile complète et autonome. Concrètement :
- un dashboard Coolify accessible en HTTPS sur votre propre domaine, pas sur une adresse IP en clair ;
- une application Node.js construite depuis GitHub sans Dockerfile écrit à la main ;
- une base PostgreSQL managée par Coolify, joignable uniquement sur le réseau Docker interne ;
- un certificat Let's Encrypt posé et renouvelé automatiquement par le proxy ;
- des sauvegardes planifiées vers un stockage S3, avec une restauration testée ;
- un redéploiement automatique à chaque push et une notification quand un déploiement échoue.
Prérequis
Côté machine, la documentation d'installation de Coolify demande au minimum 2 CPU, 2 Go de RAM et 30 Go d'espace disque libre, sur une architecture AMD64 ou ARM64. Elle précise que l'outil peut fonctionner correctement sur des serveurs moins dotés, tout en recommandant de viser un peu plus haut pour déployer plusieurs applications sans dégrader les performances. La même page donne un repère utile : le serveur de production du mainteneur, avec 4 cœurs, 8 Go de RAM et 150 Go de disque, fait tourner trois applications Node.js, quatre sites statiques, quatre services (analytics, collecte de retours, supervision de disponibilité, newsletters) et cinq bases de données. C'est l'ordre de grandeur à viser dès que la machine sert à autre chose qu'une démo, parce que ce sont les builds qui saturent en premier. La documentation conseille d'ailleurs d'activer du swap si builds et Coolify partagent le même serveur.
Les distributions supportées couvrent large : Debian et Ubuntu, la famille Red Hat (CentOS, Fedora, AlmaLinux, Rocky, TencentOS), SUSE, Arch, Alpine et Raspberry Pi OS 64 bits. Attention à deux réserves documentées : le script d'installation automatique ne fonctionne qu'avec les versions LTS d'Ubuntu (20.04, 22.04, 24.04), les autres passent par l'installation manuelle ; et sur certaines distributions comme AlmaLinux, Docker doit être installé au préalable.
Il vous faut également un nom de domaine dont vous contrôlez la zone DNS, un compte GitHub avec le dépôt de l'application à déployer, un bucket S3 ou compatible (AWS S3, Backblaze B2, Cloudflare R2, MinIO) pour les sauvegardes, et des bases confortables en ligne de commande Linux et en Git. Sur une Ubuntu LTS fraîche, Docker n'est pas à installer à la main : le script d'installation s'en charge.
Étape 1. Provisionner le VPS
But : un serveur Ubuntu LTS avec accès root, correctement dimensionné.
Chez Hetzner, vous n'avez rien à installer. Le fournisseur publie une app Coolify officielle dans son marketplace, déclenchable depuis la console ou en une ligne avec le CLI hcloud :
hcloud server create --name my-coolify-server --type cpx22 --image coolify
Point important, et source classique de confusion : la documentation Hetzner précise que « Coolify sera alors préinstallé sur le serveur, mais pas encore activé ». C'est votre première connexion SSH qui déclenche l'activation et affiche l'URL du dashboard. Tant que vous ne vous êtes pas connecté, l'interface ne répond pas, et ce n'est pas une panne.
Chez OVH ou ailleurs, il n'existe pas d'image préparée équivalente : vous provisionnez un VPS Ubuntu LTS standard, et vous passerez par le script d'installation à l'étape 3. Le reste du tutoriel est identique.
Résultat attendu : un ssh root@203.0.113.1 qui aboutit, et un lsb_release -a qui affiche bien une version LTS.
Étape 2. Durcir le serveur avant d'exposer quoi que ce soit
But : SSH par clé uniquement, filtrage réseau maîtrisé, protection contre le bruteforce. Le tout avant d'installer Coolify, pas après.
Depuis votre poste, poussez votre clé publique et vérifiez qu'elle fonctionne avant de toucher à la configuration du démon SSH. La documentation Coolify insiste sur ce point : si vous passez PermitRootLogin en prohibit-password sans avoir de clé dans ~/.ssh/authorized_keys, vous vous verrouillez dehors.
ssh-copy-id root@203.0.113.1
ssh root@203.0.113.1
Sur le serveur, éditez /etc/ssh/sshd_config. La page OpenSSH de la documentation Coolify demande deux directives, que Coolify utilisera pour se connecter à ses serveurs :
PubkeyAuthentication yes
PermitRootLogin prohibit-password
La troisième, PasswordAuthentication no, n'est pas exigée par Coolify. C'est de l'hygiène Linux, et elle a sa place ici puisque la suite consiste précisément à ouvrir des ports sur Internet. Rechargez ensuite le démon, comme le fait la documentation sur Debian et Ubuntu :
systemctl restart ssh
Vient le filtrage réseau, l'endroit où une installation se croit protégée alors qu'elle ne l'est pas. La page Firewall de Coolify pose deux choses qu'il faut lire dans l'ordre. D'abord la liste des ports nécessaires en auto-hébergé : 22 pour SSH, 80 pour la génération des certificats, 443 pour le trafic HTTPS, et trois ports supplémentaires tant que vous accédez au dashboard par l'adresse IP, à savoir 8000 pour le dashboard lui-même, 6001 pour le temps réel et 6002 pour le terminal (ce dernier requis à partir de la v4.0.0-beta.336). Oublier 6001 et 6002 ne casse pas l'installation, mais laisse une interface à moitié muette.
Ensuite l'avertissement qui compte : Coolify tourne sur Docker, dont les règles iptables en NAT contournent UFW. Fermer un port publié par un conteneur avec UFW seul ne le ferme pas vraiment. La documentation recommande donc en premier lieu le pare-feu du fournisseur (Hetzner Cloud Firewall, groupes de sécurité OVH), et à défaut l'outil communautaire ufw-docker. UFW reste utile pour ce qui écoute directement sur l'hôte, SSH en tête :
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
Le port 8000 n'apparaît volontairement pas dans cette liste. On l'ouvrira à la seule adresse IP depuis laquelle vous allez créer le compte administrateur, le temps de l'étape 3, avant de le refermer une fois le dashboard joignable par son propre domaine. Terminez par fail2ban, qui bannit les adresses qui insistent sur le port SSH :
apt install -y fail2ban
systemctl enable --now fail2ban
fail2ban-client status
Résultat attendu : une tentative de connexion par mot de passe est refusée immédiatement, ufw status ne liste que 22, 80 et 443, et le pare-feu de votre fournisseur reflète exactement la même liste.
Étape 3. Installer Coolify en une commande
But : une instance Coolify fonctionnelle avec son compte administrateur créé.
La documentation officielle donne une seule commande, à lancer en root, le seul mode pleinement supporté à ce jour :
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
Si vous n'êtes pas connecté en root, la documentation fournit la variante curl -fsSL https://cdn.coollabs.io/coolify/install.sh | sudo bash. Le script installe les outils essentiels (curl, wget, git, jq, openssl), installe Docker Engine 24 ou supérieur, configure la journalisation et le démon Docker, prépare les répertoires de données sous /data/coolify, met en place les clés SSH nécessaires à la gestion du serveur, puis démarre Coolify. Un avertissement mérite d'être retenu : une installation de Docker faite via snap n'est pas supportée. Sur une image Ubuntu fraîche, vous n'aurez pas le souci ; sur un serveur recyclé, vérifiez.
En fin d'exécution, le script affiche l'URL du dashboard, du type http://203.0.113.1:8000. Ouvrez temporairement les trois ports d'accès direct à votre seule adresse IP :
ufw allow from VOTRE.IP.PUBLIQUE.ICI to any port 8000 proto tcp
ufw allow from VOTRE.IP.PUBLIQUE.ICI to any port 6001 proto tcp
ufw allow from VOTRE.IP.PUBLIQUE.ICI to any port 6002 proto tcp
Comme UFW ne suffit pas à filtrer ce que Docker publie, reportez la même restriction dans le pare-feu de votre fournisseur : c'est lui qui fait foi.
Rendez-vous sur l'URL affichée. Vous tombez sur une page d'inscription qui crée le premier compte administrateur. Créez ce compte immédiatement. La documentation est explicite sur ce point : quiconque atteint cette page d'inscription en premier prend le contrôle total du serveur. C'est la fenêtre de vulnérabilité la plus courte et la plus critique de toute l'installation, et c'est précisément pour la fermer qu'on a restreint ces ports à une seule adresse.
Résultat attendu : vous êtes connecté au dashboard, la page d'inscription n'est plus accessible, et le serveur local apparaît dans le menu Servers.
Étape 4. Domaine, DNS wildcard et accès HTTPS au dashboard
But : arrêter de travailler sur une adresse IP, et pouvoir déployer sur n'importe quel sous-domaine sans toucher au DNS à chaque fois.
La page de configuration DNS demande un enregistrement A par domaine ou sous-domaine utilisé, et documente le wildcard pour couvrir tout le reste. Chez votre registrar :
example.com. A 203.0.113.1
*.example.com. A 203.0.113.1
Le wildcard est ce qui vous évite de créer un enregistrement DNS par ressource déployée : app.example.com, api.example.com et les sous-domaines de preview de pull request résolvent tous vers la même machine. Côté Coolify, ouvrez les paramètres du serveur et renseignez le champ Wildcard Domain au format complet, protocole compris :
https://example.com
Une fois ce champ posé, Coolify sait générer seul des sous-domaines pour les nouvelles ressources, du type https://random.example.com, et pour les previews de PR, du type https://<PRId>.random.example.com. Si votre domaine contient des caractères accentués ou non latins, convertissez-le en punycode avant de le saisir : münchen.example.com devient xn--mnchen-3ya.example.com.
Le dashboard lui-même mérite son propre domaine : le réglage vit dans la page Settings de l'instance, et le certificat suit le mécanisme automatique décrit à l'étape 8. La documentation est claire sur la suite : une fois le dashboard atteint par ce domaine personnalisé, les ports 8000, 6001 et 6002 peuvent être refermés sans risque.
ufw delete allow from VOTRE.IP.PUBLIQUE.ICI to any port 8000 proto tcp
ufw delete allow from VOTRE.IP.PUBLIQUE.ICI to any port 6001 proto tcp
ufw delete allow from VOTRE.IP.PUBLIQUE.ICI to any port 6002 proto tcp
ufw status numbered
Et, une fois de plus, retirez les mêmes règles côté fournisseur.
Résultat attendu : dig +short app.example.com renvoie l'IP du serveur, et le dashboard répond sur son domaine en HTTPS.
Étape 5. Projet, environnement et serveur
But : poser la hiérarchie qui structurera tout le reste, et laisser Coolify installer Docker sur les machines qu'il pilote.
Coolify organise les ressources en Project, puis Environment (production, staging), puis Server. Cette hiérarchie n'est pas cosmétique : c'est elle qui vous permettra plus tard de faire cohabiter un staging et une production sans dupliquer la configuration. Elle se lit en permanence dans le fil d'Ariane du dashboard.
Le serveur sur lequel Coolify est installé apparaît sous le nom Localhost. Pour en rattacher un autre, Coolify parle de Remote Server, et la procédure documentée tient en six gestes : installer OpenSSH Server sur la machine cible, y poser les directives sshd de l'étape 2, générer une paire de clés dédiée à Coolify, ajouter la clé publique aux authorized_keys, coller la clé privée dans la section Private Keys du dashboard, puis sélectionner cette clé dans les paramètres du serveur.
Un détail à ne pas rater, écrit noir sur blanc dans la documentation : la clé SSH dédiée à Coolify ne doit avoir ni passphrase ni 2FA. Coolify se connecte sans interaction humaine, une passphrase bloque tout.
ssh-keygen -t ed25519 -C "coolify" -f ~/.ssh/coolify -N ""
Sur la page General du serveur, le bouton Validate Server & Install Docker Engine fait deux choses d'un coup : il confirme que la connexion SSH fonctionne, et il installe Docker Engine sur la machine distante. Vous n'avez donc pas à préparer Docker vous-même.
Résultat attendu : un statut vert Proxy Running sur la fiche du serveur.
Étape 6. Déployer l'application Node.js depuis GitHub
But : une application construite et déployée depuis un dépôt Git, sans écrire de Dockerfile.
Deux façons de connecter le dépôt sont documentées : l'option Public Repository, qui prend l'URL d'un dépôt public sans authentification, ou un dépôt privé via l'intégration GitHub App ou une Deploy Key. Pour un projet réel, l'intégration GitHub App est celle à viser, parce qu'elle débloque aussi le déploiement automatique de l'étape 11.
Vient ensuite le choix du build pack. La documentation en documente quatre : Nixpacks, Static, Dockerfile et Docker Compose, auxquels s'ajoute Railpack, traité sur sa propre page. Le guide Nixpacks précise, à la quatrième étape de l'assistant, que « Coolify utilisera Nixpacks par défaut ». Nixpacks inspecte le dépôt Git et génère automatiquement un Dockerfile, que vous n'avez ni à écrire ni à maintenir.
Votre application n'a qu'une obligation réelle : écouter sur le port passé par l'environnement, et se lier à 0.0.0.0 plutôt qu'à localhost, faute de quoi le conteneur ne recevra jamais de trafic.
// server.mjs
import http from "node:http";
const port = process.env.PORT ?? 3000;
http
.createServer((req, res) => {
if (req.url === "/healthz") {
res.writeHead(200, { "content-type": "application/json" });
res.end(JSON.stringify({ status: "ok" }));
return;
}
res.writeHead(200, { "content-type": "text/plain" });
res.end("Coolify OK");
})
.listen(port, "0.0.0.0", () => console.log(`listening on ${port}`));
Un piège documenté mérite votre attention, et il concerne précisément Node.js. Nixpacks ne sait épingler que la version majeure : que vous passiez par NIXPACKS_NODE_VERSION, par engines.node dans le package.json ou par un .nvmrc, vous choisissez 20 ou 22, jamais 22.14.0. Le patch livré dépend de l'archive nixpkgs utilisée en interne, et vous pouvez donc obtenir un 22.12.0 là où votre code attend une fonctionnalité arrivée plus tard. La page dédiée au versionnage Node.js donne le contournement : épingler un commit de l'archive nixpkgs dans un nixpacks.toml à la racine du dépôt.
[phases.setup]
nixpkgsArchive = '51ad838b03a05b1de6f9f2a0fffecee64a9788ee'
Ce SHA correspond, d'après la documentation, à Node 22.13.1. Si votre build passe en local et échoue ici sur une syntaxe récente, commencez par là.
Quant à Railpack, il s'agit d'un build pack open source créé par Railway comme successeur de Nixpacks. Dans Coolify, il est en statut beta, « pleinement fonctionnel mais susceptible d'évoluer ». Le parcours de déploiement est le même, il suffit de sélectionner Railpack plutôt que Nixpacks dans le sélecteur de build pack, à la quatrième étape de l'assistant. Les différences pratiques tiennent en trois points : configuration en railpack.json plutôt qu'en nixpacks.toml, gestionnaire de paquets Mise plutôt que Nix, et build via Docker BuildKit plutôt que le build Docker natif. La page Railpack note aussi que Nixpacks est passé en mode maintenance quand Railpack est en développement actif. Pour une mise en production aujourd'hui, restez sur Nixpacks ; gardez Railpack en tête pour vos prochains projets.
Dernier point de vigilance, sur les healthchecks. La page dédiée est nette : quand un healthcheck est activé sur une ressource, Traefik ne route le trafic que si le test passe, et un test qui échoue produit une erreur 404 Not Found ou « No available server ». Autrement dit, un healthcheck mal réglé donne exactement le symptôme d'une application cassée, alors que celle-ci tourne parfaitement. Deux détails évitent la moitié des cas : un healthcheck configuré depuis l'interface exige que le conteneur embarque curl ou wget, et si un HEALTHCHECK existe aussi dans le Dockerfile, c'est lui qui l'emporte.
Résultat attendu : un déploiement au vert dans les logs, et l'application qui répond sur son sous-domaine.
Étape 7. Provisionner PostgreSQL et brancher l'application
But : une base managée par Coolify, joignable par l'application, invisible depuis Internet.
Coolify propose huit bases de données en un clic : PostgreSQL, Redis, DragonFly, KeyDB, Clickhouse, MongoDB, MySQL et MariaDB. Passez par New Resource, choisissez PostgreSQL, et laissez Coolify provisionner le conteneur.
La page de la ressource affiche ensuite deux chaînes de connexion, et c'est là que se joue la sécurité de votre installation. Tant que l'application et la base partagent le même réseau Docker, vous utilisez l'URL interne fournie par Coolify, celle qui n'est pas exposée publiquement. Copiez-la et collez-la comme variable d'environnement de l'application :
DATABASE_URL=<URL interne copiee depuis la page de la base>
La documentation des bases de données réserve l'URL publique au cas où application et base ne partagent pas le même réseau, par exemple un second serveur. Cette bascule demande de marquer explicitement la base « Accessible over the internet », ce qui n'a rien d'anodin : ne l'activez pas par confort. Le branchement, lui, reste un geste manuel : c'est vous qui copiez l'URL dans les variables de l'application, rien n'est injecté automatiquement.
Si vous devez malgré tout exposer la base, la documentation détaille deux mécanismes distincts, le Ports Mapping (mappage figé d'un port du conteneur vers l'hôte, qui demande un redémarrage pour changer) et le Public Port (proxy TCP Nginx démarré par Coolify, modifiable à chaud, avec un timeout d'inactivité réglable, une heure par défaut).
Résultat attendu : l'application démarre sans erreur de connexion, et la base ne répond pas à un psql lancé depuis l'extérieur.
Étape 8. HTTPS automatique avec Traefik
But : un certificat valide, renouvelé sans intervention, sur le domaine de l'application.
C'est l'étape la plus courte du tutoriel, et c'est voulu. Traefik est le proxy utilisé par défaut, et la page Traefik de la documentation le résume ainsi : Coolify le configure automatiquement et lui délègue la gestion du routage et des certificats SSL, Let's Encrypt compris. La page d'introduction est plus explicite encore sur le cycle de vie du certificat : Coolify met en place et renouvelle automatiquement les certificats Let's Encrypt des domaines personnalisés. Vous attachez un domaine à votre application, le reste se fait sans vous. Aucun certbot à lancer, aucun cron à écrire. Corollaire à ne pas oublier : la validation passe par le port 80, qui doit donc rester ouvert même si tout votre trafic utile est en HTTPS.
Caddy est disponible en alternative, marquée expérimentale, introduite en beta.237. Depuis cette version, la page des proxies supportés indique qu'on peut basculer de l'un à l'autre à tout moment. Une précaution s'impose si votre instance est plus ancienne : les ressources créées avant beta.237 ont besoin des bons labels de proxy (traefik_* ou caddy_*) pour survivre au changement. Ils se réappliquent soit en redémarrant la ressource, soit manuellement via le bouton Reset to Coolify Default Labels pour les applications, soit en resauvegardant la configuration pour les services. Dans tous les cas, un redémarrage est nécessaire pour que les nouveaux labels prennent effet.
Résultat attendu : un certificat vérifiable en une commande.
echo | openssl s_client -connect app.example.com:443 -servername app.example.com 2>/dev/null \
| openssl x509 -noout -issuer -dates
Étape 9. Variables de build, variables runtime et secrets
But : comprendre pourquoi une variable « existe » au build mais pas dans le conteneur, et protéger les valeurs sensibles.
C'est la source d'incompréhension numéro un sur Coolify. Chaque variable d'environnement porte deux drapeaux indépendants, tous deux actifs par défaut : Build Variable, disponible pendant la construction de l'image, et Runtime Variable, disponible dans le conteneur en cours d'exécution. Les trois combinaisons utiles :
| Configuration | Disponible au build | Disponible dans le conteneur |
|---|---|---|
| Build + Runtime (défaut) | oui | oui |
| Build only | oui | non |
| Runtime only | non | oui |
Une clé d'API appelée au démarrage du serveur mais cochée « Build only » produit un undefined à l'exécution, sans la moindre erreur de build. C'est typiquement là qu'on perd une demi-journée.
Le mécanisme d'injection diffère selon le build pack, et la documentation des variables d'environnement le détaille : pour un déploiement Dockerfile, les variables de build passent en instructions ARG ; pour Docker Compose et pour Nixpacks, elles passent par --env-file. Ces variables de build sont stockées dans un fichier /artifacts/build-time.env, hors du contexte de build Docker, pour ne pas se retrouver dans l'image finale. Côté runtime, une fois le build terminé, Coolify écrit un fichier .env contenant toutes les variables marquées runtime, chargé au démarrage du conteneur via la directive env_file de Docker Compose.
Pour les valeurs vraiment sensibles, tokens de registre privé ou clés d'API, activez Use Docker Build Secrets dans les paramètres d'environnement de l'application. L'option demande BuildKit, donc Docker 18.09 ou supérieur, ce que l'installation de l'étape 3 vous garantit largement. Vous n'avez rien à écrire vous-même : Coolify passe les variables de build via --secret id=KEY,env=KEY au lieu de --build-arg, ajoute la directive # syntax=docker/dockerfile:1 si elle manque, et injecte le montage dans chaque instruction RUN, où le secret devient une variable d'environnement le temps de l'étape. Le Dockerfile réécrit ressemble à cet extrait :
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=NPM_TOKEN,env=NPM_TOKEN \
npm ci
Pour un build Docker Compose, Coolify ajoute à la place une section secrets native au fichier compose. Le bénéfice est le même : le secret n'apparaît ni dans docker history, ni dans les couches de l'image. Une image poussée par erreur sur un registre public ne trahit pas votre token. Une réserve documentée mérite d'être connue avant de compter dessus : si BuildKit n'est pas disponible sur le serveur qui construit, Coolify retombe sur --build-arg même quand l'option est cochée.
Résultat attendu : un docker history sur l'image produite qui ne laisse fuir aucune valeur sensible.
Étape 10. Sauvegardes vers S3 et restauration testée
But : des sauvegardes planifiées, une rétention définie, et surtout une restauration vérifiée au moins une fois.
Le stockage se déclare d'abord globalement : menu latéral Storage, puis Add. La page dédiée à S3 détaille les champs attendus, à savoir l'endpoint, le nom du bucket, la région, l'Access Key et la Secret Access Key. L'endpoint suit ce format chez AWS, sans le nom du bucket :
https://s3.YOUR_REGION_NAME.amazonaws.com
Le bouton Validate Connection & Continue confirme la connectivité avant d'aller plus loin. Les fournisseurs S3-compatibles (Cloudflare R2, Backblaze B2, MinIO, DigitalOcean Spaces, Scaleway, Supabase Storage) se configurent avec les mêmes champs, seul le format d'endpoint change ; récupérez le vôtre dans la console de votre fournisseur plutôt que de le deviner.
Le stockage validé, rendez-vous sur la ressource PostgreSQL, onglet Settings puis Backup. Activez S3, sélectionnez la destination, et définissez la fréquence sous forme d'expression cron. Une sauvegarde quotidienne à 3 h du matin s'écrit 0 3 * * *, et la page Backups accepte aussi des alias plus lisibles :
0 3 * * *
daily
weekly
Configurez ensuite la rétention, puis déclenchez un Backup Now pour valider la chaîne complète tout de suite plutôt que de découvrir un problème de permissions IAM trois semaines plus tard. Une sauvegarde qu'on n'a jamais restaurée n'est pas une sauvegarde : la documentation précise que le dump PostgreSQL est au format custom, donc restaurable avec pg_restore. Faites l'essai sur un environnement de test.
pg_restore --verbose --clean -h localhost -U postgres -d postgres pg-dump-postgres-1697207547.dmp
Un point de périmètre à avoir en tête, et il est plus étroit qu'on ne le croit. La documentation précise que les sauvegardes planifiées se configurent pour PostgreSQL et pour Coolify lui-même, la base interne de Coolify étant sauvegardée par le même chemin, ce qui couvre sa configuration. Pour MySQL, MariaDB ou MongoDB, la même page donne les commandes de dump à lancer vous-même. Et dans tous les cas, il ne s'agit ni d'une image du serveur ni d'une copie de vos volumes applicatifs, qui restent à traiter séparément.
Résultat attendu : un objet daté visible dans le bucket, et une restauration réussie.
Étape 11. Déploiement continu à chaque push
But : ne plus jamais cliquer sur « Deploy » à la main.
La page sur le déploiement automatique GitHub documente trois méthodes : l'intégration GitHub App, GitHub Actions et le webhook manuel. Si l'application a été déployée via l'intégration GitHub App, Coolify active Auto Deploy tout seul. Sinon, l'interrupteur se trouve dans la configuration de l'application, page Advanced, section General. La branche suivie est celle déclarée dans la source de l'application.
Pour le webhook manuel, le parcours tient en trois temps : activer l'auto-deploy au même endroit, saisir une chaîne secrète aléatoire et mettre de côté l'URL de webhook fournie par Coolify, puis créer le webhook côté GitHub dans Settings du dépôt, section Webhooks. Vous y collez l'URL Coolify dans Payload URL, le secret dans Secret, vous activez la vérification SSL, vous choisissez Just the push event, et vous cochez Active.
La documentation formule l'enjeu du secret sans détour : « Un secret de webhook fonctionne comme un mot de passe. Coolify n'accepte le webhook que si le secret correspond. » Sans lui, n'importe qui connaissant l'URL peut déclencher vos déploiements.
Résultat attendu : un commit poussé sur la branche cible, et un déploiement qui démarre seul dans les secondes qui suivent.
Étape 12. Monitoring, logs et alertes
But : savoir que quelque chose a cassé avant que le client ne vous l'apprenne.
Sentinel est le conteneur de supervision open source embarqué par Coolify, et la documentation le présente comme une fonctionnalité expérimentale. Sa définition officielle est volontairement modeste : une API système Linux, la supervision des ressources du serveur (CPU et RAM pour l'instant) et celle des ressources des conteneurs. Ne comptez pas dessus pour des métriques applicatives, ce n'est pas son rôle.
L'activation se fait dans Servers, puis votre serveur, Configurations, General, section Sentinel. Coolify télécharge et démarre le conteneur automatiquement. La collecte des métriques s'active au même endroit, avec une réserve documentée : elle n'est pas disponible pour les déploiements Docker Compose ni pour les Service Templates. Les courbes se consultent ensuite dans Servers, votre serveur, Configurations, onglet Metrics, et par ressource depuis l'onglet Configurations puis Metrics de l'application ou de la base.
Les alertes vivent dans l'onglet Notifications du dashboard. La documentation en recense six canaux : e-mail (via un serveur SMTP ou une clé API Resend), Telegram via un bot déclaré auprès de BotFather, Discord par webhook, Slack par webhook entrant (compatible tel quel avec Mattermost), Pushover, et un webhook générique vers l'endpoint HTTP de votre choix. Pour le SMTP, retenez les deux ports documentés : 587 pour StartTLS, le plus largement supporté, et 465 pour TLS/SSL, recommandé pour le niveau de sécurité le plus élevé. Détail qui a son importance si vous avez suivi l'étape 1 : la documentation signale que Hetzner bloque le port 465 par défaut.
Côté déclencheurs, vous pouvez être notifié sur les déploiements (succès, échec, changement de statut d'un conteneur), les sauvegardes, les tâches planifiées, et une série d'événements serveur : nettoyage Docker, usage disque, joignabilité, patching, Traefik obsolète. Chaque canal peut recevoir un jeu d'événements différent. Le minimum vital, c'est l'échec de déploiement et l'échec de sauvegarde. Le reste s'ajoute au fil de l'eau.
Résultat attendu : un déploiement volontairement cassé qui vous envoie une notification.
Étape 13. Le multi-serveurs, aujourd'hui
But : savoir ce qui est réellement disponible, sans attendre une hypothétique version future.
C'est le sujet sur lequel circule le plus d'informations périmées, le multi-serveurs étant régulièrement renvoyé à une prochaine version majeure. La documentation sur le multi-serveurs est pourtant claire : c'est déjà là en v4, avec la mention explicite qu'il s'agit d'une fonctionnalité expérimentale. Coolify sait déployer la même application sur plusieurs serveurs, les serveurs s'ajoutant par le menu Servers, et toute action de redéploiement, redémarrage ou arrêt s'applique alors à l'ensemble.
Trois prérequis sont posés, et le deuxième surprend souvent : chaque serveur doit être ajouté à Coolify et joignable, tous les serveurs doivent partager la même architecture (AMD64 ou ARM, pas un mélange), et l'image construite doit être poussée vers un Docker Registry. Coolify automatise l'envoi, mais c'est à vous d'authentifier le serveur auprès du registre. Le mécanisme se comprend en une phrase : le serveur principal (ou le serveur de build s'il en existe un) construit l'image, la pousse au registre, puis les autres serveurs sont notifiés de la tirer et de la déployer. Autrement dit, un registre de conteneurs est une pièce obligatoire du montage, pas une option.
La répartition de charge, elle, reste à votre charge : la documentation dit explicitement qu'elle n'est pas automatisée. Deux approches sont décrites. Soit un mapping de port vers l'hôte, avec un load balancer externe pointé sur des combinaisons IP:PORT et le champ Domains vidé côté Coolify, en n'autorisant les connexions entrantes sur ce port que depuis le load balancer. Soit un routage par domaine, en renseignant le domaine du load balancer en HTTP, pas en HTTPS, dans le champ Domains, la terminaison SSL étant alors gérée en dehors de Coolify.
Quant à une éventuelle version majeure suivante, ne fondez pas une décision d'infrastructure dessus. La dernière version stable est la v4.3.7 du 17 août 2026, et c'est sur cette base qu'il faut arbitrer. La bonne nouvelle, c'est que le besoin le plus courant, à savoir ne pas faire souffrir la production pendant les builds, se règle sans multi-serveurs complet : voir plus bas.
Vérifier que tout tient debout
Avant de considérer l'installation terminée, quatre vérifications valent d'être passées dans l'ordre. Le DNS, d'abord, parce qu'une propagation incomplète explique la moitié des symptômes bizarres :
dig +short app.example.com
dig +short nimportequoi.example.com
Les deux commandes doivent renvoyer l'IP du serveur : la seconde prouve que le wildcard fonctionne. Ensuite la redirection HTTP et la réponse applicative :
curl -I http://app.example.com
curl -s https://app.example.com/healthz
La première doit renvoyer une redirection vers HTTPS, la seconde votre charge utile de healthcheck. Puis le certificat, avec la commande openssl de l'étape 8, qui doit afficher un émetteur Let's Encrypt et une date d'expiration dans le futur. Enfin le filtrage réseau, à contrôler des deux côtés :
ufw status numbered
curl -sS -m 5 -o /dev/null -w "%{http_code}\n" http://203.0.113.1:8000
UFW ne doit lister que 22, 80 et 443. La seconde commande, lancée depuis une machine extérieure, doit échouer ou expirer : c'est la seule preuve que le dashboard n'est plus joignable en direct, puisque les règles publiées par Docker échappent à UFW. Si les quatre passent, vous avez une installation propre.
Pièges fréquents
Cinq erreurs reviennent systématiquement, et chacune a un symptôme reconnaissable.
Le certificat reste en attente. Dans l'immense majorité des cas, le DNS n'a pas fini de se propager, le wildcard pointe ailleurs, ou le port 80 est fermé alors que la validation en a besoin. Vérifiez avec dig avant de suspecter le proxy. Si vous avez basculé entre Traefik et Caddy sur une instance ancienne, revoyez les labels de proxy de l'étape 8.
Le build échoue sans message clair. Sur un VPS à 2 Go de RAM qui héberge déjà une base, un build Node.js se fait tuer par le noyau à court de mémoire. Le message est rarement explicite. Montez la machine, activez du swap comme le suggère la documentation, ou déportez le build (voir plus bas).
Une variable est bien là, mais pas au bon moment. Relisez l'étape 9 et les deux drapeaux. C'est presque toujours ça.
L'application tourne mais le proxy renvoie 404 ou « No available server ». Regardez le healthcheck avant tout : Traefik ne route pas vers une ressource dont le test échoue, même si elle répond parfaitement sur son port. Vérifiez aussi que le conteneur embarque bien curl ou wget si le test est configuré depuis l'interface.
Le dashboard est resté joignable en direct. Le cas le plus grave, et le plus discret, d'autant qu'un ufw status rassurant ne prouve rien pour les ports publiés par Docker. Testez depuis l'extérieur, et faites du pare-feu de votre fournisseur la référence.
Où se situe Coolify
Coolify se décrit lui-même comme « une alternative PaaS open source et auto-hébergeable à Vercel, Heroku et Netlify », permettant de déployer sites statiques, bases de données, applications full-stack et plus de 280 services en un clic sur ses propres serveurs. La licence est Apache-2.0, et le dépôt affiche plus de 60 000 étoiles sur GitHub au 18 août 2026, ce qui situe la taille de la communauté derrière l'outil.
Le vrai arbitrage, pour la plupart des équipes, ne se joue pas entre Coolify et une plateforme managée : il se joue entre Coolify et les autres PaaS auto-hébergés. C'est un sujet à part entière, que nous avons traité en détail dans notre comparatif Coolify et Dokploy, avec les critères qui comptent vraiment au quotidien.
Pour aller plus loin
Trois évolutions valent le détour une fois l'installation de base stabilisée.
Déporter le build. Un serveur de build dédié compile les projets séparément de la machine qui sert la production, ce qui règle le problème de mémoire évoqué plus haut. Les prérequis sont exigeants : les images finales doivent être poussées vers un registre de conteneurs, le serveur de build doit être authentifié auprès de ce registre, disposer de Docker Engine, d'une architecture identique à celle des serveurs de déploiement et d'un accès au code source. L'activation se fait à l'ajout du serveur, ou plus tard depuis la page Servers, puis application par application dans les General settings, section Build, avec l'interrupteur « Use a Build Server? ». Une limite documentée depuis la v4.0.0-beta.408 est à connaître avant de s'organiser : on ne peut déployer aucune application sur un serveur marqué comme serveur de build. Les détails sont sur la page dédiée au serveur de build.
Essayer Caddy. Si la configuration Traefik vous pèse, la bascule est réversible depuis beta.237. Testez-la sur un environnement de staging avant la production, en gardant l'histoire des labels en tête.
Systématiser les secrets de build. Une fois le mécanisme de l'étape 9 compris, il n'y a plus de raison d'écrire un token de registre privé en variable de build classique. C'est une habitude qui coûte cinq minutes à prendre et évite une fuite bête.
Quelques pistes pour élargir le sujet :
- Déployer des conteneurs en local avec Rancher Desktop
- Un audit et une étude de cadrage avant de se lancer
- La maintenance applicative dans la durée
- Notre méthode de travail
- Notre agence
Reste la question qui décide vraiment de la réussite d'un self-hosting : qui met à jour, qui surveille, qui restaure à trois heures du matin. Coolify enlève l'essentiel de la complexité de déploiement, il ne supprime pas la maintenance. Prévoyez la maintenance applicative dans votre plan de charge dès le premier jour, c'est ce qui distingue une installation qui tient trois ans d'une installation qu'on abandonne au bout de six mois.
