Offre Durée limitée : -10% sur tout le site avec le code WELCOME10

Publier un service sur un VPS Linux derrière Nginx en HTTPS

Mis à jour le 19 septembre 2026 10 min de lecture 12 sections

Exposer un service sur un VPS Linux en HTTP simple, c'est laisser circuler en clair les mots de passe de vos utilisateurs comme de vos administrateurs. Ce guide couvre la chaîne complète : installer Nginx, déclarer le domaine, obtenir un certificat Let's Encrypt, passer en reverse proxy vers votre application, forcer le HTTPS et vérifier que le renouvellement automatique fonctionne réellement. Chaque étape est donnée dans l'ordre, avec la commande et le contrôle qui permet de savoir si elle a réussi.

Les prérequis à vérifier avant de toucher à la configuration

  • Un VPS Linux accessible en SSH, avec un compte disposant de sudo.
  • Un nom de domaine ou un sous-domaine dont l'enregistrement DNS de type A pointe vers l'adresse IP publique du serveur.
  • Le service à publier, qui écoute déjà sur une adresse et un port local, par exemple 127.0.0.1:3000 pour une application Node, Python ou un panel d'administration.
  • Les ports TCP 80 et 443 joignables depuis Internet. La validation d'un certificat Let's Encrypt passe par le port 80 dans le cas le plus courant, et ce même port sert ensuite à rediriger les visiteurs vers HTTPS.

Commencez par contrôler la résolution DNS, car tout le reste en dépend. Si le nom ne pointe pas encore vers le bon serveur, le certificat ne pourra pas être délivré et le navigateur ne trouvera pas votre service, quelle que soit la qualité de la configuration Nginx.

dig +short panel.example.com
hostname -I

Les deux réponses doivent afficher la même adresse IP publique. Un enregistrement DNS modifié récemment peut mettre de quelques minutes à quelques heures à se propager ; attendez avant de conclure à une erreur de configuration.

Installer Nginx et vérifier que le service tourne

sudo apt update
sudo apt install nginx -y
sudo systemctl enable --now nginx
systemctl status nginx --no-pager

Sur Debian et Ubuntu, le paquet installe un serveur web déjà actif qui sert une page d'accueil sur le port 80. La configuration globale se trouve dans /etc/nginx/nginx.conf ; les sites sont déclarés dans un fichier de /etc/nginx/sites-available/ puis activés par un lien symbolique dans /etc/nginx/sites-enabled/.

Deux commandes structurent ensuite tout le travail : sudo nginx -t valide la syntaxe de la configuration, et sudo systemctl reload nginx applique la nouvelle version sans couper les connexions en cours. Lancez toujours le test avant le rechargement. Une configuration invalide fait échouer le rechargement en laissant l'ancienne configuration active, ce qui donne l'illusion que la modification a été prise en compte alors qu'elle n'a jamais été chargée.

Déclarer le domaine dans un premier bloc server

Créez un fichier de site dédié plutôt que de modifier la configuration par défaut :

