Je vais créer un guide pratique détaillé pour chacune de ces étapes !

```
# Fichier: python_cheats/cheatsheets/puppet_practical_guide.txt
# Guide Pratique Puppet - Étapes par Étapes pour Débutants


[OK] ÉTAPE 1: INSTALLER PUPPET SUR UNE VM DE TEST

# === PRÉREQUIS ===

# Tu auras besoin de:
# - Une VM Linux (Ubuntu 22.04 ou CentOS 8 recommandé)
# - Minimum 2GB RAM, 20GB disque
# - Accès root/sudo
# - Connexion internet

# === OPTION A: UTILISER VIRTUALBOX (GRATUIT) ===

# Étape 1.1: Télécharger VirtualBox
# Va sur: https://www.virtualbox.org/wiki/Downloads
# Télécharge et installe VirtualBox pour ton OS

# Étape 1.2: Télécharger Ubuntu Server
# Va sur: https://ubuntu.com/download/server
# Télécharge Ubuntu Server 22.04 LTS (fichier .iso)

# Étape 1.3: Créer la VM
# 1. Ouvre VirtualBox
# 2. Clique "Nouvelle"
# 3. Nom: puppet-test
# 4. Type: Linux
# 5. Version: Ubuntu (64-bit)
# 6. RAM: 2048 MB (2GB)
# 7. Disque: Créer un disque virtuel (20GB)
# 8. Clique "Créer"

# Étape 1.4: Installer Ubuntu
# 1. Sélectionne la VM "puppet-test"
# 2. Clique "Configuration" -> "Stockage"
# 3. Clique sur "Vide" sous "Contrôleur: IDE"
# 4. Clique l'icône CD -> "Choisir un fichier disque"
# 5. Sélectionne le fichier Ubuntu .iso
# 6. Clique "OK"
# 7. Démarre la VM
# 8. Suis l'installation d'Ubuntu:
#    - Langue: English (ou français)
#    - Clavier: French
#    - Network: DHCP (automatique)
#    - Nom: puppet-test
#    - Username: admin
#    - Password: ton-mot-de-passe
# 9. Attends la fin de l'installation (10-15 min)
# 10. Redémarre la VM


# === OPTION B: UTILISER VAGRANT (PLUS RAPIDE) ===

# Vagrant = Outil pour créer des VMs automatiquement

# Étape 1.1: Installer Vagrant
# macOS:
brew install vagrant

# Windows: Télécharge depuis https://www.vagrantup.com/downloads

# Linux (Ubuntu):
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install vagrant


# Étape 1.2: Créer un dossier pour Vagrant
mkdir ~/puppet-lab
cd ~/puppet-lab


# Étape 1.3: Créer le Vagrantfile
cat > Vagrantfile << 'EOF'
Vagrant.configure("2") do |config|
  # Image Ubuntu 22.04
  config.vm.box = "ubuntu/jammy64"
  
  # Configuration réseau
  config.vm.network "private_network", ip: "192.168.56.10"
  
  # Configuration matérielle
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "2048"
    vb.cpus = 2
    vb.name = "puppet-test"
  end
  
  # Nom de la VM
  config.vm.hostname = "puppet-test"
  
  # Provisioning initial
  config.vm.provision "shell", inline: <<-SHELL
    apt-get update
    apt-get install -y vim curl wget git
  SHELL
end
EOF


# Étape 1.4: Démarrer la VM
vagrant up

# Affiche:
# Bringing machine 'default' up with 'virtualbox' provider...
# ==> default: Importing base box 'ubuntu/jammy64'...
# ==> default: Forwarding ports...
# ==> default: Booting VM...
# ==> default: Running provisioner: shell...

# Attends 5-10 minutes (télécharge l'image)


# Étape 1.5: Se connecter à la VM
vagrant ssh

# Tu es maintenant dans la VM!
# L'invite change: vagrant@puppet-test:~$


# === ÉTAPE 1.6: INSTALLER PUPPET SUR LA VM ===

# ATTENTION: Tu es DANS la VM maintenant!

# Télécharger le dépôt Puppet:
wget https://apt.puppet.com/puppet7-release-jammy.deb

# Installer le dépôt:
sudo dpkg -i puppet7-release-jammy.deb

# Mettre à jour:
sudo apt update

# Installer Puppet Agent:
sudo apt install puppet-agent -y

# Ajouter Puppet au PATH:
echo 'export PATH=/opt/puppetlabs/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

# Vérifier l'installation:
puppet --version
# Affiche: 7.X.X

# BRAVO! Puppet est installé!


# === ÉTAPE 1.7: CONFIGURATION INITIALE ===

# Créer la structure des dossiers:
sudo mkdir -p /etc/puppetlabs/code/environments/production/{manifests,modules}
sudo mkdir -p /etc/puppetlabs/code/environments/production/modules

# Vérifier:
ls -la /etc/puppetlabs/code/environments/production/
# Affiche:
# drwxr-xr-x 2 root root 4096 ... manifests
# drwxr-xr-x 2 root root 4096 ... modules


# === ÉTAPE 1.8: TEST RAPIDE ===

# Créer un manifest de test:
sudo nano /etc/puppetlabs/code/environments/production/manifests/test.pp

# Contenu:
file { '/tmp/puppet-works.txt':
  ensure  => present,
  content => "Puppet fonctionne! Créé le $(date)\n",
}

notify { 'test-message':
  message => 'Hello from Puppet!',
}

# Sauvegarder: Ctrl+O, Enter, Ctrl+X

# Appliquer le manifest:
sudo puppet apply /etc/puppetlabs/code/environments/production/manifests/test.pp

# Affiche:
# Notice: Compiled catalog for puppet-test in environment production in 0.03 seconds
# Notice: /Stage[main]/Main/File[/tmp/puppet-works.txt]/ensure: created
# Notice: test-message: Hello from Puppet!
# Notice: Applied catalog in 0.01 seconds

# Vérifier le fichier créé:
cat /tmp/puppet-works.txt
# Affiche: Puppet fonctionne! Créé le ...

# [OK] ÉTAPE 1 TERMINÉE! Puppet fonctionne!


[OK] ÉTAPE 2: CRÉER TON PREMIER MODULE SIMPLE

# === QU'EST-CE QU'ON VA CRÉER? ===

# Un module "webserver" qui:
# 1. Installe Apache
# 2. Crée une page web personnalisée
# 3. Configure le firewall
# 4. S'assure que le service démarre

# === ÉTAPE 2.1: GÉNÉRER LA STRUCTURE DU MODULE ===

# Se placer dans le dossier modules:
cd /etc/puppetlabs/code/environments/production/modules

# Créer la structure manuellement:
sudo mkdir -p webserver/{manifests,files,templates,examples}

# Créer les fichiers nécessaires:
sudo touch webserver/manifests/{init.pp,install.pp,config.pp,service.pp}
sudo touch webserver/examples/init.pp

# Vérifier la structure:
tree webserver/
# Affiche:
# webserver/
# ├── examples
# │   └── init.pp
# ├── files
# ├── manifests
# │   ├── config.pp
# │   ├── init.pp
# │   ├── install.pp
# │   └── service.pp
# └── templates


# === ÉTAPE 2.2: CRÉER LA CLASSE PRINCIPALE (init.pp) ===

sudo nano webserver/manifests/init.pp

# Contenu:
# Class: webserver
#
# Cette classe installe et configure un serveur web Apache
#
# Parameters:
#   $port - Port d'écoute (défaut: 80)
#   $server_name - Nom du serveur (défaut: hostname)
#
# Examples:
#   include webserver
#
#   class { 'webserver':
#     port        => 8080,
#     server_name => 'myserver.local',
#   }
#
class webserver (
  Integer $port = 80,
  String $server_name = $facts['networking']['fqdn'],
  Boolean $enable_firewall = true,
) {
  
  # Inclure les sous-classes dans l'ordre
  contain webserver::install
  contain webserver::config
  contain webserver::service
  
  # Définir l'ordre d'exécution
  Class['webserver::install']
  -> Class['webserver::config']
  ~> Class['webserver::service']
  
  # Si le firewall est activé
  if $enable_firewall {
    # Ouvrir le port dans le firewall
    exec { 'allow-http-port':
      command => "/usr/sbin/ufw allow ${port}/tcp",
      unless  => "/usr/sbin/ufw status | /bin/grep ${port}/tcp",
      require => Class['webserver::install'],
    }
  }
}

# Sauvegarder: Ctrl+O, Enter, Ctrl+X


# === ÉTAPE 2.3: CRÉER LA SOUS-CLASSE INSTALL ===

sudo nano webserver/manifests/install.pp

# Contenu:
# Class: webserver::install
#
# Installe le package Apache
#
class webserver::install {
  
  # Déterminer le nom du package selon l'OS
  $package_name = $facts['os']['family'] ? {
    'Debian' => 'apache2',
    'RedHat' => 'httpd',
    default  => fail("OS ${facts['os']['family']} non supporté"),
  }
  
  # Installer Apache
  package { $package_name:
    ensure => installed,
  }
  
  # Installer UFW (firewall) sur Debian
  if $facts['os']['family'] == 'Debian' {
    package { 'ufw':
      ensure => installed,
    }
  }
  
  # Message de confirmation
  notify { 'webserver-package-installed':
    message => "Apache installé: ${package_name}",
  }
}

# Sauvegarder


# === ÉTAPE 2.4: CRÉER LA SOUS-CLASSE CONFIG ===

sudo nano webserver/manifests/config.pp

# Contenu:
# Class: webserver::config
#
# Configure Apache et crée la page web
#
class webserver::config {
  
  # Récupérer les paramètres de la classe principale
  $port = $webserver::port
  $server_name = $webserver::server_name
  
  # Déterminer les chemins selon l'OS
  case $facts['os']['family'] {
    'Debian': {
      $docroot = '/var/www/html'
      $config_dir = '/etc/apache2'
      $service_name = 'apache2'
    }
    'RedHat': {
      $docroot = '/var/www/html'
      $config_dir = '/etc/httpd'
      $service_name = 'httpd'
    }
    default: {
      fail("OS ${facts['os']['family']} non supporté")
    }
  }
  
  # S'assurer que le dossier web existe
  file { $docroot:
    ensure => directory,
    owner  => 'root',
    group  => 'root',
    mode   => '0755',
  }
  
  # Créer une page web personnalisée
  file { "${docroot}/index.html":
    ensure  => present,
    owner   => 'root',
    group   => 'root',
    mode    => '0644',
    content => epp('webserver/index.html.epp', {
      'server_name' => $server_name,
      'port'        => $port,
      'os_name'     => $facts['os']['name'],
      'os_version'  => $facts['os']['release']['full'],
      'ip_address'  => $facts['networking']['ip'],
    }),
  }
  
  # Message de confirmation
  notify { 'webserver-configured':
    message => "Serveur web configuré sur le port ${port}",
  }
}

# Sauvegarder


# === ÉTAPE 2.5: CRÉER LA SOUS-CLASSE SERVICE ===

sudo nano webserver/manifests/service.pp

# Contenu:
# Class: webserver::service
#
# Gère le service Apache (démarrage, redémarrage)
#
class webserver::service {
  
  # Nom du service selon l'OS
  $service_name = $facts['os']['family'] ? {
    'Debian' => 'apache2',
    'RedHat' => 'httpd',
    default  => fail("OS ${facts['os']['family']} non supporté"),
  }
  
  # Gérer le service
  service { $service_name:
    ensure     => running,
    enable     => true,
    hasstatus  => true,
    hasrestart => true,
  }
  
  # Message de confirmation
  notify { 'webserver-running':
    message => "Service ${service_name} démarré et activé",
  }
}

# Sauvegarder


# === ÉTAPE 2.6: CRÉER LE TEMPLATE ===

sudo nano webserver/templates/index.html.epp

# Contenu:
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Serveur Web Puppet</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 0;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }
        .container {
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(10px);
            border-radius: 20px;
            padding: 40px;
            box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
            border: 1px solid rgba(255, 255, 255, 0.18);
            max-width: 600px;
        }
        h1 {
            margin-top: 0;
            font-size: 2.5em;
            text-align: center;
        }
        .info {
            background: rgba(255, 255, 255, 0.2);
            border-radius: 10px;
            padding: 20px;
            margin: 20px 0;
        }
        .info-item {
            margin: 10px 0;
            font-size: 1.1em;
        }
        .label {
            font-weight: bold;
            color: #ffd700;
        }
        .puppet-logo {
            text-align: center;
            font-size: 4em;
            margin: 20px 0;
        }
        .footer {
            text-align: center;
            margin-top: 30px;
            font-size: 0.9em;
            opacity: 0.8;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="puppet-logo">[BOT]</div>
        <h1>Serveur Web Géré par Puppet</h1>
        
        <div class="info">
            <div class="info-item">
                <span class="label">Serveur:</span> <%= $server_name %>
            </div>
            <div class="info-item">
                <span class="label">Port:</span> <%= $port %>
            </div>
            <div class="info-item">
                <span class="label">Système:</span> <%= $os_name %> <%= $os_version %>
            </div>
            <div class="info-item">
                <span class="label">Adresse IP:</span> <%= $ip_address %>
            </div>
            <div class="info-item">
                <span class="label">Généré le:</span> <%= Time.now.strftime('%d/%m/%Y à %H:%M:%S') %>
            </div>
        </div>
        
        <div class="footer">
            * Ce serveur est configuré automatiquement par Puppet *
        </div>
    </div>
</body>
</html>

# Sauvegarder


# === ÉTAPE 2.7: CRÉER UN EXEMPLE D'UTILISATION ===

sudo nano webserver/examples/init.pp

# Contenu:
# Exemple d'utilisation du module webserver

# Utilisation basique (avec valeurs par défaut)
include webserver

# Ou avec des paramètres personnalisés
# class { 'webserver':
#   port             => 8080,
#   server_name      => 'monserveur.local',
#   enable_firewall  => true,
# }

# Sauvegarder


# === ÉTAPE 2.8: CRÉER UN README ===

sudo nano webserver/README.md

# Contenu:
# Module: webserver

## Description

Ce module installe et configure un serveur web Apache.

## Fonctionnalités

- Installation d'Apache
- Configuration du port d'écoute
- Création d'une page web personnalisée
- Configuration du firewall
- Gestion du service Apache

## Utilisation

### Exemple basique

```puppet
include webserver
```

### Exemple avec paramètres

```puppet
class { 'webserver':
  port            => 8080,
  server_name     => 'myserver.example.com',
  enable_firewall => true,
}
```

## Paramètres

- `port` (Integer): Port d'écoute (défaut: 80)
- `server_name` (String): Nom du serveur (défaut: hostname)
- `enable_firewall` (Boolean): Activer le firewall (défaut: true)

## Compatibilité

- Ubuntu 18.04+
- Debian 10+
- CentOS 7+
- RedHat 7+

## Auteur

Ton nom

# Sauvegarder


# === ÉTAPE 2.9: VALIDER LA SYNTAXE ===

# Valider tous les manifests:
sudo puppet parser validate webserver/manifests/*.pp

# Si aucune erreur n'apparaît, c'est bon!
# Si erreur, corrige-la


# === ÉTAPE 2.10: TESTER LE MODULE ===

# Créer un manifest de test:
sudo nano /tmp/test-webserver.pp

# Contenu:
include webserver

# Sauvegarder

# Tester en mode noop (dry-run):
sudo puppet apply --noop /tmp/test-webserver.pp

# Affiche ce qui serait changé sans l'appliquer
# Vérifie qu'il n'y a pas d'erreurs

# Appliquer pour de vrai:
sudo puppet apply /tmp/test-webserver.pp

# Affiche:
# Notice: Compiled catalog for puppet-test in environment production in 0.15 seconds
# Notice: /Stage[main]/Webserver::Install/Package[apache2]/ensure: created
# Notice: webserver-package-installed: Apache installé: apache2
# Notice: /Stage[main]/Webserver::Config/File[/var/www/html]/ensure: created
# Notice: /Stage[main]/Webserver::Config/File[/var/www/html/index.html]/ensure: created
# Notice: webserver-configured: Serveur web configuré sur le port 80
# Notice: /Stage[main]/Webserver::Service/Service[apache2]/ensure: ensure changed 'stopped' to 'running'
# Notice: webserver-running: Service apache2 démarré et activé
# Notice: Applied catalog in 12.45 seconds


# === ÉTAPE 2.11: VÉRIFIER QUE ÇA FONCTIONNE ===

# Vérifier qu'Apache est démarré:
sudo systemctl status apache2
# Doit afficher: active (running)

# Vérifier que le port 80 est ouvert:
sudo netstat -tlnp | grep :80
# Doit afficher: 0.0.0.0:80

# Tester la page web:
curl http://localhost

# Affiche le code HTML de la page

# Ou voir dans un navigateur:
# Si tu utilises Vagrant, ouvre un navigateur et va sur:
# http://192.168.56.10


# === ÉTAPE 2.12: TESTER AVEC DES PARAMÈTRES DIFFÉRENTS ===

# Créer un nouveau test:
sudo nano /tmp/test-webserver-custom.pp

# Contenu:
class { 'webserver':
  port            => 8080,
  server_name     => 'monserveur.local',
  enable_firewall => false,
}

# Appliquer:
sudo puppet apply /tmp/test-webserver-custom.pp

# Vérifier le nouveau port:
sudo netstat -tlnp | grep :8080

# Tester:
curl http://localhost:8080


# [OK] ÉTAPE 2 TERMINÉE! Tu as créé ton premier module Puppet!


[OK] ÉTAPE 3: EXPLORER LE PUPPET FORGE

# === QU'EST-CE QUE PUPPET FORGE? ===

# Puppet Forge = Bibliothèque de modules créés par la communauté
# URL: https://forge.puppet.com
# Des milliers de modules prêts à l'emploi!


# === ÉTAPE 3.1: EXPLORER LE SITE WEB ===

# Ouvre un navigateur et va sur: https://forge.puppet.com

# Tu verras:
# - Barre de recherche
# - Modules populaires
# - Modules récents
# - Catégories


# === ÉTAPE 3.2: CHERCHER DES MODULES ===

# Exemple 1: Chercher un module MySQL
# 1. Tape "mysql" dans la barre de recherche
# 2. Clique "Search"
# 3. Tu vois:
#    - puppetlabs-mysql (officiel, très populaire)
#    - example42-mysql
#    - ...

# Clique sur "puppetlabs-mysql"
# Tu vois:
# - Description complète
# - Documentation
# - Exemples d'utilisation
# - Compatibilité OS
# - Nombre de téléchargements
# - Score de qualité


# Exemple 2: Chercher un module Docker
# Tape "docker" -> puppetlabs-docker


# === ÉTAPE 3.3: COMPRENDRE LES BADGES ===

# Sur chaque module, tu vois des badges:

# [OK] Approved (Approuvé)
# = Module vérifié par Puppet Inc.
# = Haute qualité, bien maintenu

# * Supported (Supporté)
# = Support officiel de Puppet Inc.
# = Parfait pour la production

# [OK] Partner Supported
# = Supporté par un partenaire officiel

# Quality Score: X/5
# = Note de qualité (documentation, tests, etc.)


# === ÉTAPE 3.4: INSTALLER UN MODULE DEPUIS FORGE ===

# Retour dans la VM Puppet

# Exemple: Installer le module MySQL

sudo puppet module install puppetlabs-mysql

# Affiche:
# Notice: Preparing to install into /etc/puppetlabs/code/environments/production/modules ...
# Notice: Downloading from https://forgeapi.puppet.com ...
# Notice: Installing -- do not interrupt ...
# /etc/puppetlabs/code/environments/production/modules
# └─┬ puppetlabs-mysql (v13.0.0)
#   ├── puppetlabs-stdlib (v8.5.0)
#   └── puppetlabs-translate (v3.2.0)

# Le module et ses dépendances sont installés!


# === ÉTAPE 3.5: LIRE LA DOCUMENTATION D'UN MODULE ===

# Documentation en ligne:
# https://forge.puppet.com/modules/puppetlabs/mysql

# Documentation locale:
# cd /etc/puppetlabs/code/environments/production/modules/mysql
# cat README.md

# Exemples d'utilisation:
# cat examples/init.pp


# === ÉTAPE 3.6: UTILISER LE MODULE MYSQL ===

# Créer un manifest de test:
sudo nano /tmp/test-mysql.pp

# Contenu basique:
class { 'mysql::server':
  root_password    => 'super-secret-password',
  override_options => {
    'mysqld' => {
      'max_connections' => '150',
      'bind-address'    => '0.0.0.0',
    }
  },
}

# Créer une base de données:
mysql::db { 'myapp':
  user     => 'myapp_user',
  password => 'myapp_password',
  host     => 'localhost',
  grant    => ['SELECT', 'INSERT', 'UPDATE', 'DELETE'],
}

# Appliquer:
sudo puppet apply /tmp/test-mysql.pp

# Attends 2-3 minutes (installation de MySQL)

# Vérifier:
sudo systemctl status mysql
# Doit afficher: active (running)

# Tester la connexion:
mysql -u myapp_user -p'myapp_password' -e "SHOW DATABASES;"
# Doit afficher la base 'myapp'


# === ÉTAPE 3.7: EXPLORER D'AUTRES MODULES POPULAIRES ===

# Module Docker:
sudo puppet module install puppetlabs-docker

# Utilisation:
# include docker
#
# docker::image { 'nginx':
#   image_tag => 'latest',
# }
#
# docker::run { 'nginx-web':
#   image   => 'nginx:latest',
#   ports   => ['80:80'],
# }


# Module PostgreSQL:
sudo puppet module install puppetlabs-postgresql

# Utilisation:
# class { 'postgresql::server': }
#
# postgresql::server::db { 'mydb':
#   user     => 'myuser',
#   password => postgresql::postgresql_password('myuser', 'mypass'),
# }


# Module NTP (serveur de temps):
sudo puppet module install puppetlabs-ntp

# Utilisation:
# class { 'ntp':
#   servers => ['0.pool.ntp.org', '1.pool.ntp.org'],
# }


# Module Firewall:
sudo puppet module install puppetlabs-firewall

# Utilisation:
# firewall { '100 allow http':
#   dport  => 80,
#   proto  => 'tcp',
#   action => 'accept',
# }


# === ÉTAPE 3.8: LISTER TES MODULES INSTALLÉS ===

sudo puppet module list

# Affiche:
# /etc/puppetlabs/code/environments/production/modules
# ├── puppetlabs-docker (v4.4.0)
# ├── puppetlabs-mysql (v13.0.0)
# ├── puppetlabs-stdlib (v8.5.0)
# └── webserver (???)  <- Ton module personnalisé


# === ÉTAPE 3.9: METTRE À JOUR UN MODULE ===

# Voir si des mises à jour sont disponibles:
sudo puppet module list --tree

# Mettre à jour un module spécifique:
sudo puppet module upgrade puppetlabs-mysql

# Mettre à jour tous les modules:
# for mod in $(puppet module list | grep -oP '(?<=├── ).*(?= \()'); do
#   sudo puppet module upgrade $mod
# done


# === ÉTAPE 3.10: DÉSINSTALLER UN MODULE ===

sudo puppet module uninstall puppetlabs-docker

# Affiche:
# Notice: Preparing to uninstall 'puppetlabs-docker' ...
# Removed 'puppetlabs-docker' (v4.4.0) from /etc/puppetlabs/code/environments/production/modules


# [OK] ÉTAPE 3 TERMINÉE! Tu sais maintenant utiliser Puppet Forge!


[OK] ÉTAPE 4: METTRE EN PLACE UN PUPPET SERVER

# === ARCHITECTURE QU'ON VA CRÉER ===

# Puppet Server: puppet-server (192.168.56.10)
# Puppet Agent 1: puppet-agent1 (192.168.56.11)
# Puppet Agent 2: puppet-agent2 (192.168.56.12)


# === ÉTAPE 4.1: CRÉER LES VMS AVEC VAGRANT ===

# Sortir de la VM actuelle:
exit  # ou Ctrl+D

# Retour sur ton ordinateur
# Aller dans le dossier Vagrant:
cd ~/puppet-lab

# Supprimer la VM de test:
vagrant destroy -f

# Créer un nouveau Vagrantfile:
cat > Vagrantfile << 'EOF'
Vagrant.configure("2") do |config|
  
  # Configuration commune
  config.vm.box = "ubuntu/jammy64"
  
  # Puppet Server
  config.vm.define "server" do |server|
    server.vm.hostname = "puppet-server"
    server.vm.network "private_network", ip: "192.168.56.10"
    
    server.vm.provider "virtualbox" do |vb|
      vb.name = "puppet-server"
      vb.memory = "2048"
      vb.cpus = 2
    end
    
    server.vm.provision "shell", inline: <<-SHELL
      # Configurer /etc/hosts
      echo "192.168.56.10 puppet-server puppet" >> /etc/hosts
      echo "192.168.56.11 puppet-agent1" >> /etc/hosts
      echo "192.168.56.12 puppet-agent2" >> /etc/hosts
      
      # Installer des outils
      apt-get update
      apt-get install -y vim curl wget git
    SHELL
  end
  
  ## Puppet Agent 1
  config.vm.define "agent1" do |agent|
    agent.vm.hostname = "puppet-agent1"
    agent.vm.network "private_network", ip: "192.168.56.11"
    
    agent.vm.provider "virtualbox" do |vb|
      vb.name = "puppet-agent1"
      vb.memory = "1024"
      vb.cpus = 1
    end
    
    agent.vm.provision "shell", inline: <<-SHELL
      # Configurer /etc/hosts
      echo "192.168.56.10 puppet-server puppet" >> /etc/hosts
      echo "192.168.56.11 puppet-agent1" >> /etc/hosts
      echo "192.168.56.12 puppet-agent2" >> /etc/hosts
      
      # Installer des outils
      apt-get update
      apt-get install -y vim curl wget git
    SHELL
  end
  
  # Puppet Agent 2
  config.vm.define "agent2" do |agent|
    agent.vm.hostname = "puppet-agent2"
    agent.vm.network "private_network", ip: "192.168.56.12"
    
    agent.vm.provider "virtualbox" do |vb|
      vb.name = "puppet-agent2"
      vb.memory = "1024"
      vb.cpus = 1
    end
    
    agent.vm.provision "shell", inline: <<-SHELL
      # Configurer /etc/hosts
      echo "192.168.56.10 puppet-server puppet" >> /etc/hosts
      echo "192.168.56.11 puppet-agent1" >> /etc/hosts
      echo "192.168.56.12 puppet-agent2" >> /etc/hosts
      
      # Installer des outils
      apt-get update
      apt-get install -y vim curl wget git
    SHELL
  end
  
end
EOF

# Créer les 3 VMs:
vagrant up

# Attends 10-15 minutes (télécharge et crée 3 VMs)


# === ÉTAPE 4.2: INSTALLER PUPPET SERVER ===

# Se connecter au serveur:
vagrant ssh server

# Tu es maintenant dans puppet-server!

# Télécharger le dépôt Puppet:
wget https://apt.puppet.com/puppet7-release-jammy.deb
sudo dpkg -i puppet7-release-jammy.deb
sudo apt update

# Installer Puppet Server:
sudo apt install puppetserver -y

# Cela prend 5-10 minutes

# Configurer la mémoire Java (pour petites VMs):
sudo nano /etc/default/puppetserver

# Cherche la ligne:
JAVA_ARGS="-Xms2g -Xmx2g ..."

# Change en:
JAVA_ARGS="-Xms512m -Xmx512m -Djruby.logger.class=com.puppetlabs.jruby_utils.jruby.Slf4jLogger"

# Sauvegarder: Ctrl+O, Enter, Ctrl+X

# Configurer puppet.conf:
sudo nano /etc/puppetlabs/puppet/puppet.conf

# Ajouter à la fin:
[main]
certname = puppet-server
server = puppet-server
dns_alt_names = puppet,puppet-server

[master]
autosign = false
environment_timeout = unlimited

# Sauvegarder

# Démarrer Puppet Server:
sudo systemctl start puppetserver
sudo systemctl enable puppetserver

# Attends 2-3 minutes (première initialisation)

# Vérifier le statut:
sudo systemctl status puppetserver
# Doit afficher: active (running)

# Vérifier que le port 8140 est ouvert:
sudo netstat -tlnp | grep 8140
# Affiche: :::8140

# Ajouter Puppet au PATH:
echo 'export PATH=/opt/puppetlabs/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

# BRAVO! Puppet Server fonctionne!


# === ÉTAPE 4.3: CRÉER LA STRUCTURE DE CODE ===

# Créer les dossiers nécessaires:
sudo mkdir -p /etc/puppetlabs/code/environments/production/{manifests,modules,data}

# Créer le fichier site.pp principal:
sudo nano /etc/puppetlabs/code/environments/production/manifests/site.pp

# Contenu:
# site.pp - Configuration principale Puppet

# Configuration par défaut pour tous les nodes
node default {
  notify { 'default-node':
    message => "Node ${trusted['certname']} n'a pas de configuration spécifique",
  }
  
  # Packages communs à installer partout
  package { ['vim', 'curl', 'wget', 'git', 'htop']:
    ensure => installed,
  }
}

# Configuration pour agent1 (serveur web)
node 'puppet-agent1' {
  notify { 'agent1-config':
    message => 'Configuration pour puppet-agent1 (serveur web)',
  }
  
  # Installer Apache
  package { 'apache2':
    ensure => installed,
  }
  
  service { 'apache2':
    ensure  => running,
    enable  => true,
    require => Package['apache2'],
  }
  
  # Page web personnalisée
  file { '/var/www/html/index.html':
    ensure  => present,
    content => "<h1>Agent 1 - Serveur Web</h1><p>Géré par Puppet Server</p>",
    require => Package['apache2'],
  }
}

# Configuration pour agent2 (serveur de base de données)
node 'puppet-agent2' {
  notify { 'agent2-config':
    message => 'Configuration pour puppet-agent2 (base de données)',
  }
  
  # Installer MySQL
  package { 'mysql-server':
    ensure => installed,
  }
  
  service { 'mysql':
    ensure  => running,
    enable  => true,
    require => Package['mysql-server'],
  }
}

# Sauvegarder

# Valider la syntaxe:
sudo puppet parser validate /etc/puppetlabs/code/environments/production/manifests/site.pp
# Aucune erreur = c'est bon!


# === ÉTAPE 4.4: CONFIGURER HIERA (OPTIONNEL) ===

# Créer le fichier hiera.yaml:
sudo nano /etc/puppetlabs/code/environments/production/hiera.yaml

# Contenu:
---
version: 5

defaults:
  datadir: data
  data_hash: yaml_data

hierarchy:
  - name: "Per-node data"
    path: "nodes/%{trusted.certname}.yaml"
  
  - name: "Common data"
    path: "common.yaml"

# Sauvegarder

# Créer les données communes:
sudo nano /etc/puppetlabs/code/environments/production/data/common.yaml

# Contenu:
---
# Packages communs
common_packages:
  - vim
  - curl
  - wget
  - git
  - htop

# Configuration NTP
ntp_servers:
  - 0.pool.ntp.org
  - 1.pool.ntp.org

# Sauvegarder


# === ÉTAPE 4.5: INSTALLER PUPPET AGENT SUR AGENT1 ===

# Ouvre un NOUVEAU terminal (garde celui du server ouvert)

# Se connecter à agent1:
vagrant ssh agent1

# Tu es maintenant dans puppet-agent1!

# Installer le dépôt Puppet:
wget https://apt.puppet.com/puppet7-release-jammy.deb
sudo dpkg -i puppet7-release-jammy.deb
sudo apt update

# Installer Puppet Agent:
sudo apt install puppet-agent -y

# Configurer l'agent:
sudo nano /etc/puppetlabs/puppet/puppet.conf

# Contenu:
[main]
certname = puppet-agent1
server = puppet-server
environment = production
runinterval = 1800

[agent]
report = true

# Sauvegarder

# Ajouter Puppet au PATH:
echo 'export PATH=/opt/puppetlabs/bin:$PATH' >> ~/.bashrc
source ~/.bashrc


# === ÉTAPE 4.6: CONNECTER AGENT1 AU SERVER ===

# Sur agent1, demander un certificat:
sudo /opt/puppetlabs/bin/puppet agent --test

# Affiche:
# Info: Creating a new SSL key for puppet-agent1
# Info: csr_attributes file loading from /etc/puppetlabs/puppet/csr_attributes.yaml
# Info: Creating a new SSL certificate request for puppet-agent1
# Info: Certificate Request fingerprint (SHA256): AB:CD:EF:12:34...
# Exiting; no certificate found and waitforcert is disabled

# C'est normal! Le certificat doit être signé par le server


# === ÉTAPE 4.7: SIGNER LE CERTIFICAT SUR LE SERVER ===

# Retourne sur le terminal du server

# Lister les demandes de certificats en attente:
sudo /opt/puppetlabs/bin/puppetserver ca list

# Affiche:
# Requested Certificates:
#     puppet-agent1       (SHA256)  AB:CD:EF:12:34...

# Signer le certificat:
sudo /opt/puppetlabs/bin/puppetserver ca sign --certname puppet-agent1

# Affiche:
# Successfully signed certificate request for puppet-agent1

# BRAVO! Agent1 est maintenant autorisé!


# === ÉTAPE 4.8: APPLIQUER LA CONFIG SUR AGENT1 ===

# Retourne sur le terminal d'agent1

# Relancer l'agent:
sudo /opt/puppetlabs/bin/puppet agent --test

# Affiche BEAUCOUP de lignes:
# Info: Downloaded certificate for puppet-agent1 from https://puppet-server:8140/puppet-ca/v1
# Info: Using configured environment 'production'
# Info: Retrieving pluginfacts
# Info: Retrieving plugin
# Info: Loading facts
# Info: Caching catalog for puppet-agent1
# Info: Applying configuration version '1640000000'
# Notice: agent1-config: Configuration pour puppet-agent1 (serveur web)
# Notice: /Stage[main]/Main/Node[puppet-agent1]/Notify[agent1-config]/message: defined 'message' as 'Configuration pour puppet-agent1 (serveur web)'
# Notice: /Stage[main]/Main/Node[puppet-agent1]/Package[apache2]/ensure: created
# Notice: /Stage[main]/Main/Node[puppet-agent1]/Service[apache2]/ensure: ensure changed 'stopped' to 'running'
# Info: /Stage[main]/Main/Node[puppet-agent1]/Service[apache2]: Scheduling refresh of Service[apache2]
# Notice: /Stage[main]/Main/Node[puppet-agent1]/File[/var/www/html/index.html]/ensure: created
# Notice: Applied catalog in 25.43 seconds

# BRAVO! Apache est installé et configuré!


# === ÉTAPE 4.9: VÉRIFIER QUE ÇA FONCTIONNE ===

# Sur agent1, vérifier Apache:
sudo systemctl status apache2
# Doit afficher: active (running)

# Tester la page web:
curl http://localhost
# Affiche: <h1>Agent 1 - Serveur Web</h1><p>Géré par Puppet Server</p>

# Ou dans un navigateur sur ton ordinateur:
# http://192.168.56.11


# === ÉTAPE 4.10: DÉMARRER L'AGENT EN SERVICE ===

# Sur agent1, activer le service Puppet:
sudo systemctl start puppet
sudo systemctl enable puppet

# L'agent va maintenant se connecter automatiquement toutes les 30 minutes!

# Vérifier:
sudo systemctl status puppet
# Doit afficher: active (running)


# === ÉTAPE 4.11: CONFIGURER AGENT2 ===

# Ouvre un NOUVEAU terminal

# Se connecter à agent2:
vagrant ssh agent2

# Répéter les étapes 4.5 à 4.10 pour agent2:

# Installer le dépôt:
wget https://apt.puppet.com/puppet7-release-jammy.deb
sudo dpkg -i puppet7-release-jammy.deb
sudo apt update

# Installer Puppet Agent:
sudo apt install puppet-agent -y

# Configurer:
sudo nano /etc/puppetlabs/puppet/puppet.conf

[main]
certname = puppet-agent2
server = puppet-server
environment = production
runinterval = 1800

[agent]
report = true

# Ajouter au PATH:
echo 'export PATH=/opt/puppetlabs/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

# Demander un certificat:
sudo /opt/puppetlabs/bin/puppet agent --test

# Sur le SERVER (terminal du server):
sudo /opt/puppetlabs/bin/puppetserver ca list
sudo /opt/puppetlabs/bin/puppetserver ca sign --certname puppet-agent2

# Sur AGENT2, relancer:
sudo /opt/puppetlabs/bin/puppet agent --test

# MySQL sera installé!

# Activer le service:
sudo systemctl start puppet
sudo systemctl enable puppet

# Vérifier MySQL:
sudo systemctl status mysql
# Doit afficher: active (running)


# === ÉTAPE 4.12: VOIR LES RAPPORTS SUR LE SERVER ===

# Sur le server, voir les derniers runs:
sudo tail -f /var/log/puppetlabs/puppetserver/puppetserver.log

# Voir les certificats signés:
sudo /opt/puppetlabs/bin/puppetserver ca list --all

# Affiche:
# Signed Certificates:
#     puppet-agent1       (SHA256)  12:34:56...
#     puppet-agent2       (SHA256)  AB:CD:EF...
#     puppet-server       (SHA256)  98:76:54...


# === ÉTAPE 4.13: MODIFIER LA CONFIG ET REDÉPLOYER ===

# Sur le SERVER, modifier site.pp:
sudo nano /etc/puppetlabs/code/environments/production/manifests/site.pp

# Ajouter à la configuration d'agent1:
node 'puppet-agent1' {
  # ... (code existant)
  
  # NOUVEAU: Installer PHP
  package { ['php', 'libapache2-mod-php']:
    ensure => installed,
  }
  
  # NOUVEAU: Créer une page PHP
  file { '/var/www/html/info.php':
    ensure  => present,
    content => "<?php phpinfo(); ?>",
    require => Package['apache2'],
  }
}

# Sauvegarder

# Sur AGENT1, forcer un run immédiat:
sudo /opt/puppetlabs/bin/puppet agent --test

# PHP sera installé!

# Tester:
curl http://localhost/info.php
# Affiche le code HTML de phpinfo


# === ÉTAPE 4.14: TESTER L'AUTO-HEALING ===

# Sur agent1, arrêter Apache manuellement:
sudo systemctl stop apache2

# Vérifier:
sudo systemctl status apache2
# Doit afficher: inactive (dead)

# Attends 30 minutes (ou force un run):
sudo /opt/puppetlabs/bin/puppet agent --test

# Puppet redémarre Apache automatiquement!
# Affiche:
# Notice: /Stage[main]/Main/Node[puppet-agent1]/Service[apache2]/ensure: ensure changed 'stopped' to 'running'

# Vérifier:
sudo systemctl status apache2
# Doit afficher: active (running)

# C'est ça l'auto-healing! [BRAVO]


# === ÉTAPE 4.15: UTILISER DES MODULES DU FORGE ===

# Sur le SERVER, installer un module:
sudo puppet module install puppetlabs-ntp

# Modifier site.pp:
sudo nano /etc/puppetlabs/code/environments/production/manifests/site.pp

# Ajouter dans node default:
node default {
  # ... (code existant)
  
  # Configurer NTP
  class { 'ntp':
    servers => ['0.pool.ntp.org', '1.pool.ntp.org'],
  }
}

# Sur les agents, forcer un run:
sudo /opt/puppetlabs/bin/puppet agent --test

# NTP sera installé et configuré partout!


# [OK] ÉTAPE 4 TERMINÉE! Tu as un Puppet Server opérationnel!


[OK] ÉTAPE 5: AUTOMATISER LA GESTION DE TES SERVEURS

# === SCÉNARIO RÉALISTE ===

# Tu gères maintenant une infrastructure complète:
# - 2 serveurs web (load balancés)
# - 1 serveur de base de données
# - 1 serveur de monitoring

# On va automatiser TOUT avec Puppet!


# === ÉTAPE 5.1: CRÉER UN MODULE "BASELINE" ===

# Sur le SERVER:

# Créer la structure:
sudo mkdir -p /etc/puppetlabs/code/environments/production/modules/baseline/{manifests,files,templates}

# Module baseline = Configuration de base pour TOUS les serveurs


# === baseline/manifests/init.pp ===
sudo nano /etc/puppetlabs/code/environments/production/modules/baseline/manifests/init.pp

# Contenu:
# Class: baseline
#
# Configuration de base pour tous les serveurs
#
class baseline {
  include baseline::packages
  include baseline::users
  include baseline::ssh
  include baseline::timezone
  include baseline::motd
}


# === baseline/manifests/packages.pp ===
sudo nano /etc/puppetlabs/code/environments/production/modules/baseline/manifests/packages.pp

# Contenu:
class baseline::packages {
  # Packages essentiels
  $packages = [
    'vim',
    'curl',
    'wget',
    'git',
    'htop',
    'net-tools',
    'dnsutils',
    'unzip',
    'software-properties-common',
  ]
  
  package { $packages:
    ensure => installed,
  }
  
  # Désinstaller les packages inutiles
  package { ['telnet', 'rsh-client', 'rsh-redone-client']:
    ensure => absent,
  }
}


# === baseline/manifests/users.pp ===
sudo nano /etc/puppetlabs/code/environments/production/modules/baseline/manifests/users.pp

# Contenu:
class baseline::users {
  # Groupe administrateurs
  group { 'sysadmins':
    ensure => present,
    gid    => 3000,
  }
  
  # Utilisateur admin
  user { 'sysadmin':
    ensure     => present,
    uid        => 3000,
    gid        => 'sysadmins',
    shell      => '/bin/bash',
    home       => '/home/sysadmin',
    managehome => true,
    comment    => 'System Administrator',
    groups     => ['sudo'],
    require    => Group['sysadmins'],
  }
  
  # Clé SSH pour sysadmin
  file { '/home/sysadmin/.ssh':
    ensure  => directory,
    owner   => 'sysadmin',
    group   => 'sysadmins',
    mode    => '0700',
    require => User['sysadmin'],
  }
  
  file { '/home/sysadmin/.ssh/authorized_keys':
    ensure  => present,
    owner   => 'sysadmin',
    group   => 'sysadmins',
    mode    => '0600',
    content => "ssh-rsa AAAAB3... ta-cle-publique-ici\n",
    require => File['/home/sysadmin/.ssh'],
  }
}


# === baseline/manifests/ssh.pp ===
sudo nano /etc/puppetlabs/code/environments/production/modules/baseline/manifests/ssh.pp

# Contenu:
class baseline::ssh {
  # Configuration SSH sécurisée
  file { '/etc/ssh/sshd_config':
    ensure  => present,
    owner   => 'root',
    group   => 'root',
    mode    => '0600',
    content => template('baseline/sshd_config.erb'),
    notify  => Service['sshd'],
  }
  
  service { 'sshd':
    ensure => running,
    enable => true,
    name   => $facts['os']['family'] ? {
      'Debian' => 'ssh',
      'RedHat' => 'sshd',
    },
  }
}


# === baseline/templates/sshd_config.erb ===
sudo nano /etc/puppetlabs/code/environments/production/modules/baseline/templates/sshd_config.erb

# Contenu:
# SSH Configuration - Managed by Puppet
# DO NOT EDIT MANUALLY

Port 22
Protocol 2

# Security
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
ChallengeResponseAuthentication no

# Performance
UseDNS no
GSSAPIAuthentication no

# Logging
SyslogFacility AUTH
LogLevel INFO

# Allow only specific groups
AllowGroups sysadmins sudo

# Banner
Banner /etc/ssh/banner

# Subsystems
Subsystem sftp /usr/lib/openssh/sftp-server


# === baseline/manifests/timezone.pp ===
sudo nano /etc/puppetlabs/code/environments/production/modules/baseline/manifests/timezone.pp

# Contenu:
class baseline::timezone {
  # Configurer le timezone
  file { '/etc/timezone':
    ensure  => present,
    content => "Europe/Paris\n",
  }
  
  exec { 'set-timezone':
    command => '/usr/bin/timedatectl set-timezone Europe/Paris',
    unless  => '/usr/bin/timedatectl | /bin/grep "Europe/Paris"',
    require => File['/etc/timezone'],
  }
}


# === baseline/manifests/motd.pp ===
sudo nano /etc/puppetlabs/code/environments/production/modules/baseline/manifests/motd.pp

# Contenu:
class baseline::motd {
  # Message du jour personnalisé
  file { '/etc/motd':
    ensure  => present,
    content => template('baseline/motd.erb'),
  }
  
  # Banner SSH
  file { '/etc/ssh/banner':
    ensure  => present,
    content => template('baseline/banner.erb'),
  }
}


# === baseline/templates/motd.erb ===
sudo nano /etc/puppetlabs/code/environments/production/modules/baseline/templates/motd.erb

# Contenu:
╔══════════════════════════════════════════════════════════════════╗
║                    SYSTÈME GÉRÉ PAR PUPPET                       ║
╚══════════════════════════════════════════════════════════════════╝

Serveur    : <%= @fqdn %>
Adresse IP : <%= @ipaddress %>
Système    : <%= @os['name'] %> <%= @os['release']['full'] %>
Kernel     : <%= @kernelversion %>
Mémoire    : <%= @memory['system']['total'] %>
CPUs       : <%= @processors['count'] %> cores

[ATTENTION]  ATTENTION: Toute modification manuelle sera écrasée par Puppet!

Dernière mise à jour: <%= Time.now.strftime('%d/%m/%Y %H:%M:%S') %>


# === baseline/templates/banner.erb ===
sudo nano /etc/puppetlabs/code/environments/production/modules/baseline/templates/banner.erb

# Contenu:
╔══════════════════════════════════════════════════════════════════╗
║                     ACCÈS AUTORISÉ UNIQUEMENT                    ║
╚══════════════════════════════════════════════════════════════════╝

Ceci est un système privé. Toute utilisation non autorisée est interdite.
Les connexions sont enregistrées et surveillées.


# === ÉTAPE 5.2: CRÉER UN MODULE "WEBSERVER" COMPLET ===

# Structure:
sudo mkdir -p /etc/puppetlabs/code/environments/production/modules/webserver/{manifests,templates}


# === webserver/manifests/init.pp ===
sudo nano /etc/puppetlabs/code/environments/production/modules/webserver/manifests/init.pp

# Contenu:
class webserver (
  String $vhost_name = $facts['networking']['fqdn'],
  Integer $port = 80,
  String $docroot = '/var/www/html',
) {
  include webserver::install
  include webserver::config
  include webserver::service
  include webserver::firewall
  
  Class['webserver::install']
  -> Class['webserver::config']
  ~> Class['webserver::service']
  -> Class['webserver::firewall']
}


# === webserver/manifests/install.pp ===
sudo nano /etc/puppetlabs/code/environments/production/modules/webserver/manifests/install.pp

# Contenu:
class webserver::install {
  # Packages Apache + PHP
  $packages = [
    'apache2',
    'php',
    'libapache2-mod-php',
    'php-mysql',
    'php-curl',
    'php-gd',
    'php-mbstring',
    'php-xml',
    'php-zip',
  ]
  
  package { $packages:
    ensure => installed,
  }
  
  # Activer les modules Apache
  exec { 'enable-rewrite':
    command => '/usr/sbin/a2enmod rewrite',
    creates => '/etc/apache2/mods-enabled/rewrite.load',
    require => Package['apache2'],
  }
  
  exec { 'enable-headers':
    command => '/usr/sbin/a2enmod headers',
    creates => '/etc/apache2/mods-enabled/headers.load',
    require => Package['apache2'],
  }
}


# === webserver/manifests/config.pp ===
sudo nano /etc/puppetlabs/code/environments/production/modules/webserver/manifests/config.pp

# Contenu:
class webserver::config {
  $vhost_name = $webserver::vhost_name
  $port = $webserver::port
  $docroot = $webserver::docroot
  
  # S'assurer que le docroot existe
  file { $docroot:
    ensure => directory,
    owner  => 'www-data',
    group  => 'www-data',
    mode   => '0755',
  }
  
  # VirtualHost configuration
  file { '/etc/apache2/sites-available/app.conf':
    ensure  => present,
    content => template('webserver/vhost.conf.erb'),
    notify  => Service['apache2'],
  }
  
  # Désactiver le site par défaut
  exec { 'disable-default-site':
    command => '/usr/sbin/a2dissite 000-default.conf',
    onlyif  => '/usr/bin/test -L /etc/apache2/sites-enabled/000-default.conf',
    notify  => Service['apache2'],
  }
  
  # Activer notre site
  exec { 'enable-app-site':
    command => '/usr/sbin/a2ensite app.conf',
    creates => '/etc/apache2/sites-enabled/app.conf',
    require => File['/etc/apache2/sites-available/app.conf'],
    notify  => Service['apache2'],
  }
  
  # Page de statut serveur
  file { "${docroot}/status.php":
    ensure  => present,
    owner   => 'www-data',
    group   => 'www-data',
    mode    => '0644',
    content => template('webserver/status.php.erb'),
  }
}


# === webserver/templates/vhost.conf.erb ===
sudo nano /etc/puppetlabs/code/environments/production/modules/webserver/templates/vhost.conf.erb

# Contenu:
<VirtualHost *:<%= @port %>>
    ServerName <%= @vhost_name %>
    ServerAdmin admin@<%= @vhost_name %>
    DocumentRoot <%= @docroot %>
    
    <Directory <%= @docroot %>>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    # Logging
    ErrorLog ${APACHE_LOG_DIR}/app-error.log
    CustomLog ${APACHE_LOG_DIR}/app-access.log combined
    
    # Security headers
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-XSS-Protection "1; mode=block"
</VirtualHost>


# === webserver/templates/status.php.erb ===
sudo nano /etc/puppetlabs/code/environments/production/modules/webserver/templates/status.php.erb

# Contenu:
<?php
// Status page - Generated by Puppet

$status = [
    'server' => '<%= @vhost_name %>',
    'ip' => '<%= @ipaddress %>',
    'os' => '<%= @os['name'] %> <%= @os['release']['full'] %>',
    'timestamp' => date('Y-m-d H:i:s'),
    'php_version' => phpversion(),
    'apache_version' => apache_get_version(),
];

header('Content-Type: application/json');
echo json_encode($status, JSON_PRETTY_PRINT);
?>


# === webserver/manifests/service.pp ===
sudo nano /etc/puppetlabs/code/environments/production/modules/webserver/manifests/service.pp

# Contenu:
class webserver::service {
  service { 'apache2':
    ensure     => running,
    enable     => true,
    hasstatus  => true,
    hasrestart => true,
  }
}


# === webserver/manifests/firewall.pp ===
sudo nano /etc/puppetlabs/code/environments/production/modules/webserver/manifests/firewall.pp

# Contenu:
class webserver::firewall {
  $port = $webserver::port
  
  # Installer UFW
  package { 'ufw':
    ensure => installed,
  }
  
  # Autoriser SSH
  exec { 'ufw-allow-ssh':
    command => '/usr/sbin/ufw allow 22/tcp',
    unless  => '/usr/sbin/ufw status | /bin/grep "22/tcp"',
    require => Package['ufw'],
  }
  
  # Autoriser HTTP
  exec { 'ufw-allow-http':
    command => "/usr/sbin/ufw allow ${port}/tcp",
    unless  => "/usr/sbin/ufw status | /bin/grep '${port}/tcp'",
    require => Package['ufw'],
  }
  
  # Activer UFW
  exec { 'ufw-enable':
    command => '/usr/sbin/ufw --force enable',
    unless  => '/usr/sbin/ufw status | /bin/grep "Status: active"',
    require => [Exec['ufw-allow-ssh'], Exec['ufw-allow-http']],
  }
}


# ===ÉTAPE 5.3: METTRE À JOUR site.pp ===

sudo nano /etc/puppetlabs/code/environments/production/manifests/site.pp

# Contenu:
# site.pp - Configuration principale

# Configuration par défaut
node default {
  include baseline
}

# Serveurs web
node /^puppet-agent[12]$/ {
  include baseline
  include webserver
}


# === ÉTAPE 5.4: APPLIQUER SUR LES AGENTS ===

# Sur agent1 et agent2, forcer un run:
sudo /opt/puppetlabs/bin/puppet agent --test

# Attends 2-3 minutes

# Vérifier:
curl http://localhost/status.php
# Affiche du JSON avec les infos du serveur


# === ÉTAPE 5.5: CRÉER UN SYSTÈME DE MONITORING ===

# Installer un module de monitoring:
sudo puppet module install puppet-prometheus

# Configurer dans site.pp:
sudo nano /etc/puppetlabs/code/environments/production/manifests/site.pp

# Ajouter:
node 'puppet-server' {
  include baseline
  
  # Prometheus pour monitoring
  class { 'prometheus':
    version => '2.40.0',
  }
  
  # Node exporter sur tous les agents
  prometheus::scrape_job { 'node':
    targets => [
      'puppet-agent1:9100',
      'puppet-agent2:9100',
    ],
  }
}

# Sur les agents, installer node_exporter:
node /^puppet-agent[12]$/ {
  include baseline
  include webserver
  
  # Node exporter
  class { 'prometheus::node_exporter':
    version => '1.5.0',
  }
}


# [OK] ÉTAPE 5 TERMINÉE! Infrastructure complètement automatisée!


[OK] RÉCAPITULATIF FINAL

# TU AS MAINTENANT:

# [OK] Une VM de test avec Puppet
# [OK] Ton premier module Puppet (webserver)
# [OK] Connaissance de Puppet Forge
# [OK] Un Puppet Server avec 2 agents
# [OK] Une infrastructure automatisée complète

# PROCHAINES ÉTAPES AVANCÉES:

# 1. Intégrer avec Git/GitLab
# 2. Mettre en place des tests (rspec-puppet)
# 3. Utiliser Puppet Bolt pour des tâches ad-hoc
# 4. Déployer sur AWS/Azure/GCP
# 5. Intégrer avec CI/CD (Jenkins, GitLab CI)

# RESSOURCES:
# - Documentation: https://puppet.com/docs/
# - Forge: https://forge.puppet.com/
# - Community: https://puppet-community.slack.com/

# FÉLICITATIONS! [BRAVO][BRAVO][BRAVO]
# Tu es maintenant un Puppeteer! [BOT]
```