Aller au contenu

TP – LAMP, SSH par clés et sauvegarde avec cron

BTS SIO SISR 1re année – Bloc 2 – S13

Note

But. Situation : Comment automatiser la création de 30 comptes, héberger un site web et administrer un serveur sans quitter son bureau ?

Comment ce TP fonctionne. Avant de manipuler, tu écris ce que tu anticipes (« J'anticipe »). Puis tu testes et tu notes ce que tu constates. Tu comprends ce que fait chaque commande (« Je comprends »). Un bilan de compétences clôt la séance. Les parties de services (Linux, Windows Server) se font sur des machines virtuelles réelles ; le simulateur réseau ou Packet Tracer servent aux manipulations d'équipements réseau.

Contexte

SimIO SARL vous confie la mise en place de son serveur applicatif interne. Ce TP est structuré en 4 parties progressives, chacune s'appuyant sur la précédente : - A : Installer et valider la pile LAMP - B : Exercices Bash sur les boucles - C : Configurer SSH par clés et sécuriser l'accès - D : Script de sauvegarde automatisée planifié avec cron


PARTIE A — Installation de la Pile LAMP

A1 — Mise à Jour du Système

sudo apt update && sudo apt upgrade -y

A2 — Installation d'Apache

# Installer Apache
sudo apt install apache2 -y

# Vérifier qu'Apache fonctionne
sudo systemctl status apache2

# S'assurer qu'il démarre au boot
sudo systemctl enable apache2

Test : Ouvrir un navigateur sur la VM cliente et taper l'adresse IP du serveur. La page par défaut Apache ("Apache2 Default Page") doit s'afficher.

Capturer cette page : Capture A1.


A3 — Installation de MariaDB

# Installer MariaDB
sudo apt install mariadb-server -y

# Démarrer et activer au boot
sudo systemctl enable --now mariadb

# Vérifier le statut
sudo systemctl status mariadb

Sécuriser l'installation MariaDB :

sudo mysql_secure_installation

Répondre aux questions comme suit :

Question Réponse recommandée
Set root password ? Yes — définir un mot de passe fort
Remove anonymous users ? Yes
Disallow root login remotely ? Yes
Remove test database ? Yes
Reload privilege tables ? Yes

Test : Se connecter à MariaDB

sudo mysql -u root -p
# Taper le mot de passe défini ci-dessus
# Résultat attendu : prompt "MariaDB [(none)]>"

Capturer le prompt MariaDB : Capture A2. Puis EXIT;

J'anticipe. Pourquoi lance-t-on mysql_secure_installation ? Cite deux choses qu'il corrige. ______________________

Éléments de réponse

Il durcit une installation par défaut : définition du mot de passe de root, suppression des utilisateurs anonymes, interdiction de la connexion de root à distance, suppression de la base de test.


A4 — Installation de PHP

# Installer PHP et le module Apache + connecteur MariaDB
sudo apt install php libapache2-mod-php php-mysql -y

# Vérifier la version installée
php -v

A5 — Créer une Page de Test PHP

# Créer le fichier de test (à supprimer après validation !)
sudo nano /var/www/html/test.php

Contenu du fichier :

<?php
echo "<h1>PHP fonctionne sur le serveur SimIO !</h1>";
echo "<p>Version PHP : " . phpversion() . "</p>";
echo "<p>Date et heure serveur : " . date('d/m/Y H:i:s') . "</p>";
phpinfo();
?>

Sauvegarder et tester depuis le navigateur : http://[IP_SERVEUR]/test.php

Capturer la page phpinfo : Capture A3.

# [ATTENTION] SUPPRIMER le fichier de test après validation (règle de sécurité)
sudo rm /var/www/html/test.php

A6 — Créer une Base de Données et un Utilisateur Dédié

sudo mysql -u root -p

Dans le prompt MariaDB :

-- Créer la base de données pour l'application
CREATE DATABASE siosarl_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- Créer un utilisateur dédié (ne jamais utiliser root pour l'application)
CREATE USER 'webuser'@'localhost' IDENTIFIED BY 'SioSarl!Web2024';

-- Accorder les droits nécessaires
GRANT ALL PRIVILEGES ON siosarl_db.* TO 'webuser'@'localhost';

-- Recharger les droits
FLUSH PRIVILEGES;

-- Vérifier
SHOW DATABASES;
SELECT user, host FROM mysql.user;

EXIT;

Capturer les résultats de SHOW DATABASES et SELECT user : Capture A4.


A7 — Créer une Page PHP de Connexion BDD

sudo nano /var/www/html/connexion_bdd.php
<?php
$serveur   = "localhost";
$login_bdd = "webuser";
$mdp_bdd   = "SioSarl!Web2024";
$base      = "siosarl_db";

try {
    $pdo = new PDO(
        "mysql:host=$serveur;dbname=$base;charset=utf8mb4",
        $login_bdd,
        $mdp_bdd
    );
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    echo "<h2 style='color:green'>Connexion à MariaDB réussie !</h2>";
    echo "<p>Base de données : <strong>$base</strong></p>";
    echo "<p>Serveur : <strong>$serveur</strong></p>";
} catch (PDOException $e) {
    echo "<h2 style='color:red'>Erreur de connexion</h2>";
    echo "<p>" . htmlspecialchars($e->getMessage()) . "</p>";
}
?>

Tester dans le navigateur : http://[IP_SERVEUR]/connexion_bdd.php

Capturer le message de succès : Capture A5.


PARTIE B — Exercices Bash : Boucles

B1 — Inventaire des Services LAMP

Créer /home/user/scripts/verif_lamp.sh :

#!/bin/bash
# ═══════════════════════════════════════════════════
# Script  : verif_lamp.sh
# Rôle    : Vérifier l'état des services de la pile LAMP
# ═══════════════════════════════════════════════════

echo "================================================="
echo "    VÉRIFICATION DE LA PILE LAMP — SimIO SARL"
echo "    $(date '+%d/%m/%Y à %H:%M:%S')"
echo "================================================="
echo ""

SERVICES=("apache2" "mariadb" "php8.2-fpm")
TOUS_OK=true

for SERVICE in "${SERVICES[@]}"
do
    # Vérifier si le paquet est installé
    if ! dpkg -l "$SERVICE" > /dev/null 2>&1
    then
        echo "  [N/A]  $SERVICE — Non installé"
        continue
    fi

    # Vérifier si le service est actif
    if systemctl is-active --quiet "$SERVICE"
    then
        echo "  [OK] $SERVICE est ACTIF"
    else
        echo "  [KO] $SERVICE est INACTIF !"
        TOUS_OK=false
    fi
done

echo ""
if [ "$TOUS_OK" = true ]
then
    echo "[OK] Pile LAMP opérationnelle."
else
    echo "[ATTENTION] Un ou plusieurs services LAMP sont inactifs. Vérifiez les logs !"
fi
chmod +x verif_lamp.sh
./verif_lamp.sh

B2 — Analyse de Fichier : Extraire les Utilisateurs Système

Créer /home/user/scripts/liste_users.sh :

#!/bin/bash
# ═══════════════════════════════════════════════════
# Script  : liste_users.sh
# Rôle    : Lister les utilisateurs avec shell valide
# ═══════════════════════════════════════════════════

echo "=== Utilisateurs avec un shell valide ==="
echo ""

COMPTEUR=0

while IFS=: read -r LOGIN MDPH ID_USER ID_GROUPE INFO REP_HOME SHELL_USER
do
    # Ne lister que les utilisateurs avec un shell interactif
    if [ "$SHELL_USER" = "/bin/bash" ] || [ "$SHELL_USER" = "/bin/sh" ]
    then
        COMPTEUR=$(( COMPTEUR + 1 ))
        echo "  $COMPTEUR. Login: $LOGIN | UID: $ID_USER | Home: $REP_HOME | Shell: $SHELL_USER"
    fi
done < /etc/passwd

echo ""
echo "Total : $COMPTEUR utilisateur(s) avec shell interactif."
chmod +x liste_users.sh
./liste_users.sh

PARTIE C — SSH par Clés Publique/Privée

Configuration : La VM cliente (poste depuis lequel vous vous connectez) et la VM serveur LAMP doivent être sur le même réseau virtuel. Notez l'IP de la VM serveur : _______________

C1 — Générer une Paire de Clés SSH sur la VM Cliente

Sur la VM cliente (pas le serveur LAMP) :

# Générer une paire de clés Ed25519 (algorithme moderne recommandé)
ssh-keygen -t ed25519 -C "admin@siosarl.local"

# À la question "Enter file in which to save the key" : appuyer sur Entrée (chemin par défaut)
# À la question "Enter passphrase" : laisser vide (pour le TP) ou saisir une passphrase

# Vérifier les clés générées
ls -la ~/.ssh/
# → id_ed25519 (privée, permissions 600) et id_ed25519.pub (publique)

# Afficher la clé publique
cat ~/.ssh/id_ed25519.pub

Capturer la sortie de ls -la ~/.ssh/ : Capture C1.


C2 — Copier la Clé Publique sur le Serveur

# Méthode automatique (recommandée)
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@[IP_SERVEUR]
# → Entrer le mot de passe habituel une dernière fois

# Vérifier que la clé a bien été ajoutée sur le serveur
ssh user@[IP_SERVEUR] "cat ~/.ssh/authorized_keys"

C3 — Tester la Connexion par Clé

# Se connecter sans mot de passe
ssh user@[IP_SERVEUR]
# → La connexion doit s'établir SANS demander de mot de passe

Capturer la connexion sans mot de passe : Capture C2.


C4 — Sécuriser le Serveur SSH

Sur la VM serveur :

# Sauvegarder la configuration avant modification
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

# Modifier la configuration
sudo nano /etc/ssh/sshd_config

Modifier/vérifier les lignes suivantes :

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
# Vérifier la syntaxe avant de redémarrer (évite de se bloquer dehors !)
sudo sshd -t

# Redémarrer SSH
sudo systemctl restart ssh

# Tester depuis la VM cliente que la connexion par clé fonctionne toujours
ssh user@[IP_SERVEUR]

Capturer le résultat de sudo sshd -t (doit être silencieux = OK) : Capture C3.

J'anticipe. Tu désactives l'authentification par mot de passe avant d'avoir testé la connexion par clé. Que risques-tu ? ______________________

Éléments de réponse

De te verrouiller dehors : plus aucun moyen de te connecter si la clé ne fonctionne pas. On teste la clé dans une seconde session, en gardant la première ouverte, avant de recharger SSH.


PARTIE D — Script de Sauvegarde Automatisée avec Cron

Contexte

SimIO SARL vous demande de mettre en place une sauvegarde nocturne automatique du site web (/var/www/html) et de la configuration Apache (/etc/apache2). Cette sauvegarde doit :

  • Être exécutée tous les jours à 2h00
  • Créer une archive compressée horodatée
  • Conserver les 7 dernières sauvegardes seulement
  • Journaliser chaque opération avec horodatage
  • Envoyer un compte-rendu lisible (succès ou échec de chaque étape)

D1 — Préparer l'Environnement

# Créer le répertoire de sauvegardes
sudo mkdir -p /var/backups/siosarl

# Créer le répertoire des scripts d'administration
sudo mkdir -p /usr/local/bin/siosarl

# Créer quelques fichiers de test dans le site web
echo "<h1>Page d'accueil SimIO</h1>" | sudo tee /var/www/html/index.html
echo "<?php echo 'App SimIO'; ?>" | sudo tee /var/www/html/app.php
sudo mkdir -p /var/www/html/assets

D2 — Écrire le Script de Sauvegarde

sudo nano /usr/local/bin/siosarl/sauvegarde.sh
#!/bin/bash
# ═══════════════════════════════════════════════════════════════════════
# Script  : sauvegarde.sh
# Auteur  : [Votre nom]
# Date    : [Date]
# Version : 1.0
# Rôle    : Sauvegarde automatique du serveur web SimIO SARL
#           - Sauvegarde /var/www/html et /etc/apache2
#           - Archives horodatées compressées en .tar.gz
#           - Conservation des 7 dernières sauvegardes (rotation)
#           - Journalisation complète dans /var/log/sauvegarde_siosarl.log
# Usage   : preuve pour une fiche de réalisation (E6) – B2.2, B2.3
# ═══════════════════════════════════════════════════════════════════════

# ─── VARIABLES DE CONFIGURATION ────────────────────────────────────────
REPERTOIRES_SOURCE=("/var/www/html" "/etc/apache2")
REPERTOIRE_BACKUP="/var/backups/siosarl"
FICHIER_LOG="/var/log/sauvegarde_siosarl.log"
NB_SAUVEGARDES_MAX=7
PREFIXE="backup_siosarl"
DATE=$(date "+%Y-%m-%d_%H-%M-%S")
NOM_ARCHIVE="${PREFIXE}_${DATE}.tar.gz"
CHEMIN_ARCHIVE="${REPERTOIRE_BACKUP}/${NOM_ARCHIVE}"
STATUT_GLOBAL=0   # 0 = succès, 1 = échec

# ─── FONCTIONS ──────────────────────────────────────────────────────────

# Fonction d'écriture dans le log
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$FICHIER_LOG"
}

# Fonction de vérification du code retour
verifier() {
    if [ $? -eq 0 ]
    then
        log "[OK] $1"
    else
        log "[ERREUR] $1 : échec"
        STATUT_GLOBAL=1
    fi
}

# ─── DÉBUT DU SCRIPT ─────────────────────────────────────────────────────
log "========================================================"
log " DÉBUT DE SAUVEGARDE — SimIO SARL"
log " Archive : $NOM_ARCHIVE"
log "========================================================"

# ─── VÉRIFICATION DU RÉPERTOIRE DE BACKUP ────────────────────────────────
if [ ! -d "$REPERTOIRE_BACKUP" ]
then
    log "Création du répertoire de backup : $REPERTOIRE_BACKUP"
    mkdir -p "$REPERTOIRE_BACKUP"
    verifier "Création répertoire backup"
fi

# ─── VÉRIFICATION DES SOURCES ────────────────────────────────────────────
log "Vérification des répertoires sources..."
for SOURCE in "${REPERTOIRES_SOURCE[@]}"
do
    if [ -d "$SOURCE" ]
    then
        TAILLE=$(du -sh "$SOURCE" | cut -f1)
        log "[OK] Source : $SOURCE ($TAILLE)"
    else
        log "[ATTENTION] Source absente ou vide : $SOURCE — Ignoré."
    fi
done

# ─── CRÉATION DE L'ARCHIVE ────────────────────────────────────────────────
log "Création de l'archive : $NOM_ARCHIVE"

tar -czf "$CHEMIN_ARCHIVE" \
    "${REPERTOIRES_SOURCE[@]}" \
    2>> "$FICHIER_LOG"

verifier "Création archive tar.gz"

# ─── VÉRIFICATION DE L'ARCHIVE CRÉÉE ─────────────────────────────────────
if [ -f "$CHEMIN_ARCHIVE" ]
then
    TAILLE_ARCHIVE=$(du -sh "$CHEMIN_ARCHIVE" | cut -f1)
    log "Archive créée avec succès : $CHEMIN_ARCHIVE ($TAILLE_ARCHIVE)"

    # Vérifier l'intégrité de l'archive
    tar -tzf "$CHEMIN_ARCHIVE" > /dev/null 2>&1
    verifier "Vérification intégrité de l'archive"
else
    log "[ERREUR] Critique : l'archive n'a pas été créée !"
    STATUT_GLOBAL=1
fi

# ─── ROTATION DES SAUVEGARDES ────────────────────────────────────────────
log "Rotation des sauvegardes (conservation des $NB_SAUVEGARDES_MAX dernières)..."

NB_ARCHIVES=$(ls -1 "${REPERTOIRE_BACKUP}/${PREFIXE}_"*.tar.gz 2>/dev/null | wc -l)
log "  Nombre d'archives présentes : $NB_ARCHIVES"

if [ "$NB_ARCHIVES" -gt "$NB_SAUVEGARDES_MAX" ]
then
    NB_A_SUPPRIMER=$(( NB_ARCHIVES - NB_SAUVEGARDES_MAX ))
    log "  Suppression des $NB_A_SUPPRIMER archive(s) les plus anciennes..."

    ls -1t "${REPERTOIRE_BACKUP}/${PREFIXE}_"*.tar.gz \
        | tail -n "$NB_A_SUPPRIMER" \
        | while read -r ANCIENNE_ARCHIVE
    do
        rm -f "$ANCIENNE_ARCHIVE"
        log "[INFO] Supprimé : $(basename $ANCIENNE_ARCHIVE)"
    done
else
    log "  Aucune rotation nécessaire."
fi

# ─── RAPPORT FINAL ────────────────────────────────────────────────────────
NB_ARCHIVES_FINAL=$(ls -1 "${REPERTOIRE_BACKUP}/${PREFIXE}_"*.tar.gz 2>/dev/null | wc -l)

log "========================================================"
if [ $STATUT_GLOBAL -eq 0 ]
then
    log "[OK] SAUVEGARDE TERMINÉE AVEC SUCCÈS"
else
    log "[ERREUR] SAUVEGARDE TERMINÉE AVEC DES ERREURS — Consultez le log"
fi
log " Archives conservées : $NB_ARCHIVES_FINAL / $NB_SAUVEGARDES_MAX maximum"
log " Espace backup utilisé : $(du -sh $REPERTOIRE_BACKUP | cut -f1)"
log "========================================================"
log ""

exit $STATUT_GLOBAL

D3 — Rendre le Script Exécutable et le Tester

# Rendre exécutable
sudo chmod +x /usr/local/bin/siosarl/sauvegarde.sh

# Tester manuellement (toujours tester avant de planifier !)
sudo /usr/local/bin/siosarl/sauvegarde.sh

# Vérifier le résultat
ls -lh /var/backups/siosarl/
cat /var/log/sauvegarde_siosarl.log

Capturer la liste des archives créées : Capture D1. Capturer le contenu du log : Capture D2.


D4 — Tester la Rotation

Simuler plusieurs sauvegardes pour tester la rotation :

# Relancer le script 3 fois de suite pour créer plusieurs archives
for i in $(seq 1 3)
do
    echo "=== Exécution $i ==="
    sudo /usr/local/bin/siosarl/sauvegarde.sh
    sleep 2   # Attendre 2 secondes pour avoir des horodatages différents
done

# Vérifier que la rotation fonctionne (au-delà de 7 archives)
ls -lh /var/backups/siosarl/

D5 — Planifier avec Cron

# Éditer le crontab de root
sudo crontab -e

Ajouter la ligne suivante :

# Sauvegarde quotidienne du serveur web SimIO SARL à 2h00
0 2 * * * /usr/local/bin/siosarl/sauvegarde.sh >> /var/log/sauvegarde_siosarl.log 2>&1
# Vérifier que la tâche est bien enregistrée
sudo crontab -l

Capturer la sortie de sudo crontab -l : Capture D3.

Je comprends. Que signifie 30 2 * * 1-5 ? Pourquoi un script lancé par cron doit-il utiliser des chemins absolus ? ______________________

Éléments de réponse

« à 2 h 30, du lundi au vendredi ». cron s'exécute avec un environnement minimal (pas ton répertoire courant ni ton PATH) : un chemin relatif ou une commande non trouvée fait échouer le script silencieusement.


D6 — Vérifier la Planification (Test Immédiat)

Pour vérifier que cron exécute bien le script, on peut temporairement modifier l'heure de planification pour qu'elle se déclenche dans 2 minutes :

# Connaître l'heure actuelle
date

# Modifier le crontab pour un test dans 2 minutes (exemple : si 10h15, mettre 10 17)
# 17 10 * * * /usr/local/bin/siosarl/sauvegarde.sh ...

# Après l'exécution, vérifier le log
cat /var/log/sauvegarde_siosarl.log

# Remettre la planification à 2h00
sudo crontab -e
# Corriger : 0 2 * * * ...

Capturer la dernière entrée du log après exécution automatique : Capture D4.



ANNEXE — FICHE DE DOCUMENTATION LAMP & SAUVEGARDE

(À compléter et verser au portfolio — Preuve pour la fiche de réalisation (E6))

Nom : _________________________ Prénom : _________________________ Date : _________


1. Configuration du Serveur LAMP

Informations Système

Paramètre Valeur
Distribution Linux
Version du noyau (uname -r)
Adresse IP du serveur
Nom d'hôte (hostname)

Composants LAMP Installés

Composant Version Port Statut Démarrage auto
Apache 80/443
MariaDB 3306
PHP N/A

Base de Données Créée

Paramètre Valeur
Nom de la base siosarl_db
Utilisateur applicatif webuser
Hôte autorisé localhost
Droits accordés ALL PRIVILEGES

2. Configuration SSH

Paramètre Valeur
Type de clé générée Ed25519
Emplacement clé privée ~/.ssh/id_ed25519
Emplacement clé publique ~/.ssh/id_ed25519.pub
Fichier authorized_keys serveur ~/.ssh/authorized_keys
PermitRootLogin no
PasswordAuthentication no

3. Configuration du Script de Sauvegarde

Paramètre Valeur configurée
Chemin du script /usr/local/bin/siosarl/sauvegarde.sh
Répertoires sauvegardés /var/www/html, /etc/apache2
Répertoire de destination /var/backups/siosarl
Fichier de log /var/log/sauvegarde_siosarl.log
Nombre de sauvegardes conservées 7
Format du nom d'archive backup_siosarl_YYYY-MM-DD_HH-MM-SS.tar.gz

4. Planification Cron

Paramètre Valeur
Expression cron 0 2 * * *
Signification Tous les jours à 2h00
Utilisateur root
Redirections >> /var/log/sauvegarde_siosarl.log 2>&1

Coller ici le résultat de sudo crontab -l :

(résultat de crontab -l)

5. Tests de Validation

Test Commande utilisée Résultat Capture N°
Apache actif systemctl status apache2 Oui / Non
Page web accessible Navigateur → IP serveur Oui / Non
PHP fonctionnel php -v Oui / Non
MariaDB actif systemctl status mariadb Oui / Non
Connexion BDD via PHP http://IP/connexion_bdd.php Oui / Non
SSH clé sans MDP ssh user@IP Oui / Non
Script sauvegarde manuel sudo ./sauvegarde.sh Oui / Non
Archive créée ls /var/backups/siosarl/ Oui / Non
Rotation (>7 archives) Exécution x8 + vérification Oui / Non
Planification cron sudo crontab -l Oui / Non