Add Cloud-Init automation with Tailscale
The commit rephrases the README to focus on Cloud-Init setup and removes unused Ansible code, making Tailscale configuration automatic. Subject line: Replace Ansible with automated Cloud-Init configuration Body: Refactors infrastructure bootstrapping to leverage Cloud-Init instead of Ansible for initial VM setup, particularly with respect to Tailscale installation and authentication. This simplifies the architecture by: - Removing manual post-provisioning Ansible steps - Automating Tailscale setup via Cloud-Init - Updating documentation to reflect new workflow
This commit is contained in:
67
README.md
67
README.md
@@ -2,49 +2,70 @@
|
|||||||
|
|
||||||
## Description
|
## 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.
|
This repository contains Infrastructure as Code (IaC) configurations for a home lab environment. It uses Terraform to provision virtual machines on Proxmox VE. The initial configuration of the VMs, including the installation and activation of Tailscale, is handled automatically by Cloud-Init.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- Terraform installed on your machine
|
- Terraform installed on your local machine.
|
||||||
- Ansible installed on your machine
|
- A Proxmox VE instance up and running.
|
||||||
- Proxmox VE installed on homelab
|
- A Tailscale account and an authentication key.
|
||||||
|
|
||||||
#### Proxmox Role and User
|
### Proxmox Setup
|
||||||
|
|
||||||
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.
|
For Terraform to interact with your Proxmox environment, you must create a dedicated user with specific, limited permissions.
|
||||||
|
|
||||||
Following the least privilege principle, the role creates a dedicated user account with limited permissions for managing the Proxmox VE cluster.
|
|
||||||
|
|
||||||
|
1. **Create a role (`TerraformProv`) with the necessary privileges:**
|
||||||
```bash
|
```bash
|
||||||
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"
|
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.
|
2. **Create a dedicated user (`terraform@pve`):**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pveum user add terraform@pve --password <password>
|
pveum user add terraform@pve --password <your_secure_password>
|
||||||
pveum acl modify / -user terraform@pve -role TerraformProv
|
pveum acl modify / -user terraform@pve -role TerraformProv
|
||||||
```
|
```
|
||||||
|
|
||||||
Generate API keys for the Proxmox VE cluster.
|
3. **Generate an API token for the user:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pveum user token add terraform@pve terraform -expire 0 -privsep 0 -comment "Terraform token"
|
pveum user token add terraform@pve terraform -expire 0 -privsep 0
|
||||||
```
|
```
|
||||||
|
Securely store the generated token ID and secret, as you will need them to authenticate Terraform.
|
||||||
|
|
||||||
### Provisioning Infrastructure
|
### Provisioning Infrastructure
|
||||||
|
|
||||||
1. Clone this repository to your local machine.
|
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.
|
|
||||||
|
|
||||||
### Configuring Infrastructure
|
2. **Navigate to the production environment directory:**
|
||||||
|
```bash
|
||||||
|
cd iac-homelab/terraform/prod
|
||||||
|
```
|
||||||
|
|
||||||
1. Navigate to the `ansible` directory.
|
3. **Create a `terraform.tfvars` file.** You can copy the example file to get started:
|
||||||
2. Run `ansible-playbook playbooks/setup_dns_server.yml` to set up the DNS server.
|
```bash
|
||||||
(Or `ansible-playbook playbooks/update_dns_records.yml` to update DNS records).
|
cp terraform.tfvars.example terraform.tfvars
|
||||||
|
```
|
||||||
|
Edit this file to include your Proxmox API credentials and your Tailscale authentication key.
|
||||||
|
|
||||||
|
4. **Initialize Terraform:**
|
||||||
|
```bash
|
||||||
|
terraform init
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Plan and apply the changes:**
|
||||||
|
```bash
|
||||||
|
terraform plan
|
||||||
|
terraform apply
|
||||||
|
```
|
||||||
|
Terraform will show you a plan of the resources to be created. If you agree, confirm the apply.
|
||||||
|
|
||||||
|
### Configuration via Cloud-Init
|
||||||
|
|
||||||
|
The configuration of virtual machines is handled automatically on the first boot by Cloud-Init. The Terraform configuration injects a script that performs the following actions:
|
||||||
|
|
||||||
|
- Updates and upgrades all system packages.
|
||||||
|
- Installs the Tailscale agent.
|
||||||
|
- Connects the new machine to your Tailscale network using the `tailscale_auth_key` you provided.
|
||||||
|
|
||||||
|
Once `terraform apply` is complete, your new virtual machines will automatically appear in your Tailscale admin console shortly after they boot up.
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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"
|
|
||||||
@@ -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
|
|
||||||
#
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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 %}
|
|
||||||
@@ -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 %}
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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.
|
|
||||||
29
cloud-init/user-data.yml.tftpl
Normal file
29
cloud-init/user-data.yml.tftpl
Normal 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} ]
|
||||||
@@ -7,7 +7,7 @@ data "proxmox_virtual_environment_vms" "templates" {
|
|||||||
tags = ["template"]
|
tags = ["template"]
|
||||||
}
|
}
|
||||||
|
|
||||||
# 2. Mapping des templates et préparation des données pour Ansible
|
# 2. Mapping des templates
|
||||||
locals {
|
locals {
|
||||||
# OS supportés
|
# OS supportés
|
||||||
supported_os = toset(["ubuntu", "debian", "alpine", "rocky", "centos"])
|
supported_os = toset(["ubuntu", "debian", "alpine", "rocky", "centos"])
|
||||||
@@ -18,18 +18,6 @@ locals {
|
|||||||
one(setintersection(local.supported_os, template.tags)) => template
|
one(setintersection(local.supported_os, template.tags)) => template
|
||||||
if length(setintersection(local.supported_os, template.tags)) > 0
|
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
|
# 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
|
vm_id = local.template_map[each.value.os].vm_id
|
||||||
}
|
}
|
||||||
|
|
||||||
# On utilise le bloc 'initialization' pour configurer directement
|
# On utilise le bloc 'initialization' pour configurer Cloud-Init
|
||||||
# le réseau et l'utilisateur, sans fichier user_data externe.
|
|
||||||
initialization {
|
initialization {
|
||||||
# Configuration IP
|
# Configuration IP
|
||||||
ip_config {
|
ip_config {
|
||||||
@@ -98,15 +85,12 @@ resource "proxmox_virtual_environment_vm" "vms" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Configuration utilisateur
|
# Données Cloud-Init via le fichier de template
|
||||||
user_account {
|
user_data_file_id = proxmox_virtual_environment_file.cloud_config[each.key].id
|
||||||
username = lookup(each.value, "username", var.default_vm_user)
|
|
||||||
keys = [file(var.admin_ssh_public_key_path)]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 5. Outputs pour récupérer les informations des VMs
|
# 4. Outputs pour récupérer les informations des VMs
|
||||||
output "vm_info" {
|
output "vm_info" {
|
||||||
description = "Informations des machines virtuelles créées"
|
description = "Informations des machines virtuelles créées"
|
||||||
value = {
|
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]
|
|
||||||
}
|
|
||||||
|
|||||||
26
terraform/prod/02-cloud-init.tf
Normal file
26
terraform/prod/02-cloud-init.tf
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -58,7 +58,6 @@ Chaque VM peut avoir des configurations optionnelles :
|
|||||||
datastore = "local-lvm" # Datastore Proxmox
|
datastore = "local-lvm" # Datastore Proxmox
|
||||||
network_bridge = "vmbr0" # Bridge réseau
|
network_bridge = "vmbr0" # Bridge réseau
|
||||||
username = "admin" # Utilisateur (défaut: damien)
|
username = "admin" # Utilisateur (défaut: damien)
|
||||||
dns_servers = ["1.1.1.1"] # Serveurs DNS
|
|
||||||
post_install_commands = ["apt update"] # Commandes post-installation
|
post_install_commands = ["apt update"] # Commandes post-installation
|
||||||
|
|
||||||
# Disques supplémentaires
|
# Disques supplémentaires
|
||||||
|
|||||||
@@ -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 }
|
|
||||||
@@ -14,6 +14,13 @@ variable "proxmox_url" {
|
|||||||
variable "proxmox_api_token" {
|
variable "proxmox_api_token" {
|
||||||
description = "Token pour accéder à l'API Proxmox"
|
description = "Token pour accéder à l'API Proxmox"
|
||||||
type = string
|
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" {
|
variable "admin_ssh_public_key_path" {
|
||||||
@@ -54,7 +61,6 @@ variable "virtual_machines" {
|
|||||||
network_model = optional(string, "virtio")
|
network_model = optional(string, "virtio")
|
||||||
username = optional(string)
|
username = optional(string)
|
||||||
on_boot = optional(bool, true)
|
on_boot = optional(bool, true)
|
||||||
dns_servers = optional(list(string), ["8.8.8.8", "8.8.4.4"])
|
|
||||||
tags = optional(list(string), [])
|
tags = optional(list(string), [])
|
||||||
|
|
||||||
# Disques supplémentaires (optionnel)
|
# Disques supplémentaires (optionnel)
|
||||||
|
|||||||
Reference in New Issue
Block a user