- De zéro serveur à un script Python en production sur VPS Hetzner, pour moins de 5€/mois.
- SSH, user non-root, ufw, Python 3.12, venv par projet, .env pour les secrets.
- Cron avec chemin absolu vers le Python du venv — la cause numéro 1 des scripts silencieusement cassés.
- Monitoring minimal via webhook : savoir quand ça casse, pas le découvrir 3 semaines plus tard.
Lecture complète : 14 min
Pourquoi j’ai écrit ce guide
Quand j’ai commandé mon premier VPS Hetzner, je ne savais pas ce qu’était SSH. Je ne savais pas que Python était déjà installé sur Ubuntu. Je ne savais pas qu’un script qui marche en local peut planter en production pour cinq raisons différentes.
J’ai passé 6 heures à tout configurer pour la première fois. Puis j’ai fait les mêmes erreurs sur mon deuxième projet. Et sur le troisième. Ce guide est celui que j’aurais voulu trouver avant de commencer. Pas un cours de sysadmin. Pas un tuto qui suppose que tu sais ce qu’est un pipe. Juste les étapes exactes, dans l’ordre, pour aller d’une page Hetzner vierge à un script Python fonctionnel en production.
Étape 1 : commander le bon VPS
Hetzner propose des VPS à partir de 4,51 euros par mois. Pour un script Python qui tourne quelques fois par jour, c’est largement suffisant. Voici ce que je recommande pour commencer :
- Modèle : CX22 (2 vCPU, 4 Go RAM, 40 Go SSD)
- Système : Ubuntu 24.04
- Localisation : Falkenstein ou Nuremberg (le plus proche de la France)
- Clé SSH : à configurer maintenant, pas après
Sur la page de commande, Hetzner te propose d’ajouter une clé SSH publique. Fais-le. Si tu actives l’authentification par mot de passe, chaque bot du monde entier va tenter de se connecter à ton serveur dans l’heure qui suit.
Générer ta clé SSH
Sur ton Mac ou Linux, ouvre un terminal :
ssh-keygen -t ed25519 -C "ton@email.com"
Sur Windows, utilise PowerShell ou Git Bash avec la même commande.
Copie la clé publique :
cat ~/.ssh/id_ed25519.pub
Colle-la dans le champ SSH de Hetzner lors de la commande. Ton serveur sera prêt en moins de 30 secondes.
Étape 2 : première connexion SSH
Hetzner te donne une adresse IP. Connecte-toi :
ssh root@TON_IP
Si tu vois root@vps:~#, tu es dedans. Première chose à faire : mettre le système à jour.
apt update && apt upgrade -y
Créer un utilisateur non-root
Travailler en root, c’est conduire sans ceinture. Un mauvais rm et tu perds tout.
adduser deploy
usermod -aG sudo deploy
Copie ta clé SSH vers le nouvel utilisateur :
mkdir -p /home/deploy/.ssh
cp /root/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh
Déconnecte-toi et reconnecte-toi avec le nouvel utilisateur :
ssh deploy@TON_IP
Étape 3 : sécuriser le minimum vital
Trois réglages qui prennent 5 minutes et qui éliminent 90% des attaques automatisées.
Désactiver le login root par SSH
sudo nano /etc/ssh/sshd_config
Trouve la ligne PermitRootLogin et change-la en :
PermitRootLogin no
Désactiver l’authentification par mot de passe
Dans le même fichier :
PasswordAuthentication no
Redémarre SSH :
sudo systemctl restart sshd
Activer le pare-feu
sudo ufw allow OpenSSH
sudo ufw enable
Si tu prévois de servir un site web plus tard, ajoute les ports 80 et 443 :
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Étape 4 : installer Python 3.12 et créer un venv
Ubuntu 24.04 vient avec Python 3.12 préinstallé. Vérifie :
python3 --version
Installe les outils nécessaires :
sudo apt install python3-venv python3-pip -y
Créer un environnement virtuel
C’est la règle numéro un. Ne jamais installer de packages en global. Chaque projet a son propre venv.
mkdir -p ~/projects/mon-script
cd ~/projects/mon-script
python3 -m venv venv
source venv/bin/activate
Quand le venv est activé, tu vois (venv) devant ton prompt. Tous les pip install se font dans cet environnement isolé.
pip install requests python-dotenv
Gèle les dépendances :
pip freeze > requirements.txt
J’ai fait l’erreur d’installer mes packages en global sur mon premier VPS. Quand j’ai lancé un deuxième projet avec des versions différentes, tout a cassé. Le venv aurait évité ça. J’ai détaillé cette erreur et quatre autres dans cet article dédié.
Étape 5 : écrire et tester ton premier script
Crée un fichier :
nano main.py
Un script minimal qui fait une requête API et écrit le résultat dans un fichier de log :
import requests
from datetime import datetime
response = requests.get("https://httpbin.org/get")
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open("output.log", "a") as f:
f.write(f"[{timestamp}] Status: {response.status_code}\n")
print(f"Done at {timestamp}")
Teste-le :
python main.py
cat output.log
Si tu vois la ligne de log, ton Python fonctionne sur le VPS. Tu peux remplacer le contenu par n’importe quel script : appel API Gemini, scraping, envoi de notifications. La structure reste la même.
Étape 6 : variables d’environnement avec .env
Ne mets jamais tes clés API en dur dans le code. Crée un fichier .env :
nano .env
API_KEY=ta_cle_ici
NOTION_TOKEN=ton_token_notion
Dans ton script Python :
from dotenv import load_dotenv
import os
load_dotenv()
api_key = os.getenv("API_KEY")
Ajoute .env à ton .gitignore si tu versionnes le code.
Étape 7 : automatiser avec cron
Cron exécute des commandes à intervalles réguliers. C’est le planificateur intégré de Linux.
crontab -e
Pour exécuter ton script toutes les 6 heures :
0 */6 * * * cd /home/deploy/projects/mon-script && /home/deploy/projects/mon-script/venv/bin/python main.py >> /home/deploy/projects/mon-script/cron.log 2>&1
Trois points que j’ai appris en perdant des heures :
- Utilise le chemin absolu du Python dans le venv. Cron ne charge pas ton
.bashrc. Si tu écris justepython, il utilisera le Python système, sans tes packages. - Redirige stdout ET stderr. Le
2>&1capture les erreurs. Sans ça, ton script peut planter toutes les 6 heures pendant des jours sans que tu le saches. cdvers le répertoire du projet d’abord. Les chemins relatifs dans ton script (commeoutput.logou.env) ne fonctionnent que si le répertoire courant est le bon.
J’ai raconté en détail la journée où j’ai configuré tout ça pour la première fois, bugs inclus.
Étape 8 : monitoring minimal
Un script qui tourne en cron sans monitoring, c’est un script dont tu ne sauras pas qu’il est mort.
Solution simple : vérifier les logs
tail -20 ~/projects/mon-script/cron.log
Solution robuste : alerte par webhook
Ajoute à la fin de ton script :
import requests
def send_alert(message):
webhook_url = os.getenv("ALERT_WEBHOOK")
if webhook_url:
requests.post(webhook_url, json={"text": message})
try:
# ... ton code principal ...
send_alert("Script OK")
except Exception as e:
send_alert(f"ERREUR: {e}")
Tu peux pointer ce webhook vers Slack, Discord, ou n’importe quel endpoint qui te prévient. L’idée c’est de savoir quand ça casse, pas de le découvrir trois semaines plus tard en vérifiant manuellement.
Étape 9 : déployer un vrai projet
Une fois ces bases en place, tu es prêt à déployer un vrai pipeline. Voici la stack que j’utilise pour automatiser la promotion de Copyboost :
- Un script Python qui appelle l’API Gemini pour générer du contenu
- Notion comme base de données pour stocker les drafts
- Cron pour lancer le script à heures fixes
- Un webhook Discord pour me prévenir des succès et des erreurs
J’ai documenté cette stack complète, avec les deux bugs qui ont tout cassé au premier lancement.
Récapitulatif de la checklist
- Commander un VPS CX22 sur Hetzner avec clé SSH
- Créer un utilisateur non-root, désactiver root login et mots de passe
- Activer ufw
- Vérifier Python 3.12, créer un venv par projet
- Stocker les secrets dans
.env - Configurer cron avec chemin absolu vers le Python du venv
- Rediriger stdout + stderr dans un fichier de log
- Ajouter un webhook d’alerte
Si tu suis ces 8 étapes, tu as un VPS fonctionnel, sécurisé, et capable de faire tourner n’importe quel script Python en production. Le tout pour moins de 5 euros par mois.
Tous les articles de la série VPS
Ce guide est le point d’entrée de la série. Chaque article approfondit un aspect de la configuration et de l’automatisation sur VPS Hetzner.
- Configurer un VPS pour automatiser sa création de contenu : 6h de debug, deux bugs réels — Le pipeline complet VPS + Python + Gemini + Notion, avec les deux bugs qui m’ont coûté une journée.
- 5 erreurs Python sur VPS qui m’ont coûté des heures — Les cinq erreurs de déploiement les plus fréquentes : environnements, cron, variables d’env, permissions, logs.
- Automatiser la promotion de son SaaS depuis un VPS — Générer des posts LinkedIn Build in Public avec Python et l’API Gemini, deux bugs documentés.
- Automatiser LinkedIn avec Python et Notion — Script Python de 150 lignes pour publier sur LinkedIn via Notion depuis un VPS.
- Erreur EADDRINUSE sur Node.js : pourquoi ça arrive et comment la corriger — lsof, kill et systemd pour éviter qu’un port occupé bloque indéfiniment ton serveur.
Dernière mise à jour : mai 2026
Discussion