diff --git a/README.md b/README.md index 0437a67..da54011 100644 --- a/README.md +++ b/README.md @@ -2,49 +2,262 @@ ## Description -This repository contains Infrastructure as Code (IaC) configurations for a home lab environment. It includes Terraform scripts for provisioning infrastructure resources and Ansible playbooks for configuring those resources. +Ce repository contient l'Infrastructure as Code (IaC) pour un environnement de homelab. Il utilise Terraform pour provisionner des machines virtuelles sur Proxmox VE avec une configuration automatique via Cloud-Init et une intégration Tailscale. -## Usage +## Fonctionnalités -### Prerequisites +- 🚀 **Déploiement automatisé** : Création de VMs via Terraform +- 🔧 **Configuration automatique** : Initialisation via Cloud-Init +- 🌐 **Réseau sécurisé** : Connexion automatique à Tailscale +- 📦 **Templates multiples** : Support Ubuntu, Debian, Alpine, Rocky, CentOS +- 🏷️ **Organisation** : Système de tags pour classifier les VMs -- Terraform installed on your machine -- Ansible installed on your machine -- Proxmox VE installed on homelab +## Structure du projet -#### Proxmox Role and User +``` +iac-homelab/ +├── README.md +├── terraform/ +│ └── prod/ +│ ├── 01-virtual-machines.tf # Configuration des VMs +│ ├── 02-cloud-init.tf # Configuration Cloud-Init +│ ├── providers.tf # Providers Terraform +│ ├── variables.tf # Variables +│ ├── terraform.tfvars # Configuration personnalisée +│ └── terraform.tfvars.example # Exemple de configuration +└── cloud-init/ + └── user-data.yml.tftpl # Template Cloud-Init +``` -The Proxmox role is responsible for configuring Proxmox VE on the homelab. It includes tasks for setting up the Proxmox VE cluster, creating virtual machines, and configuring storage. +## Prérequis -Following the least privilege principle, the role creates a dedicated user account with limited permissions for managing the Proxmox VE cluster. +- **Terraform** : Version récente installée +- **Proxmox VE** : Serveur opérationnel avec API activée +- **Templates VM** : Templates configurés avec les tags appropriés +- **Tailscale** : Compte avec clé d'authentification +- **SSH** : Clés SSH configurées + +## Configuration initiale + +### 1. Proxmox VE + +Créer un utilisateur dédié avec les permissions nécessaires : ```bash +# Créer le rôle pveum role add TerraformProv -privs "Datastore.Allocate Datastore.AllocateSpace Datastore.Audit Pool.Allocate Sys.Audit Sys.Console Sys.Modify VM.Allocate VM.Audit VM.Clone VM.Config.CDROM VM.Config.Cloudinit VM.Config.CPU VM.Config.Disk VM.Config.HWType VM.Config.Memory VM.Config.Network VM.Config.Options VM.Console VM.Migrate VM.Monitor VM.PowerMgmt SDN.Use" -``` -Create a dedicated user account with limited permissions for managing the Proxmox VE cluster. - -```bash -pveum user add terraform@pve --password +# Créer l'utilisateur +pveum user add terraform@pve --password pveum acl modify / -user terraform@pve -role TerraformProv + +# Générer le token API +pveum user token add terraform@pve terraform -expire 0 -privsep 0 ``` -Generate API keys for the Proxmox VE cluster. +### 2. Templates VM + +Créer des templates sur Proxmox avec les tags suivants : + +| OS | Tags requis | +|---|---| +| Ubuntu | `["ubuntu", "template"]` | +| Debian | `["debian", "template"]` | +| Alpine | `["alpine", "template"]` | +| Rocky | `["rocky", "template"]` | +| CentOS | `["centos", "template"]` | + +## Déploiement + +### 1. Configuration ```bash -pveum user token add terraform@pve terraform -expire 0 -privsep 0 -comment "Terraform token" +# Cloner le repository +git clone +cd iac-homelab/terraform/prod + +# Copier le fichier d'exemple +cp terraform.tfvars.example terraform.tfvars + +# Éditer avec vos valeurs +vim terraform.tfvars ``` -### Provisioning Infrastructure +### 2. Variables importantes -1. Clone this repository to your local machine. -2. Navigate to the `terraform/prod` directory. -3. Run `terraform init` to initialize the Terraform environment. -4. Run `terraform plan` to preview the infrastructure changes. -5. Run `terraform apply` to apply the infrastructure changes. +Dans `terraform.tfvars`, configurer : -### Configuring Infrastructure +```hcl +# Proxmox +proxmox_url = "https://pve01.taila5ad8.ts.net:8006" +proxmox_api_token = "terraform@pve!terraform=" -1. Navigate to the `ansible` directory. -2. Run `ansible-playbook playbooks/setup_dns_server.yml` to set up the DNS server. - (Or `ansible-playbook playbooks/update_dns_records.yml` to update DNS records). +# Tailscale +tailscale_auth_key = "tskey-auth-" + +# SSH +admin_ssh_public_key_path = "~/.ssh/id_rsa.pub" + +# VMs +virtual_machines = { + "monitoring" = { + os = "debian" + cores = 2 + memory = 4096 + disk_gb = 30 + ip = "192.168.1.161" + gateway = "192.168.1.254" + tags = ["monitoring"] + } +} +``` + +### 3. Déploiement + +```bash +# Initialisation +terraform init + +# Vérification +terraform plan + +# Déploiement +terraform apply +``` + +## Configuration des VMs + +### Options de base + +```hcl +"nom-vm" = { + os = "debian" # Template à utiliser + cores = 2 # Nombre de cœurs CPU + memory = 4096 # RAM en MB + disk_gb = 30 # Taille du disque en GB + ip = "192.168.1.100" # Adresse IP statique + gateway = "192.168.1.254" # Passerelle réseau + tags = ["web"] # Tags pour l'organisation +} +``` + +### Options avancées + +```hcl +"nom-vm-avancee" = { + # Configuration de base + os = "ubuntu" + cores = 4 + memory = 8192 + disk_gb = 50 + ip = "192.168.1.101" + gateway = "192.168.1.254" + + # Options avancées + cpu_type = "host" + datastore = "local-lvm" + network_bridge = "vmbr0" + username = "admin" + + # Disques supplémentaires + additional_disks = [ + { + interface = "scsi1" + datastore = "local-lvm" + size = 100 + } + ] +} +``` + +## Fonctionnalités automatiques + +### Cloud-Init + +Chaque VM est automatiquement configurée avec : +- Installation des packages de base +- Configuration de l'utilisateur et des clés SSH +- Installation du QEMU Guest Agent +- Configuration du hostname + +### Tailscale + +Installation et connexion automatique : +- Téléchargement et installation de Tailscale +- Connexion au réseau avec la clé d'authentification +- Configuration du hostname sur le réseau + +## Maintenance + +### Ajouter une VM + +```bash +# 1. Ajouter la configuration dans terraform.tfvars +# 2. Appliquer les changements +terraform apply +``` + +### Supprimer une VM + +```bash +# 1. Retirer la configuration de terraform.tfvars +# 2. Appliquer les changements +terraform apply +``` + +### Modifier une VM + +```bash +# 1. Modifier la configuration dans terraform.tfvars +# 2. Vérifier les changements +terraform plan +# 3. Appliquer +terraform apply +``` + +## Sécurité + +- ✅ Authentification par tokens API +- ✅ Connexion SSH par clés uniquement +- ✅ Réseau sécurisé via Tailscale +- ✅ Isolation des VMs +- ✅ Permissions minimales sur Proxmox + +## Dépannage + +### Problèmes courants + +| Problème | Solution | +|---|---| +| Template non trouvé | Vérifier les tags sur Proxmox | +| IP déjà utilisée | Vérifier les conflits d'adresses | +| Erreur SSH | Vérifier le chemin de la clé publique | +| Tailscale | Vérifier la validité de la clé d'authentification | + +### Logs détaillés + +```bash +# Logs Terraform détaillés +TF_LOG=DEBUG terraform apply + +# État des ressources +terraform show + +# Liste des ressources +terraform state list +``` + +## Ressources recommandées + +| Type de service | CPU | RAM | Disque | +|---|---|---|---| +| Monitoring | 2 | 4GB | 30GB | +| Web server | 2 | 2GB | 20GB | +| Database | 4+ | 8GB+ | 50GB+ | +| Kubernetes | 4+ | 4GB+ | 40GB+ | + +## Support + +- 📚 [Documentation Terraform Proxmox Provider](https://registry.terraform.io/providers/bpg/proxmox/latest/docs) +- 🔧 [Proxmox VE Documentation](https://pve.proxmox.com/wiki/Main_Page) +- 🌐 [Tailscale Documentation](https://tailscale.com/kb/) \ No newline at end of file diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg deleted file mode 100644 index fa078b6..0000000 --- a/ansible/ansible.cfg +++ /dev/null @@ -1,38 +0,0 @@ -# ================================================================ -# Fichier de configuration principal pour Ansible -# -# Ces paramètres s'appliqueront par défaut lorsque vous lancerez -# des commandes Ansible depuis le dossier 'ansible/' ou sa racine. -# ================================================================ - -[defaults] - -# Chemin vers le dossier contenant vos fichiers d'inventaire. -# C'est la directive la plus importante ! Ansible lira automatiquement -# tous les fichiers valides dans ce dossier (statiques et dynamiques). -inventory = ./inventory/ - -# Chemin vers le dossier contenant vos rôles. -roles_path = ./roles/ - -# Désactive la vérification des clés d'hôte SSH. -# Très UTILE en lab où les VMs sont souvent recréées avec de nouvelles clés SSH. -# ATTENTION : C'est moins sécurisé. À ne pas utiliser dans un environnement -# de production non contrôlé. Pour notre lab, c'est acceptable. -host_key_checking = False - -# N'affiche pas les tâches qui sont sautées (skipped) dans la console. -# Cela rend la sortie de la commande un peu plus propre et lisible. -display_skipped_hosts = False - -# Force l'utilisation de couleurs dans la sortie de la console pour une meilleure lisibilité. -force_color = 1 - - -[privilege_escalation] - -# Ne jamais demander le mot de passe pour l'escalade de privilèges (sudo). -# Cela suppose que vous avez configuré un accès sudo sans mot de passe -# pour votre utilisateur Ansible (une pratique courante pour l'automatisation). -# Si ce n'est pas le cas, Ansible resterait bloqué à attendre un mot de passe. -become_ask_pass = False diff --git a/ansible/inventory/00_static_hosts.yml.example b/ansible/inventory/00_static_hosts.yml.example deleted file mode 100644 index ef62209..0000000 --- a/ansible/inventory/00_static_hosts.yml.example +++ /dev/null @@ -1,43 +0,0 @@ -# ================================================================ -# Static inventory for the core Homelab infrastructure -# These machines are configured manually and are not -# destroyed/recreated by Terraform. -# ================================================================ - -all: - children: - # ------------------------------------------- - # Group for our DNS servers - # ------------------------------------------- - dns_servers: - hosts: - dns.example.com: - ansible_host: 192.168.1.10 - ansible_user: admin - - # ------------------------------------------- - # Group for our Proxmox hypervisors - # ------------------------------------------- - proxmox_hosts: - hosts: - pve01.example.com: - ansible_host: 192.168.1.20 - ansible_user: root - - # ------------------------------------------- - # Group for Lab machines (for lab DNS) - # ------------------------------------------- - lab: - hosts: - pve01.example.com: {} - - # ================================================================ - # Best practice: add a variable for the Python interpreter - # to avoid ambiguities between python2 and python3. - # ================================================================ - homelab_core: - children: - dns_servers: - proxmox_hosts: - vars: - ansible_python_interpreter: /usr/bin/python3 diff --git a/ansible/inventory/group_vars/all/static_records.yml.example b/ansible/inventory/group_vars/all/static_records.yml.example deleted file mode 100644 index 91c5083..0000000 --- a/ansible/inventory/group_vars/all/static_records.yml.example +++ /dev/null @@ -1,130 +0,0 @@ ---- -# ================================================================= -# Fichier d'exemple pour les enregistrements DNS statiques -# -# Copiez ce fichier vers `ansible/inventory/group_vars/all/static_records.yml` -# ou un fichier similaire (ex: `ansible/inventory/group_vars/VOTRE_GROUPE/dns_records.yml`) -# et adaptez les valeurs à votre environnement. -# -# Ce fichier est destiné à définir les enregistrements DNS pour les machines -# ou services ayant des adresses IP fixes, en particulier ceux qui ne -# sont pas gérés par des systèmes de provisioning dynamiques comme Terraform. -# -# La structure ci-dessous est un exemple. Vous devrez l'adapter -# à la manière dont vos playbooks Ansible attendent ces données -# (par exemple, pour configurer Dnsmasq, BIND, ou un service DNS cloud). -# ================================================================= - -# Exemple de structure pour les enregistrements DNS d'un domaine spécifique (ex: yourdomain.local) -# Remplacez "yourdomain_local_records" par une clé plus descriptive si nécessaire, -# par exemple "dns_records_lan" ou "dns_records_dmz". -# La structure de chaque enregistrement (ip, names) est un exemple. -# Vos playbooks peuvent attendre une structure différente. - -# dns_records_yourdomain_local: -# # --- Infrastructure et serveurs critiques --- -# - ip: "192.168.1.1" -# names: -# - "router.yourdomain.local" -# - "gateway.yourdomain.local" -# - "firewall.yourdomain.local" -# # Vous pourriez ajouter d'autres attributs, ex: type: "A", ttl: 3600 -# -# - ip: "192.168.1.10" -# names: -# - "dns-primary.yourdomain.local" # Nom FQDN du serveur DNS lui-même -# - "dns1.yourdomain.local" -# - "ns1.yourdomain.local" -# -# - ip: "192.168.1.11" # Un serveur DNS secondaire, par exemple -# names: -# - "dns-secondary.yourdomain.local" -# - "dns2.yourdomain.local" -# - "ns2.yourdomain.local" -# -# - ip: "192.168.1.20" -# names: -# - "hypervisor01.yourdomain.local" -# - "pve01.yourdomain.local" # Si c'est un Proxmox -# -# - ip: "192.168.1.50" -# names: -# - "nas.yourdomain.local" -# - "storage.yourdomain.local" -# -# # --- Périphériques réseau (imprimantes, caméras, etc.) --- -# - ip: "192.168.1.100" -# names: -# - "printer-color.yourdomain.local" -# - "printer01.yourdomain.local" -# -# - ip: "192.168.1.101" -# names: -# - "camera-garage.yourdomain.local" -# -# # --- Services hébergés --- -# - ip: "192.168.1.150" # Peut-être une VM ou un conteneur -# names: -# - "webserver.yourdomain.local" -# - "wiki.yourdomain.local" # Si le même serveur héberge plusieurs services -# -# # --- Enregistrements CNAME (Alias) --- -# # La structure pour les CNAMEs peut varier. Voici un exemple : -# # - name: "www.yourdomain.local" -# # cname_target: "webserver.yourdomain.local" -# # type: "CNAME" -# -# # --- Enregistrements MX (Mail Exchange) --- -# # Si vous hébergez votre propre serveur de messagerie : -# # - name: "yourdomain.local" # Le domaine pour lequel le MX est défini -# # mail_server: "mail.yourdomain.local" # FQDN du serveur de messagerie -# # priority: 10 # Priorité MX (valeur plus basse = plus prioritaire) -# # type: "MX" -# # -# # - ip: "192.168.1.60" # IP du serveur de messagerie -# # names: -# # - "mail.yourdomain.local" - -# Vous pouvez avoir des listes séparées pour différents domaines ou zones -# si votre configuration DNS le requiert. -# Par exemple, pour un domaine "lab.yourdomain.local": -# dns_records_lab_yourdomain_local: -# - ip: "10.0.0.10" -# names: -# - "kube-master.lab.yourdomain.local" -# - ip: "10.0.0.100" -# names: -# - "gitlab.lab.yourdomain.local" - -# IMPORTANT: -# La variable `dns_records_home` et `dns_records_lab` utilisée dans votre fichier original -# `static_records.yml` est une façon valide de structurer ces données. -# L'exemple ci-dessus est plus générique. Si vos playbooks sont déjà -# conçus pour utiliser `dns_records_home` et `dns_records_lab`, -# vous devriez structurer votre fichier `.example` pour correspondre à cela. -# -# Exemple reprenant votre structure originale : - -dns_records_home: # Pour le domaine "home.votredomaine.fr" - - ip: "192.168.1.1" # Exemple: Votre routeur/passerelle - names: - - "router.home.votredomaine.fr" - - "gateway" - - ip: "192.168.1.10" # Exemple: Votre serveur DNS principal pour ce domaine - names: - - "dns.home.votredomaine.fr" - - "dns" - - ip: "192.168.1.20" # Exemple: Un NAS - names: - - "nas.home.votredomaine.fr" - - "nas" - -dns_records_lab: # Pour un autre domaine, par exemple "lab.votredomaine.fr" - - ip: "192.168.100.10" # Exemple: Un hyperviseur dans le lab - names: - - "pve.lab.votredomaine.fr" - - "pve" - - ip: "192.168.100.20" # Exemple: Un serveur de build - names: - - "jenkins.lab.votredomaine.fr" - - "jenkins" \ No newline at end of file diff --git a/ansible/inventory/host_vars/dns-server.example.yml.example b/ansible/inventory/host_vars/dns-server.example.yml.example deleted file mode 100644 index babc2a5..0000000 --- a/ansible/inventory/host_vars/dns-server.example.yml.example +++ /dev/null @@ -1,79 +0,0 @@ ---- -# =============================================================== -# Fichier d'exemple pour les variables d'hôte d'un serveur DNS -# -# Copiez ce fichier vers `ansible/inventory/host_vars/VOTRE_SERVEUR_DNS.yml` -# (par exemple, `dns-primary.yourdomain.local.yml`) et adaptez les valeurs. -# -# Ces variables sont typiquement utilisées pour configurer un service -# comme Dnsmasq ou BIND sur un hôte spécifique. -# =============================================================== - -# Le nom de domaine principal que ce serveur DNS va gérer localement. -# Remplacez "yourdomain.local" par votre propre nom de domaine. -dnsmasq_domain_name: "yourdomain.local" - -# Taille du cache DNS pour dnsmasq. -# Une valeur plus élevée (ex: 1000) peut améliorer les performances sur -# les réseaux avec de nombreux appareils ou des requêtes répétées. -dnsmasq_cache_size: 500 - -# Liste des serveurs DNS en amont (upstream). -# Ce sont les serveurs auxquels votre DNS local transmettra les requêtes -# pour les domaines qu'il ne gère pas lui-même (par exemple, google.com). -# Remplacez ces adresses par celles de vos fournisseurs DNS préférés (ex: Cloudflare, Google, Quad9, ou votre FAI). -# Il est recommandé d'en utiliser au moins deux pour la redondance. -dnsmasq_upstream_servers: - - "1.1.1.1" # Exemple: Cloudflare - - "8.8.8.8" # Exemple: Google - # - "9.9.9.9" # Exemple: Quad9 - -# Adresses IP sur lesquelles le service Dnsmasq doit écouter. -# "127.0.0.1" est pour les requêtes locales sur le serveur lui-même. -# "{{ ansible_default_ipv4.address }}" est une variable "fact" d'Ansible qui -# est automatiquement remplacée par l'adresse IPv4 principale de l'hôte. -# Cela rend la configuration portable si l'IP de votre serveur DNS change. -dnsmasq_listen_addresses: - - "127.0.0.1" - - "{{ ansible_default_ipv4.address }}" # Assurez-vous que l'hôte a bien une adresse IPv4 par défaut. - # Si vous avez plusieurs interfaces réseau et souhaitez écouter sur une IP spécifique, - # vous pouvez la mettre en dur ici, par exemple : - # - "192.168.1.10" - -# ---------------------------------------------------------------- -# Section DHCP - Optionnelle -# -# Décommentez et configurez cette section si vous souhaitez que -# ce serveur DNS agisse également comme serveur DHCP pour votre réseau. -# Assurez-vous qu'aucun autre serveur DHCP (comme celui de votre routeur) -# n'est actif sur le même segment réseau pour éviter les conflits. -# ---------------------------------------------------------------- -dnsmasq_dhcp_enabled: false - -# Exemple de configuration DHCP (si dnsmasq_dhcp_enabled est true): -# -# # Plage d'adresses IP à distribuer par le DHCP, et durée du bail. -# # Format: "IP_DEBUT,IP_FIN,DUREE_BAIL" (ex: "192.168.1.100,192.168.1.199,12h") -# dnsmasq_dhcp_range: "192.168.1.150,192.168.1.250,24h" -# -# # Adresse IP de la passerelle (routeur) à fournir aux clients DHCP. -# dnsmasq_dhcp_router: "192.168.1.1" -# -# # Options DHCP supplémentaires (exemple : serveur NTP) -# # dnsmasq_dhcp_options: -# # - "option:ntp-server,192.168.1.10" # Si votre serveur DNS est aussi serveur NTP - -# Autres variables spécifiques à votre configuration DNS pourraient être ajoutées ici. -# Par exemple, pour activer ou désactiver des fonctionnalités de dnsmasq: -# dnsmasq_no_hosts: false # Si true, dnsmasq n'utilisera pas /etc/hosts -# dnsmasq_expand_hosts: true # Si true, ajoute le domaine aux noms simples dans /etc/hosts - -# Si vous utilisez des listes de blocage (blocklists) pour le filtrage DNS: -# dnsmasq_blocklist_urls: -# - "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" -# - "https://mirror1.malwaredomains.com/files/justdomains" - -# Active la journalisation des requêtes DNS (utile pour le débogage) -# dnsmasq_log_queries: false -# dnsmasq_log_dhcp: false # Active la journalisation des événements DHCP -# diff --git a/ansible/playbooks/setup_dns_server.yml b/ansible/playbooks/setup_dns_server.yml deleted file mode 100644 index bb210b5..0000000 --- a/ansible/playbooks/setup_dns_server.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- -# ================================================================ -# Playbook d'Installation Initiale du Serveur DNS -# -# À lancer une seule fois pour provisionner un nouveau serveur. -# Il installe Dnsmasq et déploie la configuration complète. -# USAGE : ansible-playbook -i inventory/ playbooks/setup_dns_server.yml -# ================================================================ - -- name: "Provisionner et configurer le serveur DNS" - hosts: dns_servers - become: true - roles: - - role: dns_server - - role: grafana_alloy diff --git a/ansible/playbooks/update_dns_records.yml b/ansible/playbooks/update_dns_records.yml deleted file mode 100644 index e377cb7..0000000 --- a/ansible/playbooks/update_dns_records.yml +++ /dev/null @@ -1,15 +0,0 @@ ---- -# ================================================================ -# Playbook de Mise à Jour des Enregistrements DNS -# -# C'est le playbook à lancer après un `terraform apply` ou -# une modification des variables DNS. -# Il garantit que la configuration est à jour. -# USAGE : ansible-playbook -i inventory/ playbooks/update_dns_records.yml -# ================================================================ - -- name: "Synchroniser les enregistrements DNS" - hosts: dns_servers - become: true - roles: - - role: dns_server diff --git a/ansible/roles/dns_server/handlers/main.yml b/ansible/roles/dns_server/handlers/main.yml deleted file mode 100644 index dc66cb4..0000000 --- a/ansible/roles/dns_server/handlers/main.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -# ================================================================ -# Handlers pour le rôle dns_server -# -# Ces tâches ne sont exécutées que si elles sont "notifiées" -# par une autre tâche qui a effectué un changement. -# ================================================================ - -- name: Restart dnsmasq - ansible.builtin.service: - name: dnsmasq - state: restarted diff --git a/ansible/roles/dns_server/tasks/main.yml b/ansible/roles/dns_server/tasks/main.yml deleted file mode 100644 index 354c2e8..0000000 --- a/ansible/roles/dns_server/tasks/main.yml +++ /dev/null @@ -1,55 +0,0 @@ ---- -# Tâches principales pour le rôle dns_server - -- name: "[DNS] Installation du paquet Dnsmasq" - tags: install - ansible.builtin.apt: - name: dnsmasq - state: present - update_cache: true - -- name: "[DNS] Création du dossier pour les fichiers d'hôtes" - tags: configure - ansible.builtin.file: - path: /etc/dnsmasq.hosts.d - state: directory - owner: root - group: root - mode: '0755' - -- name: "[DNS] Création du fichier de configuration principal (dnsmasq.conf)" - tags: configure - ansible.builtin.template: - src: dnsmasq.conf.j2 - dest: /etc/dnsmasq.conf - owner: root - group: root - mode: '0644' - notify: Restart dnsmasq - -- name: "[DNS] Déploiement des enregistrements DNS statiques (home)" - tags: configure - ansible.builtin.template: - src: records.home.j2 - dest: /etc/dnsmasq.hosts.d/records.home.arnodo.fr - owner: root - group: root - mode: '0644' - notify: Restart dnsmasq - -- name: "[DNS] Déploiement des enregistrements DNS dynamiques (lab)" - tags: configure - ansible.builtin.template: - src: records.lab.j2 - dest: /etc/dnsmasq.hosts.d/records.lab.arnodo.fr - owner: root - group: root - mode: '0644' - notify: Restart dnsmasq - -- name: "[DNS] Vérification que le service Dnsmasq est actif et activé au démarrage" - tags: service - ansible.builtin.service: - name: dnsmasq - state: started - enabled: true diff --git a/ansible/roles/dns_server/templates/dnsmasq.conf.j2 b/ansible/roles/dns_server/templates/dnsmasq.conf.j2 deleted file mode 100644 index d37dfe4..0000000 --- a/ansible/roles/dns_server/templates/dnsmasq.conf.j2 +++ /dev/null @@ -1,36 +0,0 @@ -# ================================================================ -# Fichier de configuration principal de Dnsmasq -# CE FICHIER EST GÉRÉ PAR ANSIBLE - NE PAS MODIFIER MANUELLEMENT -# ================================================================ - -# Ne jamais transmettre les requêtes pour le domaine local vers l'extérieur -local=/{{ dnsmasq_domain_name }}/ - -# Définit le domaine de base pour les noms courts -domain={{ dnsmasq_domain_name }} - -# Active la fonctionnalité 'domain' ci-dessus pour les noms dans les fichiers d'hôtes -expand-hosts - -# Ne pas lire le fichier /etc/resolv.conf du système -no-resolv - -# Interfaces d'écoute -{% for addr in dnsmasq_listen_addresses %} -listen-address={{ addr }} -{% endfor %} - -# Serveurs DNS en amont (upstream) -{% for server in dnsmasq_upstream_servers %} -server={{ server }} -{% endfor %} - -# Taille du cache -cache-size={{ dnsmasq_cache_size }} - -# Configuration log -log-queries - -# On indique explicitement où trouver nos listes d'hôtes additionnelles -addn-hosts=/etc/dnsmasq.hosts.d/records.home.arnodo.fr -addn-hosts=/etc/dnsmasq.hosts.d/records.lab.arnodo.fr diff --git a/ansible/roles/dns_server/templates/records.home.j2 b/ansible/roles/dns_server/templates/records.home.j2 deleted file mode 100644 index 8dfcb82..0000000 --- a/ansible/roles/dns_server/templates/records.home.j2 +++ /dev/null @@ -1,8 +0,0 @@ -# =================================================== -# Fichier des enregistrements DNS statiques (home) -# GÉRÉ PAR ANSIBLE -# Source: group_vars/all/static_records.yml -# =================================================== -{% for record in dns_records_home %} -{{ record.ip }} {{ record.names | join(' ') }} -{% endfor %} diff --git a/ansible/roles/dns_server/templates/records.lab.j2 b/ansible/roles/dns_server/templates/records.lab.j2 deleted file mode 100644 index 4d75f0b..0000000 --- a/ansible/roles/dns_server/templates/records.lab.j2 +++ /dev/null @@ -1,11 +0,0 @@ -# =================================================== -# Fichier des enregistrements DNS dynamiques (lab) -# GÉRÉ PAR ANSIBLE -# Source: Inventaire généré par Terraform -# =================================================== -# -# IP Address FQDN Short Name -# -{% for host in groups['lab'] | default([]) %} -{{ hostvars[host].ansible_host }} {{ hostvars[host].inventory_hostname }} {{ hostvars[host].inventory_hostname_short }} -{% endfor %} diff --git a/ansible/roles/grafana_alloy/handlers/main.yml b/ansible/roles/grafana_alloy/handlers/main.yml deleted file mode 100644 index 83bdfe6..0000000 --- a/ansible/roles/grafana_alloy/handlers/main.yml +++ /dev/null @@ -1,24 +0,0 @@ ---- -# ================================================================ -# Handlers for grafana_alloy role -# ================================================================ - -- name: Reload systemd - ansible.builtin.systemd: - daemon_reload: true - become: true - listen: Reload systemd - -- name: Restart alloy - ansible.builtin.service: - name: alloy - state: restarted - become: true - listen: Restart alloy - -- name: Convert GPG key - ansible.builtin.command: - cmd: gpg --dearmor -o /etc/apt/keyrings/grafana.gpg /tmp/grafana.gpg.key - creates: /etc/apt/keyrings/grafana.gpg - become: true - listen: Convert GPG key diff --git a/ansible/roles/grafana_alloy/tasks/main.yml b/ansible/roles/grafana_alloy/tasks/main.yml deleted file mode 100644 index 0ce2785..0000000 --- a/ansible/roles/grafana_alloy/tasks/main.yml +++ /dev/null @@ -1,139 +0,0 @@ ---- -# ================================================================ -# Rôle : grafana_alloy -# Tâches principales -# -# Objectif : Installer Grafana Alloy depuis le dépôt officiel -# Grafana sur une distribution Debian/Ubuntu, puis -# déployer la configuration et le service systemd. -# -# Étapes CLI équivalentes : -# 1. sudo apt install gpg -# 2. sudo mkdir -p /etc/apt/keyrings/ -# 3. wget -q -O - https://apt.grafana.com/gpg.key | \ -# gpg --dearmor | sudo tee /etc/apt/keyrings/grafana.gpg >/dev/null -# 4. echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] \ -# https://apt.grafana.com stable main" \ -# | sudo tee /etc/apt/sources.list.d/grafana.list -# 5. sudo apt-get update -# 6. sudo apt-get install alloy -# 7. sudo systemctl start alloy -# 8. sudo systemctl enable alloy.service -# -# Cette implémentation reprend ces étapes en Ansible et ajoute -# les déploiements de configuration + unité systemd. -# ================================================================ - -- name: "[grafana_alloy] Paquets de base (gpg, wget, apt-transport-https, ca-certificates)" - ansible.builtin.apt: - name: - - gpg - - wget - - apt-transport-https - - ca-certificates - state: present - update_cache: true - tags: - - grafana_alloy - - install - -- name: "[grafana_alloy] Création du répertoire /etc/apt/keyrings" - ansible.builtin.file: - path: /etc/apt/keyrings - state: directory - mode: "0755" - tags: - - grafana_alloy - - repo - -- name: "[grafana_alloy] Téléchargement de la clé GPG Grafana" - ansible.builtin.get_url: - url: https://apt.grafana.com/gpg.key - dest: /tmp/grafana.gpg.key - mode: "0644" - notify: Convert GPG key - tags: - - grafana_alloy - - repo - -- name: "[grafana_alloy] Conversion de la clé GPG au format keyring" - ansible.builtin.command: - cmd: gpg --dearmor -o /etc/apt/keyrings/grafana.gpg /tmp/grafana.gpg.key - creates: /etc/apt/keyrings/grafana.gpg - tags: - - grafana_alloy - - repo - -- name: "[grafana_alloy] Ajout du dépôt Grafana" - ansible.builtin.apt_repository: - repo: "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" - filename: grafana - state: present - tags: - - grafana_alloy - - repo - -- name: "[grafana_alloy] Installation du paquet alloy" - ansible.builtin.apt: - name: alloy - state: present - update_cache: true - tags: - - grafana_alloy - - install - -# ---------------------------------------------------------------- -# Déploiement de la configuration d'Alloy (River) -# ---------------------------------------------------------------- -- name: "[grafana_alloy] Dossier de configuration /etc/alloy" - ansible.builtin.file: - path: /etc/alloy - state: directory - owner: root - group: root - mode: "0755" - tags: - - grafana_alloy - - config - -- name: "[grafana_alloy] Déploiement de la configuration Alloy" - ansible.builtin.template: - src: config.alloy.j2 - dest: "{{ alloy_config_file | default('/etc/alloy/config.alloy') }}" - owner: root - group: root - mode: "0644" - notify: - - Restart alloy - tags: - - grafana_alloy - - config - -# ---------------------------------------------------------------- -# Déploiement/override de l’unité systemd -# ---------------------------------------------------------------- -- name: "[grafana_alloy] Déploiement du service systemd (override)" - ansible.builtin.template: - src: alloy.service.j2 - dest: /etc/systemd/system/alloy.service - owner: root - group: root - mode: "0644" - notify: - - Reload systemd - - Restart alloy - tags: - - grafana_alloy - - config - -# ---------------------------------------------------------------- -# Activation et démarrage du service -# ---------------------------------------------------------------- -- name: "[grafana_alloy] Démarrage et activation du service alloy" - ansible.builtin.service: - name: alloy - state: started - enabled: true - tags: - - grafana_alloy - - service diff --git a/ansible/roles/grafana_alloy/templates/alloy.service.j2 b/ansible/roles/grafana_alloy/templates/alloy.service.j2 deleted file mode 100644 index cab8ad5..0000000 --- a/ansible/roles/grafana_alloy/templates/alloy.service.j2 +++ /dev/null @@ -1,27 +0,0 @@ -[Unit] -Description=Grafana Alloy -Documentation=https://grafana.com/docs/alloy/latest/ -Wants=network-online.target -After=network-online.target - -[Service] -User=alloy -Group=alloy -Type=simple - -# Commande de démarrage finale et correcte, basée sur la sortie de "alloy run --help" -ExecStart=/usr/bin/alloy run /etc/alloy/config.alloy \ - --storage.path=/var/lib/alloy \ - --server.http.listen-addr=127.0.0.1:12345 - -# Sécurité via systemd -ReadWritePaths=/var/lib/alloy -ReadOnlyPaths=/etc/alloy - -# Politiques de redémarrage et de limites de fichiers -Restart=on-failure -RestartSec=5s -LimitNOFILE=65536 - -[Install] -WantedBy=multi-user.target diff --git a/ansible/roles/grafana_alloy/templates/config.alloy.j2 b/ansible/roles/grafana_alloy/templates/config.alloy.j2 deleted file mode 100644 index b13fb31..0000000 --- a/ansible/roles/grafana_alloy/templates/config.alloy.j2 +++ /dev/null @@ -1,87 +0,0 @@ -// ============================================================================= -// -// Template Grafana Alloy pour Ansible -// Monitoring complet : Métriques Système + Statut Dnsmasq + Logs Système -// -// v3 : Délimitation claire des pipelines Métriques et Logs. -// Inclut la correction pour le label "unit". -// -// ============================================================================= - - -// ============================================================================= -// === CONFIGURATION GLOBALE ET DESTINATIONS =================================== -// ============================================================================= - -logging { - level = "{{ alloy_log_level | default("info") }}" - format = "{{ alloy_log_format | default("logfmt") }}" -} - -// Destination pour les métriques Prometheus -prometheus.remote_write "to_prometheus" { - endpoint { - url = "{{ alloy_prometheus_url | default("http://vision.lab.home.arnodo.fr:9090/api/v1/write") }}" - } -} - -// Destination pour les logs Loki -loki.write "to_loki" { - endpoint { - url = "{{ alloy_loki_url | default("http://vision.lab.home.arnodo.fr:3100/loki/api/v1/push") }}" - } - external_labels = { - source = "raspberrypi", - } -} - - -// ============================================================================= -// === PIPELINE DES MÉTRIQUES (PROMETHEUS) ===================================== -// ============================================================================= - -// Étape 1 : Collecte des métriques locales -prometheus.exporter.unix "system" {} -prometheus.exporter.dnsmasq "dnsmasq_status" {} - -// Étape 2 : Scrape des métriques et envoi vers Prometheus -prometheus.scrape "local_metrics" { - targets = concat( - prometheus.exporter.unix.system.targets, - prometheus.exporter.dnsmasq.dnsmasq_status.targets, - ) - forward_to = [prometheus.remote_write.to_prometheus.receiver] -} - - -// ============================================================================= -// === PIPELINE DES LOGS (LOKI) ================================================ -// ============================================================================= - -// Étape 1 : Définition des règles de transformation pour les logs -loki.relabel "journal_rules" { - forward_to = [] // Ce bloc ne fait que définir des règles - - rule { - source_labels = ["__journal__systemd_unit"] - target_label = "unit" - } -} - -// Étape 2 : Lecture des logs du journal systemd, transformation et envoi -loki.source.journal "read_journal" { - // CORRECTION 1 : Envoi vers la bonne destination "to_loki" - forward_to = [loki.write.to_loki.receiver] - - // Applique les règles définies ci-dessus - relabel_rules = loki.relabel.journal_rules.rules - - // CORRECTION 2 : Ajout des labels statiques (y compris "job") - labels = { - component = "loki.source.journal", - job = "journal", - } -} - -// CORRECTION 3 : Le bloc loki.write "endpoint" en double a été supprimé. -// Les logs sont maintenant envoyés au bloc "to_loki" défini en haut du fichier. diff --git a/cloud-init/user-data.yml.tftpl b/cloud-init/user-data.yml.tftpl new file mode 100644 index 0000000..044769c --- /dev/null +++ b/cloud-init/user-data.yml.tftpl @@ -0,0 +1,29 @@ +#cloud-config + +# 1. Configuration du nom d'hôte de la machine +hostname: ${hostname} +fqdn: ${hostname} +preserve_hostname: false + +# 2. Création de l'utilisateur +users: + - name: ${username} + sudo: ALL=(ALL) NOPASSWD:ALL + groups: sudo, admin + shell: /bin/bash + ssh_authorized_keys: + - ${ssh_key} + +# 3. Mise à jour du système +package_update: true +package_upgrade: true + +# 4. Installation des paquets +packages: + - qemu-guest-agent + - curl + +# 5. Installation et configuration de Tailscale +runcmd: + - [ sh, -c, "curl -fsSL https://tailscale.com/install.sh | sh" ] + - [ tailscale, up, --authkey=${tailscale_auth_key}, --hostname=${vm_name} ] diff --git a/terraform/prod/01-virtual-machines.tf b/terraform/prod/01-virtual-machines.tf index 2083172..170f3bf 100644 --- a/terraform/prod/01-virtual-machines.tf +++ b/terraform/prod/01-virtual-machines.tf @@ -7,7 +7,7 @@ data "proxmox_virtual_environment_vms" "templates" { tags = ["template"] } -# 2. Mapping des templates et préparation des données pour Ansible +# 2. Mapping des templates locals { # OS supportés supported_os = toset(["ubuntu", "debian", "alpine", "rocky", "centos"]) @@ -18,18 +18,6 @@ locals { one(setintersection(local.supported_os, template.tags)) => template if length(setintersection(local.supported_os, template.tags)) > 0 } - - ansible_vms = { - for key, vm in proxmox_virtual_environment_vm.vms : key => { - # Données issues de la ressource VM créée - name = vm.name - proxmox_node = vm.node_name - - # Données issues de vos variables d'entrée - ip_address = var.virtual_machines[key].ip - os_distro = var.virtual_machines[key].os - } - } } # 3. Création des machines virtuelles @@ -87,8 +75,7 @@ resource "proxmox_virtual_environment_vm" "vms" { vm_id = local.template_map[each.value.os].vm_id } - # On utilise le bloc 'initialization' pour configurer directement - # le réseau et l'utilisateur, sans fichier user_data externe. + # On utilise le bloc 'initialization' pour configurer Cloud-Init initialization { # Configuration IP ip_config { @@ -98,15 +85,12 @@ resource "proxmox_virtual_environment_vm" "vms" { } } - # Configuration utilisateur - user_account { - username = lookup(each.value, "username", var.default_vm_user) - keys = [file(var.admin_ssh_public_key_path)] - } + # Données Cloud-Init via le fichier de template + user_data_file_id = proxmox_virtual_environment_file.cloud_config[each.key].id } } -# 5. Outputs pour récupérer les informations des VMs +# 4. Outputs pour récupérer les informations des VMs output "vm_info" { description = "Informations des machines virtuelles créées" value = { @@ -119,14 +103,3 @@ output "vm_info" { } } } - -# Génération automatique de l'inventaire Ansible -resource "local_file" "ansible_inventory" { - filename = "${path.module}/../../ansible/inventory/01_lab_hosts.yml" - - content = templatefile("${path.module}/templates/inventory.tftpl", { - vms = local.ansible_vms - }) - - depends_on = [proxmox_virtual_environment_vm.vms] -} diff --git a/terraform/prod/02-cloud-init.tf b/terraform/prod/02-cloud-init.tf new file mode 100644 index 0000000..90996c3 --- /dev/null +++ b/terraform/prod/02-cloud-init.tf @@ -0,0 +1,26 @@ +# Fichier: terraform/prod/02-cloud-init.tf + +resource "proxmox_virtual_environment_file" "cloud_config" { + for_each = var.virtual_machines + + node_name = var.target_node + datastore_id = "local" + content_type = "snippets" + + source_raw { + data = templatefile("${path.module}/../../cloud-init/user-data.yml.tftpl", { + # Variables pour définir les informations de l'utilisateur + username = lookup(each.value, "username", var.default_vm_user) + ssh_key = file(var.admin_ssh_public_key_path) + + # Variables pour définir les informations de la VM + hostname = "${each.key}.${var.domain_suffix}" + + # Nouvelles variables pour Tailscale + vm_name = each.key # Le nom de la VM (ex: "web-01") + tailscale_auth_key = var.tailscale_auth_key + }) + + file_name = "${each.key}-cloud-init.yml" + } +} diff --git a/terraform/prod/02-lxc-containers.tf b/terraform/prod/02-lxc-containers.tf deleted file mode 100644 index e773762..0000000 --- a/terraform/prod/02-lxc-containers.tf +++ /dev/null @@ -1,196 +0,0 @@ -# Fichier: terraform/prod/lxc-containers.tf -# Description: Déploiement des conteneurs LXC sur Proxmox -# Status: Préparatoire - À développer selon les besoins - -# NOTE: Ce fichier est préparé pour le futur déploiement de conteneurs LXC -# Il n'est pas encore fonctionnel et servira de base pour le développement - -# 1. Récupération des templates LXC disponibles -# data "proxmox_virtual_environment_container_templates" "lxc_templates" { -# node_name = var.target_node -# } - -# 2. Mapping des templates LXC par distribution -# locals { -# # Distributions LXC supportées -# supported_lxc_distros = toset(["ubuntu", "debian", "alpine", "centos"]) -# -# # Map des templates LXC par distribution (à implémenter) -# lxc_template_map = { -# # Structure exemple : -# # "ubuntu" = "ubuntu-20.04-standard_20.04-1_amd64.tar.gz" -# # "debian" = "debian-11-standard_11.0-1_amd64.tar.gz" -# # "alpine" = "alpine-3.14-default_20210623_amd64.tar.xz" -# } -# } - -# 3. Création des conteneurs LXC -# resource "proxmox_virtual_environment_container" "lxc_containers" { -# for_each = var.lxc_containers -# -# # Configuration de base -# node_name = var.target_node -# vm_id = each.value.vm_id -# -# # Configuration du conteneur -# description = "LXC Container: ${each.key}" -# tags = concat(["terraform-managed", "lxc"], each.value.tags) -# -# # Configuration système -# unprivileged = lookup(each.value, "unprivileged", true) -# on_boot = lookup(each.value, "on_boot", true) -# started = lookup(each.value, "started", true) -# -# # Configuration OS -# operating_system { -# template_file_id = each.value.template -# type = lookup(each.value, "os_type", "ubuntu") -# } -# -# # Configuration CPU et mémoire -# cpu { -# cores = each.value.cores -# } -# -# memory { -# dedicated = each.value.memory -# swap = lookup(each.value, "swap", 512) -# } -# -# # Configuration réseau -# network_interface { -# name = "eth0" -# bridge = lookup(each.value, "network_bridge", "vmbr0") -# enabled = true -# firewall = lookup(each.value, "firewall", false) -# } -# -# # Configuration stockage -# disk { -# datastore_id = lookup(each.value, "datastore", "local-lvm") -# size = each.value.disk_gb -# } -# -# # Configuration d'initialisation -# initialization { -# hostname = "${each.key}.${var.domain_suffix}" -# -# ip_config { -# ipv4 { -# address = "${each.value.ip}/${lookup(each.value, "netmask", "24")}" -# gateway = each.value.gateway -# } -# } -# -# dns { -# servers = lookup(each.value, "dns_servers", ["8.8.8.8", "8.8.4.4"]) -# } -# -# user_account { -# keys = [file(var.admin_ssh_public_key_path)] -# } -# } -# } - -# 4. Outputs pour les conteneurs LXC -# output "lxc_info" { -# description = "Informations des conteneurs LXC créés" -# value = { -# for k, v in proxmox_virtual_environment_container.lxc_containers : k => { -# id = v.id -# name = v.hostname -# node = v.node_name -# ip = var.lxc_containers[k].ip -# status = v.status -# } -# } -# } - -# ===== SECTION COMMENTÉE - EXEMPLES DE CONFIGURATION ===== - -# Exemple de configuration pour les variables LXC (à ajouter dans variables.tf) : -# variable "lxc_containers" { -# description = "Configuration des conteneurs LXC à déployer" -# type = map(object({ -# # Configuration de base -# vm_id = number -# template = string -# cores = number -# memory = number -# disk_gb = number -# ip = string -# gateway = string -# -# # Configuration optionnelle -# os_type = optional(string, "ubuntu") -# netmask = optional(string, "24") -# datastore = optional(string, "local-lvm") -# network_bridge = optional(string, "vmbr0") -# unprivileged = optional(bool, true) -# on_boot = optional(bool, true) -# started = optional(bool, true) -# firewall = optional(bool, false) -# swap = optional(number, 512) -# dns_servers = optional(list(string), ["8.8.8.8", "8.8.4.4"]) -# tags = optional(list(string), []) -# })) -# default = {} -# } - -# Exemple de configuration dans terraform.tfvars : -# lxc_containers = { -# "web-proxy" = { -# vm_id = 200 -# template = "ubuntu-20.04-standard_20.04-1_amd64.tar.gz" -# cores = 1 -# memory = 1024 -# disk_gb = 8 -# ip = "192.168.1.200" -# gateway = "192.168.1.254" -# tags = ["proxy", "nginx"] -# } -# -# "monitoring-light" = { -# vm_id = 201 -# template = "alpine-3.14-default_20210623_amd64.tar.xz" -# cores = 1 -# memory = 512 -# disk_gb = 4 -# ip = "192.168.1.201" -# gateway = "192.168.1.254" -# tags = ["monitoring", "lightweight"] -# } -# } - -# ===== AVANTAGES DES LXC ===== -# -# 1. Consommation réduite de ressources par rapport aux VMs -# 2. Démarrage plus rapide -# 3. Idéal pour les services légers (reverse proxy, monitoring, etc.) -# 4. Partage du kernel avec l'hôte = meilleure efficacité -# 5. Isolation suffisante pour la plupart des cas d'usage homelab -# -# ===== QUAND UTILISER LXC VS VM ===== -# -# Utiliser LXC pour : -# - Services web légers (nginx, apache) -# - Outils de monitoring légers -# - Reverse proxy -# - Services de fichiers simples -# - Environnements de développement -# -# Utiliser VM pour : -# - Services nécessitant un kernel spécifique -# - Applications nécessitant une isolation forte -# - Kubernetes nodes -# - Bases de données critiques -# - Services Windows - -# ===== TODO POUR ACTIVATION ===== -# -# Pour activer ce fichier : -# 1. Décommenter le code ci-dessus -# 2. Ajouter la variable lxc_containers dans variables.tf -# 3. Configurer les templates LXC disponibles -# 4. Tester avec un conteneur simple -# 5. Documenter les templates disponibles diff --git a/terraform/prod/README.md b/terraform/prod/README.md index 2e3e226..f4d65d4 100644 --- a/terraform/prod/README.md +++ b/terraform/prod/README.md @@ -1,101 +1,41 @@ # Terraform Configuration - Production Environment -Ce dossier contient la configuration Terraform pour déployer l'infrastructure du homelab sur Proxmox. +Ce dossier contient la configuration Terraform pour déployer l'infrastructure du homelab sur Proxmox VE. ## Structure des fichiers -### Fichiers principaux - -- **`virtual-machines.tf`** - Configuration et déploiement des machines virtuelles -- **`lxc-containers.tf`** - Configuration des conteneurs LXC (préparatoire) +- **`01-virtual-machines.tf`** - Configuration et déploiement des machines virtuelles +- **`02-cloud-init.tf`** - Configuration Cloud-Init pour l'initialisation automatique des VMs - **`providers.tf`** - Configuration des providers Terraform - **`variables.tf`** - Définition des variables - **`terraform.tfvars`** - Valeurs des variables (à personnaliser) -- **`inventory.tf`** - Génération de l'inventaire Ansible +- **`terraform.tfvars.example`** - Exemple de configuration -### Dossier templates - -- **`cloud-init.yaml.tpl`** - Template de configuration Cloud-Init pour les VMs -- **`inventory.tpl`** - Template pour générer l'inventaire Ansible - -## Déploiement des VMs - -### Configuration de base - -Les VMs sont configurées dans le fichier `terraform.tfvars` sous la variable `virtual_machines` : - -```hcl -virtual_machines = { - "nom-vm" = { - os = "debian" # OS du template à utiliser - cores = 2 # Nombre de CPU cores - memory = 4096 # RAM en MB - disk_gb = 30 # Taille du disque en GB - ip = "192.168.1.100" # Adresse IP statique - gateway = "192.168.1.254" # Passerelle réseau - tags = ["monitoring"] # Tags pour l'organisation - packages = ["curl", "vim"] # Packages à installer - } -} -``` - -### Options avancées - -Chaque VM peut avoir des configurations optionnelles : - -```hcl -"nom-vm-avancee" = { - # Configuration de base - os = "ubuntu" - cores = 4 - memory = 8192 - disk_gb = 50 - ip = "192.168.1.101" - gateway = "192.168.1.254" - - # Options avancées - cpu_type = "host" # Type de CPU (défaut: host) - datastore = "local-lvm" # Datastore Proxmox - network_bridge = "vmbr0" # Bridge réseau - username = "admin" # Utilisateur (défaut: damien) - dns_servers = ["1.1.1.1"] # Serveurs DNS - post_install_commands = ["apt update"] # Commandes post-installation - - # Disques supplémentaires - additional_disks = [ - { - interface = "scsi1" - datastore = "local-lvm" - size = 100 - } - ] -} -``` - -## Templates supportés - -Les templates doivent être présents sur Proxmox avec les tags appropriés : - -- **ubuntu** - Ubuntu Server (tag: `ubuntu`, `template`) -- **debian** - Debian (tag: `debian`, `template`) -- **alpine** - Alpine Linux (tag: `alpine`, `template`) -- **rocky** - Rocky Linux (tag: `rocky`, `template`) -- **centos** - CentOS (tag: `centos`, `template`) - -## Utilisation +## Configuration rapide ### 1. Prérequis - Terraform installé -- Accès à l'API Proxmox -- Templates VM configurés sur Proxmox +- Accès à l'API Proxmox VE +- Templates VM configurés sur Proxmox avec les tags appropriés - Clés SSH configurées +- Compte Tailscale avec une clé d'authentification ### 2. Configuration -1. Copier `terraform.tfvars.example` vers `terraform.tfvars` -2. Personnaliser les valeurs dans `terraform.tfvars` -3. Vérifier les chemins des clés SSH +```bash +# Copier le fichier d'exemple +cp terraform.tfvars.example terraform.tfvars + +# Éditer avec vos valeurs +vim terraform.tfvars +``` + +Variables importantes à configurer : +- `proxmox_url` : URL de votre serveur Proxmox +- `proxmox_api_token` : Token d'API Proxmox +- `tailscale_auth_key` : Clé d'authentification Tailscale +- `virtual_machines` : Configuration de vos VMs ### 3. Déploiement @@ -103,122 +43,98 @@ Les templates doivent être présents sur Proxmox avec les tags appropriés : # Initialisation terraform init -# Planification +# Vérification terraform plan -# Application +# Déploiement terraform apply ``` -### 4. Vérification +## Configuration des VMs -```bash -# Liste des ressources -terraform state list +Les VMs sont configurées dans `terraform.tfvars` : -# Informations des VMs -terraform output vm_info +```hcl +virtual_machines = { + "monitoring" = { + os = "debian" + cores = 2 + memory = 4096 + disk_gb = 30 + ip = "192.168.1.161" + gateway = "192.168.1.254" + tags = ["monitoring"] + } +} ``` -## Intégration Ansible +### Options disponibles -L'inventaire Ansible est généré automatiquement dans `../../ansible/inventory/hosts.ini`. +- **os** : Template à utiliser (ubuntu, debian, alpine, rocky, centos) +- **cores** : Nombre de cœurs CPU +- **memory** : RAM en MB +- **disk_gb** : Taille du disque principal en GB +- **ip** : Adresse IP statique +- **gateway** : Passerelle réseau +- **tags** : Tags pour l'organisation +- **additional_disks** : Disques supplémentaires (optionnel) +- **username** : Utilisateur de la VM (optionnel, défaut: root) -### Groupes générés automatiquement +## Templates requis -- **Par OS** : `ubuntu`, `debian`, `alpine`, etc. -- **Par tags** : groupes basés sur les tags des VMs -- **Par pattern de nom** : `monitoring`, `web`, `database`, `kubernetes` +Les templates doivent être présents sur Proxmox avec les tags correspondants : -### Utilisation avec Ansible +| OS | Tags requis | +|---|---| +| Ubuntu | `["ubuntu", "template"]` | +| Debian | `["debian", "template"]` | +| Alpine | `["alpine", "template"]` | +| Rocky | `["rocky", "template"]` | +| CentOS | `["centos", "template"]` | -```bash -# Test de connectivité -ansible all -i inventory/hosts.ini -m ping +## Fonctionnalités automatiques -# Playbook sur un groupe -ansible-playbook -i inventory/hosts.ini playbooks/common.yml --limit monitoring -``` - -## Conteneurs LXC (Futur) - -Le fichier `lxc-containers.tf` est préparé pour le déploiement de conteneurs LXC. -Il n'est pas encore fonctionnel mais servira de base pour le développement futur. - -### Avantages des LXC - -- Consommation réduite de ressources -- Démarrage plus rapide -- Idéal pour les services légers - -### Cas d'usage recommandés - -**LXC pour :** -- Reverse proxy (nginx) -- Monitoring léger -- Services web simples -- Environnements de développement - -**VM pour :** -- Kubernetes nodes -- Bases de données critiques -- Services nécessitant une isolation forte -- Applications avec besoins kernel spécifiques +- **Cloud-Init** : Configuration automatique des VMs au premier démarrage +- **Tailscale** : Installation et connexion automatique au réseau Tailscale +- **SSH** : Configuration des clés SSH pour l'accès sécurisé +- **QEMU Guest Agent** : Installation automatique pour une meilleure intégration ## Maintenance -### Mise à jour des VMs +### Ajouter une VM -```bash -# Modifier terraform.tfvars -# Puis appliquer les changements -terraform plan -terraform apply -``` +1. Ajouter la configuration dans `terraform.tfvars` +2. Exécuter `terraform apply` -### Suppression d'une VM +### Supprimer une VM -```bash -# Retirer la VM de terraform.tfvars -# Puis appliquer -terraform apply -``` +1. Retirer la configuration de `terraform.tfvars` +2. Exécuter `terraform apply` -### Sauvegarde de l'état +### Modifier une VM -```bash -# Sauvegarde manuelle -cp terraform.tfstate terraform.tfstate.backup.$(date +%Y%m%d) -``` +1. Modifier la configuration dans `terraform.tfvars` +2. Exécuter `terraform plan` pour voir les changements +3. Exécuter `terraform apply` ## Dépannage ### Problèmes courants -1. **Template non trouvé** : Vérifier que le template existe sur Proxmox avec les bons tags -2. **IP déjà utilisée** : Vérifier les conflits d'adresses IP -3. **Clé SSH** : Vérifier le chemin vers la clé publique SSH +- **Template non trouvé** : Vérifier les tags sur Proxmox +- **IP déjà utilisée** : Vérifier les conflits d'adresses +- **Erreur SSH** : Vérifier le chemin de la clé publique +- **Tailscale** : Vérifier la validité de la clé d'authentification -### Logs utiles +### Logs détaillés ```bash -# Logs Terraform détaillés TF_LOG=DEBUG terraform apply - -# État des ressources -terraform show ``` ## Sécurité -- Les clés SSH privées ne sont jamais stockées dans le code -- Les tokens API sont dans des variables d'environnement -- Les VMs sont configurées avec des utilisateurs non-root -- SSH par mot de passe est désactivé - -## Support - -Pour toute question ou problème, consulter : -- Documentation Terraform Proxmox Provider -- Logs Proxmox (`/var/log/pveproxy/`) -- État Terraform (`terraform show`) +- Authentification par clés SSH uniquement +- Connexion sécurisée via Tailscale +- Isolation réseau des VMs +- Tokens API sécurisés \ No newline at end of file diff --git a/terraform/prod/templates/inventory.tftpl b/terraform/prod/templates/inventory.tftpl deleted file mode 100644 index 61e3d1b..0000000 --- a/terraform/prod/templates/inventory.tftpl +++ /dev/null @@ -1,13 +0,0 @@ -# Ansible Inventory - Généré par Terraform le ${timestamp()} -# Ne pas modifier ce fichier manuellement, il sera écrasé. - -all: - children: - lab: - hosts: -%{ for key, vm_data in vms } - ${vm_data.name}: - ansible_host: ${vm_data.ip_address} - os_distro: "${vm_data.os_distro}" - proxmox_node: "${vm_data.proxmox_node}" -%{ endfor } diff --git a/terraform/prod/terraform.tfvars.example b/terraform/prod/terraform.tfvars.example index 77d73a9..f0181ef 100644 --- a/terraform/prod/terraform.tfvars.example +++ b/terraform/prod/terraform.tfvars.example @@ -11,7 +11,7 @@ ############################# # URL de votre serveur Proxmox (REQUIS) -proxmox_url = "https://pve01.lab.home.arnodo.fr:8006" +proxmox_url = "https://pve01.taila5ad8.ts.net:8006" # Token API Proxmox (REQUIS - À configurer dans Proxmox) # Créer dans : Datacenter -> Permissions -> API Tokens @@ -25,7 +25,7 @@ target_node = "pve01" ############################# # Suffixe de domaine pour les VMs -domain_suffix = "lab.home.arnodo.fr" +domain_suffix = "taila5ad8.ts.net" ############################# # Configuration SSH @@ -37,143 +37,60 @@ admin_ssh_public_key_path = "~/.ssh/keys/id_rsa.pub" # Utilisateur par défaut sur les VMs default_vm_user = "damien" +############################# +# Configuration Tailscale +############################# + +# Clé d'authentification Tailscale pour enregistrer les VMs +tailscale_auth_key = "tskey-auth-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + ############################# # Machines virtuelles ############################# virtual_machines = { # Exemple VM de monitoring - "vision" = { + "monitoring" = { os = "debian" cores = 2 memory = 4096 disk_gb = 30 ip = "192.168.1.161" gateway = "192.168.1.254" - tags = ["monitoring", "grafana"] + tags = ["monitoring"] } - # Exemples d'autres VMs (décommentez et adaptez selon vos besoins) + # Exemple serveur web + "webserver" = { + os = "ubuntu" + cores = 2 + memory = 2048 + disk_gb = 20 + ip = "192.168.1.162" + gateway = "192.168.1.254" + tags = ["web", "nginx"] + } - # # Serveur web - # "webserver" = { - # os = "ubuntu" - # cores = 2 - # memory = 2048 - # disk_gb = 20 - # ip = "192.168.1.162" - # gateway = "192.168.1.254" - # tags = ["web", "nginx"] - # } + # Exemple base de données avec disque supplémentaire + "database" = { + os = "debian" + cores = 4 + memory = 8192 + disk_gb = 50 + ip = "192.168.1.163" + gateway = "192.168.1.254" + tags = ["database", "postgresql"] - # # Base de données - # "database" = { - # os = "debian" - # cores = 4 - # memory = 8192 - # disk_gb = 50 - # ip = "192.168.1.163" - # gateway = "192.168.1.254" - # tags = ["database", "postgresql"] - # - # # Disque supplémentaire pour les données - # additional_disks = [ - # { - # interface = "scsi1" - # datastore = "local-lvm" - # size = 100 - # } - # ] - # } - - # # Node Kubernetes master - # "k8s-master" = { - # os = "ubuntu" - # cores = 4 - # memory = 4096 - # disk_gb = 40 - # ip = "192.168.1.170" - # gateway = "192.168.1.254" - # tags = ["kubernetes", "master"] - # } - - # # Node Kubernetes worker - # "k8s-worker1" = { - # os = "ubuntu" - # cores = 4 - # memory = 8192 - # disk_gb = 60 - # ip = "192.168.1.171" - # gateway = "192.168.1.254" - # tags = ["kubernetes", "worker"] - # } - - # # Serveur de fichiers/NAS - # "fileserver" = { - # os = "debian" - # cores = 2 - # memory = 4096 - # disk_gb = 40 - # ip = "192.168.1.180" - # gateway = "192.168.1.254" - # tags = ["storage", "nas"] - # - # # Multiples disques pour le stockage - # additional_disks = [ - # { - # interface = "scsi1" - # datastore = "local-lvm" - # size = 500 - # }, - # { - # interface = "scsi2" - # datastore = "local-lvm" - # size = 500 - # } - # ] - # } - - # # VM de développement - # "devbox" = { - # os = "ubuntu" - # cores = 4 - # memory = 8192 - # disk_gb = 80 - # ip = "192.168.1.190" - # gateway = "192.168.1.254" - # tags = ["development", "docker"] - # } + additional_disks = [ + { + interface = "scsi1" + datastore = "local-lvm" + size = 100 + } + ] + } } -############################# -# Conteneurs LXC (Futur) -############################# - -# Configuration préparée pour les conteneurs LXC -# Actuellement désactivée - sera implémentée dans une future version - -# lxc_containers = { -# # Exemple proxy léger -# "nginx-proxy" = { -# vm_id = 200 -# template = "ubuntu-20.04-standard" -# cores = 1 -# memory = 1024 -# disk_gb = 8 -# ip = "192.168.1.200" -# gateway = "192.168.1.254" -# tags = ["proxy", "nginx"] -# } -# } - -############################# -# Maintien compatibilité (deprecated) -############################# - -# Ancienne variable - sera supprimée dans une future version -# Utilisez virtual_machines à la place -monitoring_vms = {} - ############################# # Notes de configuration ############################# @@ -185,15 +102,8 @@ monitoring_vms = {} # - Template Rocky avec tags : ["rocky", "template"] # - Template CentOS avec tags : ["centos", "template"] -# Réseau recommandé : -# - VLAN/Bridge : vmbr0 -# - Plage IP : 192.168.1.0/24 -# - Passerelle : 192.168.1.254 -# - DNS : 8.8.8.8, 8.8.4.4 (ou votre DNS local) - # Ressources recommandées par type de service : # - Monitoring : 2 CPU, 4GB RAM, 30GB disque # - Web server : 2 CPU, 2GB RAM, 20GB disque -# - Database : 4 CPU, 8GB RAM, 50GB+ disque -# - Kubernetes : 4 CPU, 4GB+ RAM, 40GB+ disque -# - Development : 4 CPU, 8GB RAM, 80GB disque +# - Database : 4+ CPU, 8GB+ RAM, 50GB+ disque +# - Kubernetes : 4+ CPU, 4GB+ RAM, 40GB+ disque diff --git a/terraform/prod/variables.tf b/terraform/prod/variables.tf index 79d36ac..5fc93d5 100644 --- a/terraform/prod/variables.tf +++ b/terraform/prod/variables.tf @@ -14,6 +14,13 @@ variable "proxmox_url" { variable "proxmox_api_token" { description = "Token pour accéder à l'API Proxmox" type = string + sensitive = true +} + +variable "tailscale_auth_key" { + description = "Clé d'authentification Tailscale pour enregistrer les noeuds." + type = string + sensitive = true } variable "admin_ssh_public_key_path" { @@ -23,9 +30,9 @@ variable "admin_ssh_public_key_path" { } variable "domain_suffix" { - description = "Suffixe de domaine pour les VMs (ex: lab.home.arnodo.fr)" + description = "Suffixe de domaine pour les VMs (ex: taila5ad8.ts.net)" type = string - default = "lab.home.arnodo.fr" + default = "taila5ad8.ts.net" } variable "default_vm_user" { @@ -54,7 +61,6 @@ variable "virtual_machines" { network_model = optional(string, "virtio") username = optional(string) on_boot = optional(bool, true) - dns_servers = optional(list(string), ["8.8.8.8", "8.8.4.4"]) tags = optional(list(string), []) # Disques supplémentaires (optionnel)