sudo nano /etc/nginx/sites-available/panel.example.com
server {
    listen 80;
    listen [::]:80;
    server_name panel.example.com;

    root /var/www/panel;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Activez le site, testez la syntaxe, puis rechargez :

sudo ln -s /etc/nginx/sites-available/panel.example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Le nom de domaine doit apparaître dans server_name exactement tel qu'il est saisi dans le navigateur. Un nom présent à un seul endroit, alors que le serveur héberge plusieurs sites, produit un site qui répond sur l'adresse IP mais pas sur le domaine attendu. Ce point de configuration est la cause la plus fréquente des surprises lors d'une première mise en ligne.

Ouvrir les ports 80 et 443 dans le pare-feu

sudo ufw allow 'Nginx Full'
sudo ufw status verbose

Le profil Nginx Full, fourni par le paquet Nginx, ouvre les ports 80 et 443 d'un seul coup. Si un de ces ports reste bloqué, le site répond en local depuis le serveur mais jamais depuis Internet, et la validation du certificat échoue sans message très explicite. Notre guide pour ouvrir les ports d'un serveur Linux avec UFW détaille la logique des règles et des profils d'application.

Obtenir un certificat Let's Encrypt avec Certbot

Let's Encrypt recommande Certbot comme client ACME de référence. Sur Ubuntu, la procédure officielle passe par snap, afin de ne pas dépendre d'un paquet de distribution plus ancien :

sudo apt remove certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot
sudo certbot --nginx

La commande certbot --nginx obtient le certificat et modifie la configuration Nginx pour le servir, en une seule étape. Si vous préférez écrire vous-même la configuration, utilisez sudo certbot certonly --nginx : le certificat est alors déposé dans /etc/letsencrypt/live/panel.example.com/, avec fullchain.pem et privkey.pem, que vous référencez à la main.

Un certificat Let's Encrypt est valide 90 jours, sans durée personnalisable. L'organisme recommande de renouveler au bout de 60 jours, marge comprise pour corriger un éventuel problème. Retenez la logique : plus un certificat s'approche de l'expiration, moins vous avez de temps pour réparer une validation qui échoue.

Passer en reverse proxy vers votre application

Le scénario le plus courant consiste à laisser l'application écouter uniquement en local et à confier le chiffrement, le nom de domaine et l'exposition publique à Nginx :

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name panel.example.com;

    ssl_certificate     /etc/letsencrypt/live/panel.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/panel.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Trois points méritent votre attention. D'abord, l'application doit écouter sur 127.0.0.1 et non sur toutes les interfaces : sinon elle reste joignable en HTTP non chiffré sur son propre port, et le HTTPS de Nginx ne protège plus rien. Ensuite, les en-têtes transmis font que votre application voit l'adresse IP réelle du visiteur au lieu de celle du proxy, et qu'elle peut générer des URL en HTTPS grâce à X-Forwarded-Proto. Enfin, les deux derniers en-têtes ne servent que si le service utilise du WebSocket, ce qui est le cas des consoles web et des terminaux intégrés : sans eux, la négociation échoue et l'interface reste bloquée sur un écran de chargement. La documentation de Nginx précise que proxy_http_version 1.1 était nécessaire pour cela avant la version 1.29.7.

Notez également que Nginx ferme une connexion WebSocket si le serveur en amont n'envoie rien pendant 60 secondes par défaut. Sur une console qui reste ouverte sans activité, ajustez proxy_read_timeout plutôt que de laisser les sessions se couper toutes les minutes.

http2 on; est disponible depuis Nginx 1.25.1. Sur une version plus ancienne, la même fonction s'obtient avec listen 443 ssl http2;.

Rediriger tout le trafic du port 80 vers HTTPS

server {
    listen 80;
    listen [::]:80;
    server_name panel.example.com;
    return 301 https://$host$request_uri;
}

Certbot propose cette redirection automatiquement lors de sa première exécution en mode --nginx. Conservez malgré tout le bloc sur le port 80 : il continue de servir au renouvellement du certificat et à la redirection des anciens liens indexés ou partagés.

Durcir la configuration TLS

ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

Depuis Nginx 1.27.3, les protocoles activés par défaut sont TLS 1.2 et TLS 1.3. Sur des versions antérieures, la valeur par défaut peut encore accepter des protocoles obsolètes : écrire la ligne explicitement évite que le niveau de sécurité de votre service dépende de la version installée. Un test simple consiste à demander une poignée de main avec un protocole obsolète : elle doit être refusée.

echo | openssl s_client -connect panel.example.com:443 -tls1_1

Le cache de session évite de refaire une négociation complète à chaque requête, ce qui réduit la latence perçue sur une application qui enchaîne beaucoup de petits appels.

Sauvegarder les fichiers de configuration avant de modifier

Un serveur web qui héberge plusieurs applications web finit toujours par accumuler des fichiers de configuration. Avant d'y toucher, dupliquez le fichier concerné : revenir en arrière coûte alors une seule commande, alors qu'une parenthèse oubliée se paie en site inaccessible.

sudo cp /etc/nginx/sites-available/panel.example.com /etc/nginx/sites-available/panel.example.com.bak
ls -l /etc/nginx/sites-available/

La logique repose sur les hôtes virtuels (virtual hosts) : un fichier de configuration par nom de domaine, et un lien symbolique dans sites-enabled pour l'activer. Pour désactiver proprement un site, supprimez uniquement le lien symbolique et gardez le fichier d'origine :

sudo rm /etc/nginx/sites-enabled/panel.example.com
sudo nginx -t
sudo systemctl reload nginx

En ligne de commande, prenez aussi l'habitude de relire la configuration du serveur en entier après plusieurs mois : un fichier oublié qui pointe vers un domaine devenu inutile reste chargé et peut répondre à la place d'un autre site. Si vous devez redémarrer Nginx plutôt que le recharger, vérifiez d'abord la syntaxe, car un redémarrage avec une configuration fautive coupe le service jusqu'à la correction.

Nginx n'est pas le seul serveur web possible : Apache reste très répandu sur les hébergements mutualisés, et beaucoup d'applications web embarquent leur propre serveur intégré qui écoute sur un port local. Dans tous ces cas, si vous voulez du HTTPS, le rôle du serveur web frontal reste identique : terminer le chiffrement, recevoir les requêtes TCP sur le port 443 et les transmettre à l'application. Ce tutoriel se limite à Nginx, qui couvre le besoin le plus courant sur un VPS Linux.

Vérifier le renouvellement automatique du certificat

systemctl list-timers | grep certbot
sudo certbot renew --dry-run

Les paquets Certbot installent un cron job ou un timer systemd qui lance le renouvellement sans intervention de votre part. Sur une installation par snap, ce timer s'appelle snap.certbot.renew.timer et s'exécute deux fois par jour. Depuis Certbot 4.0.0, un certificat est considéré comme à renouveler dès qu'il reste moins d'un tiers de sa durée de vie, soit environ 30 jours pour un certificat de 90 jours ; avant cette version, le seuil était fixé à 30 jours. L'option --dry-run teste toute la chaîne sans consommer de quota auprès de l'autorité de certification.

Un renouvellement qui échoue en silence est le pire des scénarios : le service fonctionne normalement jusqu'au jour où les visiteurs voient un avertissement de sécurité, puis plus rien. Contrôlez donc les deux points, le timer actif et le renouvellement à blanc, et refaites ce contrôle après chaque modification de la configuration Nginx ou du DNS. Si aucun timer n'existe sur votre système, ajoutez un appel régulier à certbot renew dans le planificateur de votre choix.

Diagnostiquer les erreurs les plus fréquentes

  • Le certificat n'est jamais délivré : le port 80 est fermé, le DNS ne pointe pas encore vers le serveur, ou une autre machine répond à la place. Le détail de la tentative est écrit dans /var/log/letsencrypt/letsencrypt.log.
  • Erreur 502 Bad Gateway : l'application locale est arrêtée ou écoute sur un autre port que celui du proxy_pass. La commande ss -lntp liste les ports réellement en écoute.
  • Rechargement refusé : sudo nginx -t indique le fichier et la ligne fautive ; l'ancienne configuration reste active tant que la nouvelle n'est pas valide.
  • Boucle de redirection : un autre proxy placé en amont gère déjà le HTTPS et transmet son propre en-tête. Dans ce cas, adaptez la redirection au lieu de la cumuler.
  • WebSocket qui ne se connecte pas : en-têtes Upgrade et Connection absents, ou délai de 60 secondes dépassé côté amont.
  • Diagnostic du service : journalctl -u nginx -n 50 --no-pager pour le service, et /var/log/nginx/error.log pour les erreurs applicatives vues par Nginx.

Pour aller plus loin

Un service publié est aussi un service à surveiller. Si le VPS devient injoignable, notre guide pour diagnostiquer un VPS inaccessible en 30 secondes vous aide à séparer un problème réseau d'un problème applicatif. Si votre service tourne dans un conteneur, voyez installer Docker sur un VPS. Enfin, avant d'ouvrir un service à Internet, il est prudent de limiter les tentatives de connexion SSH.

La démarche décrite ici fonctionne sur un VPS Linux standard, où vous gardez la main sur le serveur web et sur les certificats. Si vous partez d'une machine neuve, comparez nos offres de VPS Linux et leurs images Ubuntu pour choisir l'environnement le plus proche de votre stack.

Configurez votre VPS Linux et mettez votre service en HTTPS dès aujourd'hui.

Déployer mon VPS Linux