guides/serveur/vps-setup-complet.md

1463 lines
38 KiB
Markdown
Raw Permalink Normal View History

# Mettre en place un serveur VPS
Guide complet pour configurer et sécuriser un serveur VPS depuis zéro.
---
## 📋 Table des matières
1. [Prérequis](#prérequis)
2. [Première connexion](#première-connexion)
3. [Sécurisation de base](#sécurisation-de-base)
4. [Installation d'un serveur web](#installation-dun-serveur-web)
5. [Déploiement](#déploiement)
6. [Maintenance](#maintenance)
7. [Ressources](#ressources)
---
## Prérequis
### Ce dont vous avez besoin
- Un VPS chez un hébergeur (OVH, Hetzner, DigitalOcean, Infomaniak, etc.)
- Une adresse IP publique (fournie par l'hébergeur)
- Un terminal (macOS/Linux)
- 1h-2h devant vous
**📝 Note sur Vim :** Ce guide utilise **vim** pour éditer les fichiers de configuration. Vim est l'éditeur standard présent sur tous les serveurs Linux.
**Débutant avec Vim ?** → Consultez [vim-guide-essentiel.md](linux-essentials/vim-guide-essentiel.md) (15 min de lecture)
**Commandes minimales pour suivre ce guide :**
- `i` : Passer en mode édition
- `Esc` : Sortir du mode édition
- `:wq` : Sauvegarder et quitter
- `:q!` : Quitter sans sauvegarder
### Informations à noter
Avant de commencer, notez ces informations fournies par votre hébergeur :
```
IP du VPS : _______________
Utilisateur initial : _______ (root, ubuntu, admin, ou autre)
Mot de passe/clé SSH : _______________
Distribution : Debian / Ubuntu (recommandé)
```
### ⚠️ Deux types d'accès VPS
Votre configuration initiale dépend de votre hébergeur :
**Type A - Accès root direct** (OVH, Hetzner, DigitalOcean)
- Connexion : `ssh root@IP`
- Vous devez créer vous-même un utilisateur non-root
- Suivez toutes les étapes ci-dessous
**Type B - Utilisateur sudo pré-configuré** (Infomaniak, hébergeurs managed)
- Connexion : `ssh ubuntu@IP` (ou autre utilisateur fourni)
- L'utilisateur a déjà les droits sudo
- **Sautez l'étape 3** (création d'utilisateur)
- Pour les commandes root, utilisez `sudo` devant chaque commande
---
## Première connexion
### Étape 1 : Se connecter au VPS
**Pourquoi ?** Établir la première connexion sécurisée à votre serveur et vérifier que tout fonctionne.
**Type A - Connexion root :**
```bash
ssh root@<adresse-IP>
# Entrez le mot de passe fourni par l'hébergeur
```
**Type B - Connexion utilisateur sudo (Infomaniak, etc.) :**
```bash
ssh ubuntu@<adresse-IP>
# Ou : ssh admin@<adresse-IP>
# Selon l'utilisateur fourni par votre hébergeur
```
**Première connexion :**
```bash
# Le serveur vous demande de confirmer son empreinte SSH
The authenticity of host 'xxx.xxx.xxx.xxx' can't be established.
ED25519 key fingerprint is SHA256:...
Are you sure you want to continue connecting (yes/no)?
# Tapez "yes" et Entrée
# Ceci enregistre le serveur comme connu et évite les attaques MITM
```
**Si vous êtes connecté en root (Type A), changez le mot de passe :**
```bash
passwd
# Entrez un mot de passe FORT (20+ caractères, complexe)
# Pourquoi ? Le mot de passe initial est souvent simple ou envoyé par email (non sécurisé)
```
**Si vous avez un utilisateur sudo (Type B), vérifiez vos droits :**
```bash
sudo -v
# Doit répondre sans erreur
# Si demandé, entrez le mot de passe sudo fourni par l'hébergeur
```
### Étape 2 : Mettre à jour le système
**Pourquoi ?** Les images serveur contiennent souvent des paquets obsolètes avec des failles de sécurité. La première chose à faire est de tout mettre à jour.
**Type A (root) :**
```bash
# Mettre à jour la liste des paquets disponibles
apt update
# Installer toutes les mises à jour de sécurité et correctifs
apt upgrade -y
# Supprimer les paquets obsolètes qui ne sont plus nécessaires
apt autoremove -y
```
**Type B (sudo) :**
```bash
# Même chose mais avec sudo devant chaque commande
sudo apt update
sudo apt upgrade -y
sudo apt autoremove -y
```
**💡 Astuce :** Combinez les commandes pour gagner du temps :
```bash
sudo apt update && sudo apt upgrade -y && sudo apt autoremove -y
```
---
## Sécurisation de base
### Étape 3 : Créer un utilisateur non-root
**⚠️ Type B (Infomaniak, etc.) : SAUTEZ CETTE ÉTAPE** - vous avez déjà un utilisateur sudo
**Type A uniquement (accès root direct) :**
**Pourquoi ?** Le compte root a tous les privilèges sans restriction. Une simple erreur de commande (ex: `rm -rf /`) peut détruire tout le système. Un utilisateur non-root avec sudo est plus sûr :
- Vous devez taper `sudo` avant chaque commande sensible (temps de réflexion)
- Les logs montrent qui a fait quoi (traçabilité)
- Les scripts ne peuvent pas accidentellement tout casser
**Création de l'utilisateur :**
```bash
# Créer un utilisateur (remplacez "monuser" par votre nom)
adduser monuser
# Le système vous demande :
# - Un mot de passe (FORT, 20+ caractères)
# - Des infos optionnelles (nom complet, etc.) - appuyez sur Entrée pour ignorer
# Ajouter l'utilisateur au groupe sudo (droits administrateur)
usermod -aG sudo monuser
# Vérifier que l'utilisateur est bien dans le groupe sudo
groups monuser
# Sortie attendue : monuser : monuser sudo
```
**💡 Note :** Choisissez un nom d'utilisateur :
- Simple et court (ex: votre prénom)
- Pas "admin" ou "user" (trop prévisible pour les attaquants)
- Sans caractères spéciaux
### Étape 4 : Configurer l'authentification par clé SSH
**Pourquoi ?** Les mots de passe peuvent être :
- Devinés par force brute (des milliers de tentatives par jour)
- Interceptés sur un réseau compromis
- Oubliés ou réutilisés
Les clés SSH sont :
- Mathématiquement impossibles à deviner (256 bits d'entropie)
- Jamais transmises sur le réseau (seule une signature l'est)
- Uniques par machine (pas de réutilisation)
**⚠️ Si votre hébergeur (Type B) a déjà configuré une clé SSH à la création du VPS, SAUTEZ CETTE ÉTAPE**
---
**1⃣ Sur votre machine locale (pas le VPS) : Créer ou vérifier votre clé SSH**
```bash
# Vérifier si vous avez déjà une clé SSH
ls -la ~/.ssh/id_*.pub
# Si vous voyez "id_ed25519.pub" ou "id_rsa.pub", vous avez déjà une clé ✅
# Sinon, créez-en une :
ssh-keygen -t ed25519 -C "votre-email@example.com"
# Questions posées :
# "Enter file in which to save the key" → Appuyez sur Entrée (emplacement par défaut)
# "Enter passphrase" → Appuyez sur Entrée (pas de passphrase, ou tapez-en une si vous voulez plus de sécurité)
# "Enter same passphrase again" → Appuyez sur Entrée
# Afficher votre clé publique
cat ~/.ssh/id_ed25519.pub
# Copiez TOUTE la ligne (commence par "ssh-ed25519 AAAA..." et finit par votre email)
```
**💡 Passphrase ou pas ?**
- **Sans passphrase** : Connexion automatique (pratique pour scripts)
- **Avec passphrase** : Protection supplémentaire si quelqu'un vole votre ordinateur
---
**2⃣ Sur le VPS : Ajouter votre clé publique**
**Type A (connecté en root) :**
```bash
# Passer à votre utilisateur
su - monuser
# Créer le dossier .ssh avec les bons droits
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# Créer le fichier authorized_keys
vim ~/.ssh/authorized_keys
# Appuyez sur 'i' pour passer en mode insertion
# Collez votre clé publique (Cmd+V ou Ctrl+Shift+V)
# Appuyez sur Esc puis tapez :wq et Entrée pour sauvegarder et quitter
# Définir les bons droits (important pour la sécurité SSH)
chmod 600 ~/.ssh/authorized_keys
# Retour à root
exit
```
**Type B (connecté avec votre utilisateur sudo) :**
```bash
# Vous êtes déjà votre utilisateur, pas besoin de su -
# Créer le dossier .ssh avec les bons droits
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# Créer le fichier authorized_keys
vim ~/.ssh/authorized_keys
# Appuyez sur 'i' pour passer en mode insertion
# Collez votre clé publique (Cmd+V ou Ctrl+Shift+V)
# Appuyez sur Esc puis tapez :wq et Entrée pour sauvegarder et quitter
# Définir les bons droits
chmod 600 ~/.ssh/authorized_keys
```
---
**3⃣ Tester la connexion par clé SSH**
```bash
# Depuis votre machine locale (ouvrez un NOUVEAU terminal)
ssh monuser@<adresse-IP>
# Ou : ssh ubuntu@<adresse-IP> (selon votre utilisateur)
# ✅ Vous devriez être connecté SANS taper de mot de passe
# ❌ Si on vous demande un mot de passe, vérifiez :
# - Les droits : chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
# - Que la clé publique est bien copiée (une seule ligne, pas de retour à la ligne)
```
**💡 Astuce :** Gardez votre ancienne session SSH ouverte au cas où quelque chose ne fonctionne pas !
### Étape 5 : Sécuriser SSH
**Pourquoi ?** Par défaut, SSH accepte :
- Les connexions root (cible n°1 des attaquants)
- Les mots de passe (vulnérables aux attaques par force brute)
- Le port 22 (scanné en permanence par des bots)
En durcissant SSH, vous bloquez 99% des attaques automatisées.
---
**1⃣ Éditer la configuration SSH**
```bash
# Type A (root)
vim /etc/ssh/sshd_config
# Type B (sudo)
sudo vim /etc/ssh/sshd_config
```
**2⃣ Modifications à faire**
Cherchez ces lignes dans le fichier (Ctrl+W pour chercher) et modifiez-les :
```bash
# Désactiver la connexion root par SSH
PermitRootLogin no
# Pourquoi ? 'root' est le seul nom d'utilisateur connu de tous les attaquants
# Désactiver l'authentification par mot de passe
PasswordAuthentication no
# Pourquoi ? Les bots tentent des milliers de mots de passe par jour
# Désactiver l'authentification par défi-réponse
ChallengeResponseAuthentication no
# Pourquoi ? Autre méthode d'authentification par mot de passe à désactiver
# S'assurer que l'authentification par clé est activée
PubkeyAuthentication yes
# Pourquoi ? C'est la seule méthode sûre que nous autorisons
# (Optionnel) Changer le port SSH
# Port 2222
# Pourquoi ? Les bots scannent le port 22 en priorité
# ⚠️ Si vous faites ça, pensez à autoriser le nouveau port dans le pare-feu !
```
**💡 Conseil :** Ne changez le port SSH que si vous comprenez bien ce que vous faites. C'est plus contraignant qu'utile pour un VPS personnel.
**Type B uniquement** - Si vous voulez désactiver le mot de passe mais garder root pour sudo :
```bash
# Gardez root activé mais seulement sans mot de passe
PermitRootLogin prohibit-password
```
---
**3⃣ Redémarrer SSH**
```bash
# Type A (root)
systemctl restart sshd
systemctl status sshd
# Type B (sudo)
sudo systemctl restart sshd
sudo systemctl status sshd
```
---
**4⃣ ⚠️ TESTER AVANT DE FERMER LA SESSION**
**CRITIQUE** : Si vous fermez votre session SSH actuelle avant de tester, vous risquez de vous enfermer dehors !
```bash
# GARDEZ votre session SSH actuelle OUVERTE
# Ouvrez un NOUVEAU terminal et testez :
ssh monuser@<adresse-IP>
# Ou : ssh ubuntu@<adresse-IP>
# Si port modifié : ssh -p 2222 monuser@<adresse-IP>
# ✅ Connexion OK ? Vous pouvez fermer l'ancienne session
# ❌ Connexion refuse ? Retournez dans l'ancienne session et corrigez
```
**Si vous êtes bloqué :**
- La plupart des hébergeurs ont une "console VNC" dans leur interface web
- Connectez-vous via la console et corrigez `/etc/ssh/sshd_config`
### Étape 6 : Installer et configurer le pare-feu (UFW)
**Pourquoi ?** Sans pare-feu, tous les ports de votre serveur sont exposés à Internet. N'importe qui peut :
- Scanner vos services (base de données, admin panels)
- Exploiter des vulnérabilités
- Accéder à des services non sécurisés
**UFW (Uncomplicated Firewall)** = pare-feu simple qui bloque tout sauf ce que vous autorisez explicitement.
---
**1⃣ Installer UFW**
```bash
# Type A (root)
apt install ufw -y
# Type B (sudo)
sudo apt install ufw -y
```
---
**2⃣ Configurer les règles (IMPORTANT : dans cet ordre !)**
```bash
# Note : ufw nécessite toujours sudo (même en root)
# Définir la politique par défaut : TOUT BLOQUER
sudo ufw default deny incoming
# Pourquoi ? Principe de sécurité : interdire par défaut, autoriser au cas par cas
# Autoriser les connexions sortantes (pour apt, wget, etc.)
sudo ufw default allow outgoing
# Pourquoi ? Votre serveur doit pouvoir se connecter à Internet (mises à jour, APIs)
# ⚠️ CRITIQUE : Autoriser SSH AVANT d'activer UFW
sudo ufw allow 22/tcp
# Si vous avez changé le port SSH (étape 5) :
# sudo ufw allow 2222/tcp
# 🚨 Si vous oubliez ça, vous serez bloqué dehors !
# Autoriser HTTP et HTTPS (si vous installez un serveur web)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Pourquoi ? Les visiteurs doivent pouvoir accéder à votre site
# Afficher les règles avant activation (vérification)
sudo ufw show added
```
---
**3⃣ Activer le pare-feu**
```bash
# Activer UFW
sudo ufw enable
# Il vous demande confirmation (la connexion SSH peut être interrompue)
# Tapez 'y' puis Entrée
# Vérifier que tout fonctionne
sudo ufw status verbose
# Résultat attendu :
# Status: active
# To Action From
# -- ------ ----
# 22/tcp ALLOW Anywhere
# 80/tcp ALLOW Anywhere
# 443/tcp ALLOW Anywhere
```
**✅ Si vous voyez ce résultat, c'est bon !**
**❌ Si votre connexion SSH se coupe, vous avez oublié `sudo ufw allow 22/tcp`**
---
**4⃣ Commandes utiles UFW**
```bash
# Voir les règles numérotées
sudo ufw status numbered
# Supprimer une règle (ex: règle n°3)
sudo ufw delete 3
# Autoriser un port spécifique (ex: pour une app Node.js)
sudo ufw allow 8080/tcp
# Autoriser une IP spécifique (ex: votre IP fixe pour un service admin)
sudo ufw allow from 203.0.113.0/24 to any port 3306
# Utile pour restreindre l'accès à MySQL/PostgreSQL
# Désactiver temporairement UFW
sudo ufw disable
# Réactiver
sudo ufw enable
# Réinitialiser (supprime toutes les règles)
sudo ufw reset
```
**💡 Bonne pratique :** N'ouvrez que les ports dont vous avez besoin. Si vous installez un nouveau service plus tard, ajoutez la règle à ce moment-là.
### Étape 7 : Installer Fail2ban
**Pourquoi ?** Même avec SSH sécurisé, des bots vont :
- Scanner votre serveur 24/7
- Tenter des milliers de connexions SSH
- Essayer des mots de passe courants
- Saturer vos logs et ralentir le serveur
**Fail2ban** surveille les logs et bannit automatiquement les IP malveillantes.
**Exemple concret :**
```
2026-02-13 10:23:45 Failed password for root from 185.220.101.23
2026-02-13 10:23:47 Failed password for root from 185.220.101.23
2026-02-13 10:23:49 Failed password for root from 185.220.101.23
→ Fail2ban bannit 185.220.101.23 pendant 10 minutes (ou plus)
```
---
**1⃣ Installer Fail2ban**
```bash
# Type A (root)
apt install fail2ban -y
# Type B (sudo)
sudo apt install fail2ban -y
```
---
**2⃣ Créer une configuration personnalisée**
**Pourquoi jail.local et pas jail.conf ?**
- `jail.conf` = fichier par défaut (écrasé lors des mises à jour)
- `jail.local` = votre config personnalisée (prioritaire, jamais écrasé)
```bash
# Copier le fichier par défaut
# Type A
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# Type B
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# Éditer votre configuration
# Type A
vim /etc/fail2ban/jail.local
# Type B
sudo vim /etc/fail2ban/jail.local
```
---
**3⃣ Configuration recommandée**
Cherchez et modifiez ces sections dans `jail.local` :
```ini
[DEFAULT]
# Durée de bannissement (10 minutes = 600 secondes)
bantime = 600
# Augmentez à 3600 (1h) ou 86400 (24h) pour être plus strict
# Période d'observation (10 minutes)
findtime = 600
# Sur 10 min, si on dépasse maxretry → ban
# Nombre de tentatives autorisées avant ban
maxretry = 5
# Réduisez à 3 pour être plus strict
# Email de notification (optionnel - nécessite un serveur mail configuré)
# destemail = votre-email@example.com
# sendername = Fail2ban-VPS
# action = %(action_mwl)s
[sshd]
enabled = true
port = 22
# Si vous avez changé le port SSH :
# port = 2222
# Par défaut, Fail2ban surveille déjà les tentatives SSH
# Pas besoin d'ajouter d'autres paramètres
```
**💡 Explication des paramètres :**
- `bantime = 600` : Bloquer l'IP pendant 10 minutes
- `findtime = 600` : Observer sur les 10 dernières minutes
- `maxretry = 5` : Si 5 échecs en 10 min → ban 10 min
---
**4⃣ Démarrer Fail2ban**
```bash
# Type A (root)
systemctl start fail2ban
systemctl enable fail2ban
systemctl status fail2ban
# Type B (sudo)
sudo systemctl start fail2ban
sudo systemctl enable fail2ban
sudo systemctl status fail2ban
# Vérifier que Fail2ban fonctionne
# Type A
fail2ban-client status
# Type B
sudo fail2ban-client status
# Résultat attendu :
# Status
# |- Number of jail: 1
# `- Jail list: sshd
# Voir les détails de la jail SSH
sudo fail2ban-client status sshd
# Affiche : nombre d'IPs bannies, liste des IPs bannies
```
---
**5⃣ Commandes utiles Fail2ban**
```bash
# Voir toutes les jails actives
sudo fail2ban-client status
# Voir les IPs bannies pour SSH
sudo fail2ban-client status sshd
# Débannir manuellement une IP (si vous vous êtes bloqué)
sudo fail2ban-client set sshd unbanip 203.0.113.45
# Bannir manuellement une IP
sudo fail2ban-client set sshd banip 185.220.101.23
# Recharger la configuration après modifications
sudo fail2ban-client reload
# Voir les logs Fail2ban en temps réel
sudo tail -f /var/log/fail2ban.log
```
**🎯 Résultat :** Vous verrez les attaques en temps réel dans les logs, et Fail2ban les bloquera automatiquement !
### Étape 8 : Configurer les mises à jour automatiques
**Pourquoi ?** En 2026, des dizaines de nouvelles vulnérabilités sont découvertes chaque mois :
- Failles zero-day dans le noyau Linux
- Bugs critiques dans OpenSSH, Apache, etc.
- Exploits rendus publics (CVE)
**Sans mises à jour régulières**, votre serveur devient vulnérable en quelques semaines.
**Avec unattended-upgrades :**
- Les correctifs de sécurité s'installent automatiquement
- Vous dormez tranquille
- Redémarrage automatique aux heures creuses si nécessaire
---
**1⃣ Installer unattended-upgrades**
```bash
# Type A (root)
apt install unattended-upgrades -y
# Type B (sudo)
sudo apt install unattended-upgrades -y
```
---
**2⃣ Activer la configuration automatique**
```bash
# Type A
dpkg-reconfigure -plow unattended-upgrades
# Type B
sudo dpkg-reconfigure -plow unattended-upgrades
# Interface graphique → Sélectionnez "Oui" avec les flèches puis Entrée
```
---
**3⃣ Personnaliser la configuration (optionnel mais recommandé)**
```bash
# Type A
vim /etc/apt/apt.conf.d/50unattended-upgrades
# Type B
sudo vim /etc/apt/apt.conf.d/50unattended-upgrades
```
**Configuration recommandée :**
```bash
# Quelles mises à jour installer automatiquement ?
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-security";
# Ne mettre à jour QUE les paquets de sécurité (recommandé)
# Décommentez pour installer TOUTES les mises à jour (moins prudent) :
# "${distro_id}:${distro_codename}-updates";
};
# Redémarrer automatiquement si une mise à jour le nécessite ?
Unattended-Upgrade::Automatic-Reboot "true";
# Pourquoi ? Certaines mises à jour du noyau nécessitent un reboot
# Heure du redémarrage automatique
Unattended-Upgrade::Automatic-Reboot-Time "03:00";
# 3h du matin = heure creuse (peu de visiteurs)
# Changez selon votre fuseau horaire et trafic
# Notifications par email (nécessite un serveur mail configuré)
# Unattended-Upgrade::Mail "votre-email@example.com";
# Unattended-Upgrade::MailReport "on-change";
# Utile pour être notifié des mises à jour importantes
# Supprimer automatiquement les paquets inutilisés
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
# Libère de l'espace disque automatiquement
```
---
**4⃣ Tester la configuration**
```bash
# Simulation (ne fait rien, juste un test)
# Type A
unattended-upgrades --dry-run --debug
# Type B
sudo unattended-upgrades --dry-run --debug
# Affiche ce qui SERAIT mis à jour
# Vérifiez qu'il n'y a pas d'erreurs
```
**💡 Fréquence des vérifications :**
- Par défaut : vérifie chaque jour
- Installe automatiquement les mises à jour de sécurité
- Redémarre si nécessaire à 3h du matin
**⚠️ Important pour les sites critiques :**
Si vous avez un site haute disponibilité, configurez plutôt `Automatic-Reboot "false"` et faites les redémarrages manuellement pendant les maintenances planifiées.
---
## Installation d'un serveur web
### Étape 9 : Installer Apache
**Pourquoi Apache ?**
- **Robuste** : Utilisé depuis 1995, tourne sur 30% des sites web mondiaux
- **Mature** : Énormément de documentation et tutoriels
- **Compatible** : .htaccess, mod_rewrite, intégration PHP native
- **Flexible** : Modules pour tout (SSL, compression, cache, proxy)
**Alternative :** Nginx est plus performant pour du contenu statique et proxy inverse, mais Apache est plus simple pour débuter.
---
**1⃣ Installer Apache**
```bash
# Type A (root)
apt install apache2 -y
# Type B (sudo)
sudo apt install apache2 -y
```
**2⃣ Démarrer et activer Apache**
```bash
# Type A
systemctl start apache2 # Démarre Apache maintenant
systemctl enable apache2 # Active au démarrage du serveur
systemctl status apache2 # Vérifie que tout fonctionne
# Type B
sudo systemctl start apache2
sudo systemctl enable apache2
sudo systemctl status apache2
# Résultat attendu :
# ● apache2.service - The Apache HTTP Server
# Loaded: loaded
# Active: active (running)
```
---
**3⃣ Tester Apache**
**Depuis votre navigateur :**
- Allez sur `http://<adresse-IP-du-VPS>`
- Vous devriez voir la page "Apache2 Debian Default Page"
**✅ Ça fonctionne ?** Parfait, Apache écoute sur le port 80 !
**❌ Erreur de connexion ?** Vérifiez :
```bash
# Le pare-feu autorise-t-il le port 80 ?
sudo ufw status | grep 80
# Apache est-il bien démarré ?
sudo systemctl status apache2
# Apache écoute-t-il sur le port 80 ?
sudo netstat -tlnp | grep :80
```
---
### Étape 10 : Configurer un nom de domaine
**Pourquoi ?** Une adresse IP (`185.123.45.67`) c'est difficile à retenir et peu professionnel. Un nom de domaine (`monsite.com`) :
- Est mémorable pour vos visiteurs
- Permet d'obtenir un certificat SSL
- Donne une image professionnelle
- Facilite les migrations de serveur (changez l'IP sans changer l'URL)
**Prérequis :** Avoir acheté un nom de domaine chez un registrar (OVH, Infomaniak, Namecheap, Gandi, etc.)
---
**1⃣ Configurer les DNS chez votre registrar**
Connectez-vous à votre registrar et créez ces enregistrements DNS :
```
Type Nom Valeur TTL
A @ <adresse-IP-du-VPS> 3600
A www <adresse-IP-du-VPS> 3600
```
**Explications :**
- **Type A** : Associe un nom de domaine à une adresse IPv4
- **@** : Représente le domaine racine (example.com)
- **www** : Sous-domaine (www.example.com)
- **TTL** : Durée de cache (3600 = 1 heure)
**💡 Astuce :** Certains registrars proposent un enregistrement CNAME pour `www` qui pointe vers `@`. Ça fonctionne aussi !
---
**2⃣ Attendre la propagation DNS**
**Pourquoi attendre ?** Les DNS sont distribués mondialement. Votre modification doit :
- Se propager aux serveurs DNS racine
- Se propager aux serveurs DNS de votre FAI
- Se propager aux DNS publics (Google, Cloudflare, etc.)
**Durée :** 5 minutes à 24 heures (généralement 30 min)
**Vérifier la propagation depuis votre machine locale :**
```bash
# Vérifier que le domaine pointe vers votre VPS
nslookup example.com
# Résultat attendu :
# Address: <IP-de-votre-VPS>
# Alternative avec dig (plus détaillé)
dig example.com +short
# Doit afficher : <IP-de-votre-VPS>
# Vérifier www aussi
nslookup www.example.com
```
**✅ Ça affiche votre IP ?** Vous pouvez passer à l'étape suivante
**❌ Ça affiche une autre IP ou rien ?** Attendez encore un peu ou vérifiez votre configuration DNS
### Étape 11 : Configurer un site avec Apache
**Pourquoi un VirtualHost ?** Apache peut héberger plusieurs sites sur le même serveur. Chaque site a son propre VirtualHost (configuration séparée). C'est comme avoir plusieurs appartements dans un immeuble.
---
**1⃣ Créer le dossier du site**
```bash
# Type A (root)
mkdir -p /var/www/monsite
chown -R monuser:monuser /var/www/monsite
echo "<h1>Mon site fonctionne !</h1>" > /var/www/monsite/index.html
# Type B (sudo) - Remplacez "ubuntu" par votre utilisateur
sudo mkdir -p /var/www/monsite
sudo chown -R ubuntu:ubuntu /var/www/monsite
echo "<h1>Mon site fonctionne !</h1>" > /var/www/monsite/index.html
```
**Pourquoi chown ?** Par défaut, les fichiers créés par root appartiennent à root. `chown` change le propriétaire pour que VOTRE utilisateur puisse modifier les fichiers sans sudo.
---
**2⃣ Créer la configuration Apache (VirtualHost)**
```bash
# Type A
vim /etc/apache2/sites-available/monsite.conf
# Type B
sudo vim /etc/apache2/sites-available/monsite.conf
```
**Copiez-collez cette configuration :**
```apache
<VirtualHost *:80>
# Nom de domaine principal
ServerName example.com
# Alias (www.example.com pointe vers le même site)
ServerAlias www.example.com
# Dossier racine du site
DocumentRoot /var/www/monsite
# Configuration du dossier
<Directory /var/www/monsite>
# Options :
# -Indexes : NE PAS lister les fichiers si pas d'index.html (sécurité)
# +FollowSymLinks : Autoriser les liens symboliques
Options -Indexes +FollowSymLinks
# AllowOverride All : Permet l'utilisation de fichiers .htaccess
# (utile pour WordPress, Laravel, etc.)
AllowOverride All
# Require all granted : Autoriser l'accès public
Require all granted
</Directory>
# Fichiers de logs séparés par site (facilite le debug)
ErrorLog ${APACHE_LOG_DIR}/monsite-error.log
CustomLog ${APACHE_LOG_DIR}/monsite-access.log combined
</VirtualHost>
```
**Esc** puis **:wq** et **Entrée** pour sauvegarder et quitter.
---
**3⃣ Activer le site et les modules nécessaires**
```bash
# Activer le module rewrite (URL propres : /article/titre au lieu de /index.php?page=article&id=123)
# Type A
a2enmod rewrite
# Type B
sudo a2enmod rewrite
# Activer votre site
# Type A
a2ensite monsite.conf
# Type B
sudo a2ensite monsite.conf
# Désactiver le site par défaut d'Apache (page "Apache2 Debian Default Page")
# Type A
a2dissite 000-default.conf
# Type B
sudo a2dissite 000-default.conf
# Tester la configuration (vérifie les erreurs de syntaxe)
# Type A
apache2ctl configtest
# Type B
sudo apache2ctl configtest
# Résultat attendu : "Syntax OK"
# Recharger Apache pour appliquer les changements
# Type A
systemctl reload apache2
# Type B
sudo systemctl reload apache2
```
---
**4⃣ Tester votre site**
**Depuis votre navigateur :**
- Allez sur `http://example.com`
- Vous devriez voir "Mon site fonctionne !"
**✅ Ça fonctionne ?** Parfait, passez à l'étape suivante pour sécuriser avec HTTPS !
**❌ Erreur 404 ou 403 ?**
```bash
# Vérifier les droits du dossier
ls -la /var/www/monsite
# Vérifier les logs d'erreur
sudo tail -20 /var/log/apache2/monsite-error.log
# Vérifier que le VirtualHost est bien activé
ls -la /etc/apache2/sites-enabled/
```
### Étape 12 : Installer un certificat SSL (HTTPS)
**Pourquoi HTTPS est obligatoire en 2026 ?**
- **Sécurité** : Chiffre les données entre le visiteur et le serveur (mots de passe, infos personnelles)
- **SEO** : Google pénalise les sites en HTTP depuis 2014
- **Confiance** : Les navigateurs affichent "Non sécurisé" sur les sites HTTP
- **Standards** : La plupart des APIs modernes nécessitent HTTPS
- **Gratuit** : Let's Encrypt offre des certificats SSL gratuits à vie
**Sans HTTPS :** ❌ "Non sécurisé" - Visiteurs méfiants - Mauvais SEO
**Avec HTTPS :** ✅ 🔒 Cadenas vert - Confiance - Bon référencement
---
**1⃣ Installer Certbot**
```bash
# Type A
apt install certbot python3-certbot-apache -y
# Type B
sudo apt install certbot python3-certbot-apache -y
```
**Certbot** = outil officiel Let's Encrypt qui :
- Génère automatiquement le certificat SSL
- Configure Apache pour HTTPS
- Renouvelle automatiquement le certificat tous les 90 jours
---
**2⃣ Obtenir le certificat SSL**
```bash
# Type A
certbot --apache -d example.com -d www.example.com
# Type B
sudo certbot --apache -d example.com -d www.example.com
```
**Certbot vous pose des questions :**
1. **Enter email address** : Votre email (pour les alertes d'expiration)
```
votre-email@example.com
```
2. **Terms of Service** : Acceptez les conditions (A)
```
(A)gree/(C)ancel: A
```
3. **Share email with EFF** : Newsletter (optionnel)
```
(Y)es/(N)o: N
```
4. **Redirect HTTP to HTTPS ?** : TOUJOURS choisir Redirect
```
1: No redirect - Make no further changes
2: Redirect - Make all requests redirect to HTTPS
Select: 2
```
**Pourquoi "Redirect" ?**
- Force tous les visiteurs en HTTPS
- Améliore le SEO (évite le duplicate content)
- Meilleure sécurité
**Résultat attendu :**
```
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
```
---
**3⃣ Vérifier le renouvellement automatique**
**Pourquoi ?** Les certificats Let's Encrypt expirent après 90 jours. Certbot installe automatiquement une tâche qui les renouvelle.
```bash
# Test de renouvellement (simulation, ne fait rien)
# Type A
certbot renew --dry-run
# Type B
sudo certbot renew --dry-run
# Résultat attendu :
# Congratulations, all simulated renewals succeeded
# Vérifier que la tâche automatique est bien programmée
systemctl list-timers | grep certbot
# Résultat attendu :
# certbot.timer ... left ... certbot.service
```
**💡 Fonctionnement :** Certbot vérifie 2 fois par jour si le certificat expire dans moins de 30 jours, et le renouvelle automatiquement si nécessaire.
---
**4⃣ Tester HTTPS**
**Depuis votre navigateur :**
1. Allez sur `http://example.com`
→ Devrait automatiquement rediriger vers `https://example.com`
2. Vérifiez le cadenas 🔒 dans la barre d'adresse
→ Cliquez dessus : "Connection is secure"
3. Testez aussi `https://www.example.com`
→ Doit afficher le même site avec le cadenas
**Tester la qualité du certificat :**
- Allez sur [SSL Labs](https://www.ssllabs.com/ssltest/)
- Entrez votre domaine
- Attendez l'analyse (2-3 min)
- **Objectif :** Note A ou A+
**❌ Erreur "Your connection is not private" ?**
- Vérifiez que le DNS pointe bien vers votre VPS : `nslookup example.com`
- Attendez quelques minutes (Let's Encrypt vérifie le domaine)
- Vérifiez les logs : `sudo tail -50 /var/log/letsencrypt/letsencrypt.log`
---
**🎉 Félicitations !** Votre site est maintenant sécurisé en HTTPS avec un certificat SSL qui se renouvelle automatiquement !
---
## Déploiement
### Étape 13 : Déployer avec rsync
**rsync** = outil de synchronisation efficace (ne transfère que les modifications).
**Depuis votre machine locale :**
```bash
# Synchroniser un dossier local vers le VPS
rsync -avhP ./mon-site-local/ monuser@<adresse-IP>:/var/www/monsite/
# Options expliquées :
# -a : mode archive (préserve permissions, timestamps, etc.)
# -v : mode verbeux (affiche les fichiers transférés)
# -h : tailles lisibles (Ko, Mo, etc.)
# -P : affiche la progression + reprend les transferts interrompus
# Avec suppression des fichiers distants en trop
rsync -avhP --delete ./mon-site-local/ monuser@<adresse-IP>:/var/www/monsite/
```
**Script de déploiement automatique :**
```bash
# Créer un fichier deploy.sh
vim deploy.sh
```
```bash
#!/bin/bash
# Configuration
LOCAL_DIR="./dist/"
REMOTE_USER="monuser"
REMOTE_HOST="123.45.67.89"
REMOTE_DIR="/var/www/monsite/"
# Déploiement
echo "🚀 Déploiement en cours..."
rsync -avhP --delete \
--exclude 'node_modules' \
--exclude '.git' \
--exclude '.env' \
"$LOCAL_DIR" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR"
echo "✅ Déploiement terminé !"
# Recharger Apache (optionnel)
ssh "$REMOTE_USER@$REMOTE_HOST" "sudo systemctl reload apache2"
```
```bash
# Rendre le script exécutable
chmod +x deploy.sh
# Utiliser le script
./deploy.sh
```
### Étape 14 : Déployer avec Git
**Alternative à rsync :** déployer directement depuis un dépôt Git.
**Sur le VPS :**
```bash
# Installer Git
apt install git -y
# Aller dans le dossier du site
cd /var/www/monsite
# Cloner le dépôt
git clone https://github.com/votre-user/votre-repo.git .
# Ou initialiser Git
git init
git remote add origin https://github.com/votre-user/votre-repo.git
git pull origin main
```
**Script de déploiement :**
```bash
vim /home/monuser/deploy.sh
```
```bash
#!/bin/bash
cd /var/www/monsite
# Récupérer les dernières modifications
git pull origin main
# Si projet Node.js / SvelteKit
# npm install
# npm run build
# Recharger Apache
sudo systemctl reload apache2
echo "✅ Déploiement terminé !"
```
**Déployer depuis votre machine locale :**
```bash
ssh monuser@<adresse-IP> 'bash /home/monuser/deploy.sh'
```
---
## Maintenance
### Commandes utiles
**Surveiller l'espace disque :**
```bash
df -h # Vue globale
du -sh /var/www/* # Taille des sites
```
**Surveiller les logs Apache :**
```bash
tail -f /var/log/apache2/access.log # Logs d'accès en temps réel
tail -f /var/log/apache2/error.log # Logs d'erreur
```
**Surveiller les tentatives SSH :**
```bash
fail2ban-client status sshd # IPs bannies
journalctl -u sshd -n 50 # Dernières connexions SSH
```
**Mettre à jour le système :**
```bash
apt update && apt upgrade -y
apt autoremove -y
```
**Redémarrer les services :**
```bash
systemctl restart apache2
systemctl restart fail2ban
systemctl reboot # Redémarrer le serveur
```
### Tâches régulières
**Hebdomadaire :**
- Vérifier l'espace disque : `df -h`
- Vérifier les logs d'erreur : `tail -50 /var/log/apache2/error.log`
**Mensuel :**
- Vérifier les IPs bannies : `fail2ban-client status`
- Vérifier les mises à jour manuelles : `apt list --upgradable`
**Annuel :**
- Renouveler le certificat SSL (automatique avec Certbot)
- Auditer les règles du pare-feu : `ufw status verbose`
---
## Ressources
### Documentation officielle
- **OVH VPS :** [Débuter avec un VPS](https://docs.ovh.com/fr/vps/debuter-avec-vps/)
- **OVH Sécurité :** [Sécuriser un VPS](https://docs.ovh.com/fr/vps/conseils-securisation-vps/)
- **Apache :** [Documentation officielle](https://httpd.apache.org/docs/)
- **Let's Encrypt :** [Certbot](https://certbot.eff.org/)
- **UFW :** [Documentation Ubuntu](https://help.ubuntu.com/community/UFW)
- **Fail2ban :** [Documentation officielle](https://www.fail2ban.org/)
### Tutoriels vidéo
- **Grafikart :** [Playlist Serveur Web](https://www.youtube.com/playlist?list=PLjwdMgw5TTLUnvhOKLcpCG8ORQsfE7uB4)
- **Yves Rougy :** [Apprendre SSH](https://www.youtube.com/watch?v=QGixbJ9prEc&list=PLQqbP89HgbbYIarPqOU8DdC2jC3P3L7a6)
### Outils utiles
- **Explain Shell :** [https://explainshell.com/](https://explainshell.com/) - Décompose les commandes shell
- **SSL Labs :** [https://www.ssllabs.com/ssltest/](https://www.ssllabs.com/ssltest/) - Teste la config SSL
- **Security Headers :** [https://securityheaders.com/](https://securityheaders.com/) - Teste les en-têtes de sécurité
### Commandes de référence
**rsync :**
```bash
# Synchronisation de base
rsync -avhP source/ destination/
# Avec exclusions
rsync -avhP --exclude 'node_modules' source/ destination/
# Avec suppression
rsync -avhP --delete source/ destination/
# Mode dry-run (simulation)
rsync -avhPn source/ destination/
```
**SSH :**
```bash
# Connexion standard
ssh user@host
# Avec port personnalisé
ssh -p 2222 user@host
# Exécuter une commande à distance
ssh user@host 'commande'
# Copier un fichier (scp)
scp fichier.txt user@host:/path/
scp -r dossier/ user@host:/path/
```
**Git :**
```bash
# Cloner un dépôt
git clone https://github.com/user/repo.git
# Mettre à jour
git pull origin main
# Vérifier le statut
git status
```
---
## Checklist de sécurité
Avant de mettre votre VPS en production, vérifiez :
- [ ] Mot de passe root changé
- [ ] Utilisateur non-root créé avec sudo
- [ ] Authentification SSH par clé configurée
- [ ] Authentification SSH par mot de passe désactivée
- [ ] Connexion root SSH désactivée
- [ ] Pare-feu UFW activé et configuré
- [ ] Fail2ban installé et actif
- [ ] Mises à jour automatiques activées
- [ ] Apache installé et fonctionnel
- [ ] Certificat SSL installé (HTTPS)
- [ ] DNS configuré correctement
- [ ] Logs vérifiés (pas d'erreurs)
---
## Troubleshooting
### Impossible de se connecter en SSH
**Symptôme :** `Connection refused` ou `Connection timed out`
**Solutions :**
1. Vérifier que SSH écoute sur le bon port :
```bash
sudo netstat -tlnp | grep ssh
```
2. Vérifier le pare-feu :
```bash
sudo ufw status
```
3. Vérifier le service SSH :
```bash
sudo systemctl status sshd
```
### Apache ne démarre pas
**Symptôme :** `systemctl status apache2` montre une erreur
**Solutions :**
1. Tester la configuration :
```bash
sudo apache2ctl configtest
```
2. Lire les logs :
```bash
sudo journalctl -u apache2 -n 50
```
3. Vérifier qu'un autre service n'utilise pas le port 80/443 :
```bash
sudo netstat -tlnp | grep :80
sudo netstat -tlnp | grep :443
```
### Let's Encrypt échoue
**Symptôme :** `certbot` retourne une erreur
**Solutions :**
1. Vérifier que le DNS pointe vers le VPS :
```bash
nslookup example.com
```
2. Vérifier qu'Apache fonctionne et est accessible en HTTP :
```bash
curl http://example.com
```
3. Vérifier les logs Certbot :
```bash
sudo journalctl -u certbot -n 50
```
---
## Pour aller plus loin
Une fois votre VPS configuré, vous pouvez :
- **Installer Docker** pour conteneuriser vos applications
- **Configurer un reverse proxy** pour gérer plusieurs sites
- **Mettre en place une CI/CD** avec GitHub Actions
- **Installer une base de données** (PostgreSQL, MySQL)
- **Configurer un serveur mail** (Postfix, Dovecot)
- **Monitorer votre serveur** (Netdata, Prometheus + Grafana)
- **Optimiser Apache** (compression, cache, rate limiting)
- **Renforcer la sécurité** (AppArmor, SELinux, 2FA SSH)
Consultez les autres guides dans [linux-essentials/](linux-essentials/) pour la maintenance et le diagnostic !