Merge pull request #2 from darnodo/feat/tailscale

Feat/tailscale
This commit is contained in:
D. Arnodo
2025-07-14 19:40:01 +02:00
committed by GitHub
24 changed files with 428 additions and 1283 deletions

265
README.md
View File

@@ -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 <password>
# Créer l'utilisateur
pveum user add terraform@pve --password <mot_de_passe_securise>
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 <repository-url>
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=<token>"
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-<votre-cle>"
# 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/)

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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
#

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 %}

View File

@@ -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 %}

View File

@@ -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

View File

@@ -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 lunité 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

View File

@@ -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

View File

@@ -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.

View File

@@ -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} ]

View File

@@ -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]
}

View File

@@ -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"
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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 }

View File

@@ -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

View File

@@ -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)