first sync
This commit is contained in:
1 parent
6087245e5c
commit
b046f4054e
15 files changed
+721
-103
No files matched your search
@@ -1,39 +0,0 @@
|
||||
name: terraform validation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
types: [opened, reopened, edited, synchronize]
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
name: 'Terraform'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: hashicorp/setup-terraform@v3
|
||||
with:
|
||||
terraform_version: 1.7.5
|
||||
|
||||
- name: Terraform fmt
|
||||
id: fmt
|
||||
run: terraform fmt -check -diff -recursive
|
||||
continue-on-error: true
|
||||
|
||||
- name: Terraform Init
|
||||
id: init
|
||||
run: terraform init
|
||||
# working-directory: examples
|
||||
|
||||
- name: Terraform Validate
|
||||
id: validate
|
||||
run: terraform validate
|
||||
# working-directory: examples
|
||||
|
||||
- name: Terraform Plan
|
||||
id: plan
|
||||
run: terraform plan
|
||||
+6
-38
@@ -1,41 +1,9 @@
|
||||
# ---> VisualStudioCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
#
|
||||
*.exe
|
||||
|
||||
# Local .terraform directories
|
||||
**/.terraform/*
|
||||
|
||||
# .tfstate files
|
||||
.terraform/
|
||||
*.tfstate
|
||||
*.tfstate.*
|
||||
|
||||
# Crash log files
|
||||
crash.log
|
||||
crash.*.log
|
||||
|
||||
# Exclude all .tfvars files, which are likely to contain sensitive data
|
||||
*.tfvars
|
||||
*.tfvars.json
|
||||
|
||||
# Ignore transient lock info files created by terraform apply
|
||||
.terraform.tfstate.lock.info
|
||||
|
||||
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
|
||||
*tfplan*
|
||||
|
||||
# Ignore CLI configuration files
|
||||
.terraformrc
|
||||
terraform.rc
|
||||
terraform.tfvars
|
||||
*.auto.tfvars
|
||||
generated/
|
||||
override.tf
|
||||
override.tf.json
|
||||
@@ -1,39 +1,117 @@
|
||||
# centreon-terraform — VM Debian 12 minimale pour Centreon
|
||||
|
||||
# ${REPO_NAME}
|
||||
Crée sur le nœud Proxmox `pve` une VM Debian 12 réduite au strict nécessaire, durcie
|
||||
par cloud-init, et prête à être reprise par Ansible (dépôt `centreon-ansible`).
|
||||
|
||||
${REPO_DESCRIPTION}
|
||||
Ce dépôt ne connaît rien de Centreon : il produit un serveur, rien d'autre.
|
||||
|
||||
# A propos de
|
||||
## Ce que le code met en place
|
||||
|
||||
# Prérequis
|
||||
| Point | Choix retenu |
|
||||
|---|---|
|
||||
| Système | Debian 12 *genericcloud* (image officielle, ~350 Mo, sans noyau cloud-specific inutile) |
|
||||
| Pourquoi pas Debian 13 | Centreon 25.10 ne supporte que Debian 12 |
|
||||
| Comptes | un seul compte unix (`ansible`), sans mot de passe, sudo NOPASSWD, clé publique uniquement |
|
||||
| root | connexion SSH refusée, mot de passe verrouillé |
|
||||
| SSH | mot de passe et clavier-interactif désactivés, `AuthenticationMethods publickey`, `AllowUsers` limité au compte d'administration |
|
||||
| Services exposés | **22/tcp et ICMP uniquement**, et seulement depuis `ssh_allowed_cidrs` |
|
||||
| Pare-feu | nftables, politique `drop` en entrée et en transit, avec un répertoire `/etc/nftables.d/` qu'Ansible viendra compléter |
|
||||
| Mises à jour | `unattended-upgrades` activé |
|
||||
| Sysctl | redirections ICMP, source routing, dmesg et kptr restreints |
|
||||
| Agent | `qemu-guest-agent` (remontée des IP et arrêt propre côté Proxmox) |
|
||||
|
||||
Vous avez besoin d'une installation docker fonctionnelle.
|
||||
Rien d'autre n'écoute : pas de serveur mail local, pas de rpcbind, pas d'exim —
|
||||
l'image *genericcloud* n'en embarque aucun.
|
||||
|
||||
https://developer.hashicorp.com/terraform/install?product_intent=terraform
|
||||
## Prérequis
|
||||
|
||||
# Démarrage manuel
|
||||
1. **Jeton d'API Proxmox.** Le jeton `terraform@pve!provisioner` existant convient, à
|
||||
condition que son rôle porte au minimum :
|
||||
`VM.Allocate`, `VM.Config.*`, `VM.PowerMgmt`, `VM.Audit`, `VM.Console`,
|
||||
`VM.GuestAgent.Audit`, `Datastore.Allocate`, `Datastore.AllocateSpace`,
|
||||
`Datastore.AllocateTemplate`, `Datastore.Audit`, `Sys.Audit`, `SDN.Use`.
|
||||
`SDN.Use` est nécessaire depuis PVE 8.2 pour attacher une carte à un bridge.
|
||||
|
||||
~~~bash
|
||||
git clone https://gitea.tips-of-mine.com${REPO_LINK}.git
|
||||
cd ${TEMPLATE_NAME}
|
||||
~~~
|
||||
2. **Accès SSH au nœud.** Le dépôt du snippet cloud-init passe par SSH : l'API
|
||||
Proxmox ne sait pas téléverser dans le contenu `snippets`. Le compte utilisé doit
|
||||
pouvoir écrire dans `/var/lib/vz/snippets`.
|
||||
|
||||
# Utilisation du repository
|
||||
3. **Contenu `snippets` activé** sur le stockage `local` :
|
||||
`pvesm set local --content images,rootdir,vztmpl,backup,iso,snippets`
|
||||
(à vérifier une fois : `pvesm status --storage local`).
|
||||
|
||||
init
|
||||
~~~bash
|
||||
terraform init
|
||||
~~~
|
||||
4. **Réservation d'adresse.** `10.0.5.20` doit être exclue de la plage DHCP
|
||||
d'OPNsense, sinon le bail pourra être attribué à une autre machine.
|
||||
|
||||
validation
|
||||
~~~bash
|
||||
terraform validate
|
||||
~~~
|
||||
## Secrets
|
||||
|
||||
plan
|
||||
~~~bash
|
||||
terraform plan
|
||||
~~~
|
||||
Aucun secret n'est écrit dans les fichiers `.tf` ni dans `terraform.tfvars` :
|
||||
|
||||
# Buy me a coffe
|
||||
<a href='https://ko-fi.com/R5R2KNI3N' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi4.png?v=3' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
||||
```bash
|
||||
export TF_VAR_pve_api_token='terraform@pve!provisioner=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
|
||||
export TF_VAR_pve_ssh_password='...'
|
||||
```
|
||||
|
||||
Si le projet rejoint la CI Gitea, ces deux valeurs se lisent dans OpenBao comme pour
|
||||
`proxmox-create-vm`, en réutilisant `secret/proxmox`.
|
||||
|
||||
## Exécution sans installer Terraform
|
||||
|
||||
```bash
|
||||
cp terraform.tfvars.example terraform.tfvars # puis adapter, surtout ssh_public_keys
|
||||
|
||||
docker run --rm -it \
|
||||
-v "$PWD":/work -w /work \
|
||||
-e TF_VAR_pve_api_token -e TF_VAR_pve_ssh_password \
|
||||
hashicorp/terraform:latest init
|
||||
|
||||
docker run --rm -it \
|
||||
-v "$PWD":/work -w /work \
|
||||
-e TF_VAR_pve_api_token -e TF_VAR_pve_ssh_password \
|
||||
hashicorp/terraform:latest apply
|
||||
```
|
||||
|
||||
Sous PowerShell, remplacer `"$PWD"` par `${PWD}` et passer les variables avec
|
||||
`-e TF_VAR_pve_api_token=$env:TF_VAR_pve_api_token`.
|
||||
|
||||
L'état reste local (`terraform.tfstate`) : c'est une plateforme de test, il n'y a pas
|
||||
de backend distant. Le passage sur le backend S3 se fait en ajoutant un `state.tf`,
|
||||
comme dans `proxmox-create-vm`.
|
||||
|
||||
## Après l'apply
|
||||
|
||||
`terraform apply` produit :
|
||||
|
||||
- la VM 120 démarrée, qui exécute cloud-init pendant **3 à 6 minutes** (mise à jour
|
||||
complète du système comprise) ;
|
||||
- `generated/inventory.yml`, l'inventaire Ansible correspondant.
|
||||
|
||||
Vérification :
|
||||
|
||||
```bash
|
||||
ssh [email protected] 'cloud-init status --wait && sudo nft list chain inet filter input'
|
||||
```
|
||||
|
||||
La sortie attendue ne contient que `lo`, `established,related`, l'ICMP et le port 22.
|
||||
|
||||
## Points d'attention
|
||||
|
||||
- **cloud-init ne rejoue rien.** Modifier `templates/user-data.yaml.tftpl` après
|
||||
création ne change pas la VM existante : le snippet garde le même nom, donc le même
|
||||
identifiant, et Terraform ne voit même pas de différence. Pour repartir d'un
|
||||
système propre : `terraform destroy` puis `apply`.
|
||||
- **Image Debian.** `overwrite = false` évite de retélécharger 350 Mo à chaque apply.
|
||||
Debian republie régulièrement l'image `latest` sous le même nom : si une version
|
||||
plus récente est souhaitée, supprimer le fichier sur le nœud et relancer l'apply.
|
||||
Le paramètre `debian_image_checksum` est disponible mais laissé vide, une empreinte
|
||||
figée cassant à chaque respin de l'image.
|
||||
- **Extension `.img`.** Proxmox n'accepte que `.iso` et `.img` dans le contenu `iso` :
|
||||
le `.qcow2` téléchargé est donc renommé, son format réel étant inchangé.
|
||||
- **Redémarrage.** Si cloud-init installe un nouveau noyau, la VM continue de tourner
|
||||
sur l'ancien. Un `sudo reboot` avant de lancer Ansible est une bonne habitude.
|
||||
|
||||
## Suite
|
||||
|
||||
```bash
|
||||
cp generated/inventory.yml ../centreon-ansible/inventory/hosts.yml
|
||||
```
|
||||
@@ -0,0 +1,26 @@
|
||||
locals {
|
||||
fqdn = "${var.vm_hostname}.${var.dns_domain}"
|
||||
}
|
||||
|
||||
# Le fichier est déposé dans le contenu "snippets" du stockage, via SSH.
|
||||
# Attention : cloud-init ne rejoue la configuration qu'au premier démarrage.
|
||||
# Modifier ce snippet après coup n'a donc aucun effet sur une VM déjà installée.
|
||||
resource "proxmox_virtual_environment_file" "user_data" {
|
||||
content_type = "snippets"
|
||||
datastore_id = var.snippet_datastore_id
|
||||
node_name = var.pve_node
|
||||
|
||||
source_raw {
|
||||
file_name = "${var.vm_hostname}-user-data.yaml"
|
||||
|
||||
data = templatefile("${path.module}/templates/user-data.yaml.tftpl", {
|
||||
hostname = var.vm_hostname
|
||||
fqdn = local.fqdn
|
||||
timezone = var.timezone
|
||||
locale = var.locale
|
||||
ansible_user = var.ansible_user
|
||||
ssh_keys = var.ssh_public_keys
|
||||
admin_cidrs = var.ssh_allowed_cidrs
|
||||
})
|
||||
}
|
||||
}
|
||||
Whitespace-only changes.
Whitespace-only changes.
@@ -0,0 +1,121 @@
|
||||
resource "proxmox_virtual_environment_download_file" "debian_cloud_image" {
|
||||
content_type = "iso"
|
||||
datastore_id = var.image_datastore_id
|
||||
node_name = var.pve_node
|
||||
url = var.debian_image_url
|
||||
file_name = var.debian_image_file_name
|
||||
checksum = var.debian_image_checksum
|
||||
checksum_algorithm = var.debian_image_checksum == null ? null : var.debian_image_checksum_algorithm
|
||||
|
||||
# L'image n'est pas retéléchargée à chaque apply, mais un fichier déjà
|
||||
# présent et non géré par Terraform est repris plutôt que de faire échouer le plan.
|
||||
overwrite = false
|
||||
overwrite_unmanaged = true
|
||||
upload_timeout = 1800
|
||||
}
|
||||
|
||||
resource "proxmox_virtual_environment_vm" "centreon" {
|
||||
name = var.vm_hostname
|
||||
description = "Serveur central Centreon - géré par Terraform, ne pas modifier à la main"
|
||||
tags = ["terraform", "debian12", "centreon"]
|
||||
|
||||
node_name = var.pve_node
|
||||
vm_id = var.vm_id
|
||||
|
||||
on_boot = true
|
||||
started = true
|
||||
stop_on_destroy = true
|
||||
|
||||
machine = "q35"
|
||||
bios = "seabios"
|
||||
scsi_hardware = "virtio-scsi-single"
|
||||
boot_order = ["scsi0"]
|
||||
|
||||
operating_system {
|
||||
type = "l26"
|
||||
}
|
||||
|
||||
agent {
|
||||
enabled = true
|
||||
trim = true
|
||||
}
|
||||
|
||||
cpu {
|
||||
cores = var.vm_cores
|
||||
type = "host"
|
||||
}
|
||||
|
||||
memory {
|
||||
dedicated = var.vm_memory
|
||||
}
|
||||
|
||||
disk {
|
||||
datastore_id = var.vm_datastore_id
|
||||
import_from = proxmox_virtual_environment_download_file.debian_cloud_image.id
|
||||
interface = "scsi0"
|
||||
size = var.vm_disk_size
|
||||
file_format = "qcow2"
|
||||
discard = "on"
|
||||
iothread = true
|
||||
ssd = true
|
||||
}
|
||||
|
||||
network_device {
|
||||
bridge = var.vm_bridge
|
||||
model = "virtio"
|
||||
}
|
||||
|
||||
# Console série : permet un « qm terminal 120 » depuis le nœud si le réseau
|
||||
# de la VM est cassé, sans ouvrir de service supplémentaire.
|
||||
serial_device {}
|
||||
|
||||
initialization {
|
||||
datastore_id = var.vm_datastore_id
|
||||
interface = "ide2"
|
||||
|
||||
dns {
|
||||
domain = var.dns_domain
|
||||
servers = var.dns_servers
|
||||
}
|
||||
|
||||
ip_config {
|
||||
ipv4 {
|
||||
address = "${var.vm_ipv4_address}/${var.vm_ipv4_prefix}"
|
||||
gateway = var.vm_ipv4_gateway
|
||||
}
|
||||
}
|
||||
|
||||
user_data_file_id = proxmox_virtual_environment_file.user_data.id
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
# Proxmox renvoie un type de machine versionné (pc-q35-11.0+pve2) et
|
||||
# réordonne le boot : sans cela, chaque plan proposerait une modification.
|
||||
ignore_changes = [
|
||||
machine,
|
||||
boot_order,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
resource "local_file" "ansible_inventory" {
|
||||
filename = var.ansible_inventory_path
|
||||
file_permission = "0644"
|
||||
|
||||
content = yamlencode({
|
||||
all = {
|
||||
children = {
|
||||
centreon_central = {
|
||||
hosts = {
|
||||
(var.vm_hostname) = {
|
||||
ansible_host = var.vm_ipv4_address
|
||||
ansible_user = var.ansible_user
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
depends_on = [proxmox_virtual_environment_vm.centreon]
|
||||
}
|
||||
Whitespace-only changes.
+24
@@ -0,0 +1,24 @@
|
||||
output "vm_id" {
|
||||
description = "VMID de la machine créée."
|
||||
value = proxmox_virtual_environment_vm.centreon.vm_id
|
||||
}
|
||||
|
||||
output "vm_ipv4_address" {
|
||||
description = "Adresse IPv4 fixe de la machine."
|
||||
value = var.vm_ipv4_address
|
||||
}
|
||||
|
||||
output "vm_fqdn" {
|
||||
description = "Nom pleinement qualifié de la machine."
|
||||
value = local.fqdn
|
||||
}
|
||||
|
||||
output "ssh_command" {
|
||||
description = "Commande de connexion une fois cloud-init terminé."
|
||||
value = "ssh ${var.ansible_user}@${var.vm_ipv4_address}"
|
||||
}
|
||||
|
||||
output "ansible_inventory_file" {
|
||||
description = "Inventaire généré, à recopier dans le dépôt Ansible."
|
||||
value = local_file.ansible_inventory.filename
|
||||
}
|
||||
Whitespace-only changes.
@@ -0,0 +1,18 @@
|
||||
provider "proxmox" {
|
||||
endpoint = var.pve_endpoint
|
||||
api_token = var.pve_api_token
|
||||
insecure = var.pve_insecure
|
||||
|
||||
# Le dépôt d'un snippet cloud-init passe obligatoirement par SSH :
|
||||
# l'API Proxmox ne permet pas de téléverser dans le contenu "snippets".
|
||||
ssh {
|
||||
agent = false
|
||||
username = var.pve_ssh_username
|
||||
password = var.pve_ssh_password
|
||||
|
||||
node {
|
||||
name = var.pve_node
|
||||
address = var.pve_node_address
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
#cloud-config
|
||||
# Généré par Terraform — toute modification manuelle sera écrasée.
|
||||
# Rappel : ce fichier n'est appliqué qu'au tout premier démarrage de la VM.
|
||||
|
||||
hostname: ${hostname}
|
||||
fqdn: ${fqdn}
|
||||
prefer_fqdn_over_hostname: true
|
||||
manage_etc_hosts: true
|
||||
timezone: ${timezone}
|
||||
|
||||
# La clé "users" remplace la liste par défaut : le compte "debian" livré avec
|
||||
# l'image cloud n'est donc jamais créé. Un seul compte existe sur la machine,
|
||||
# sans mot de passe (lock_passwd), accessible uniquement par clé.
|
||||
users:
|
||||
- name: ${ansible_user}
|
||||
gecos: Compte d administration (Ansible)
|
||||
groups: [sudo]
|
||||
shell: /bin/bash
|
||||
lock_passwd: true
|
||||
sudo: "ALL=(ALL) NOPASSWD:ALL"
|
||||
ssh_authorized_keys:
|
||||
%{ for key in ssh_keys ~}
|
||||
- "${key}"
|
||||
%{ endfor ~}
|
||||
|
||||
disable_root: true
|
||||
ssh_pwauth: false
|
||||
ssh_deletekeys: true
|
||||
ssh_genkeytypes: [ed25519, rsa]
|
||||
|
||||
package_update: true
|
||||
package_upgrade: true
|
||||
|
||||
# Strict minimum : agent invité, pare-feu, mises à jour de sécurité,
|
||||
# et les prérequis d'Ansible et de l'installateur Centreon.
|
||||
packages:
|
||||
- qemu-guest-agent
|
||||
- nftables
|
||||
- unattended-upgrades
|
||||
- apt-listchanges
|
||||
- locales
|
||||
- python3-apt
|
||||
- ca-certificates
|
||||
- curl
|
||||
- wget
|
||||
- gnupg2
|
||||
- lsb-release
|
||||
- apt-transport-https
|
||||
|
||||
write_files:
|
||||
- path: /etc/ssh/sshd_config.d/99-durcissement.conf
|
||||
owner: root:root
|
||||
permissions: "0600"
|
||||
content: |
|
||||
# Durcissement SSH — cloud-init
|
||||
PermitRootLogin no
|
||||
PasswordAuthentication no
|
||||
KbdInteractiveAuthentication no
|
||||
PermitEmptyPasswords no
|
||||
PubkeyAuthentication yes
|
||||
AuthenticationMethods publickey
|
||||
AllowUsers ${ansible_user}
|
||||
MaxAuthTries 3
|
||||
LoginGraceTime 30
|
||||
X11Forwarding no
|
||||
AllowAgentForwarding no
|
||||
AllowTcpForwarding no
|
||||
ClientAliveInterval 300
|
||||
ClientAliveCountMax 2
|
||||
|
||||
- path: /etc/nftables.conf
|
||||
owner: root:root
|
||||
permissions: "0640"
|
||||
content: |
|
||||
#!/usr/sbin/nft -f
|
||||
# Jeu de règles principal — cloud-init.
|
||||
# En entrée, seuls SSH et ICMP sont ouverts. Les ports applicatifs
|
||||
# (web, SNMP, gorgone) sont ajoutés par Ansible dans /etc/nftables.d/.
|
||||
flush ruleset
|
||||
|
||||
table inet filter {
|
||||
set reseaux_admin {
|
||||
type ipv4_addr
|
||||
flags interval
|
||||
elements = { ${join(", ", admin_cidrs)} }
|
||||
}
|
||||
|
||||
chain input {
|
||||
type filter hook input priority filter; policy drop;
|
||||
|
||||
iif "lo" accept
|
||||
ct state established,related accept
|
||||
ct state invalid drop
|
||||
|
||||
ip protocol icmp icmp type { echo-request, destination-unreachable, time-exceeded, parameter-problem } accept
|
||||
ip6 nexthdr ipv6-icmp accept
|
||||
|
||||
tcp dport 22 ip saddr @reseaux_admin ct state new accept
|
||||
|
||||
include "/etc/nftables.d/*.nft"
|
||||
|
||||
counter comment "paquets rejetes en entree"
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority filter; policy drop;
|
||||
}
|
||||
|
||||
chain output {
|
||||
type filter hook output priority filter; policy accept;
|
||||
}
|
||||
}
|
||||
|
||||
- path: /etc/nftables.d/00-placeholder.nft
|
||||
owner: root:root
|
||||
permissions: "0640"
|
||||
content: |
|
||||
# Fragments de règles ajoutés par Ansible. Ne rien mettre ici.
|
||||
|
||||
- path: /etc/apt/apt.conf.d/20auto-upgrades
|
||||
owner: root:root
|
||||
permissions: "0644"
|
||||
content: |
|
||||
APT::Periodic::Update-Package-Lists "1";
|
||||
APT::Periodic::Unattended-Upgrade "1";
|
||||
|
||||
- path: /etc/sysctl.d/99-durcissement.conf
|
||||
owner: root:root
|
||||
permissions: "0644"
|
||||
content: |
|
||||
net.ipv4.conf.all.accept_redirects = 0
|
||||
net.ipv4.conf.default.accept_redirects = 0
|
||||
net.ipv4.conf.all.send_redirects = 0
|
||||
net.ipv4.conf.all.accept_source_route = 0
|
||||
net.ipv6.conf.all.accept_redirects = 0
|
||||
net.ipv4.icmp_echo_ignore_broadcasts = 1
|
||||
net.ipv4.tcp_syncookies = 1
|
||||
kernel.dmesg_restrict = 1
|
||||
kernel.kptr_restrict = 2
|
||||
fs.protected_hardlinks = 1
|
||||
fs.protected_symlinks = 1
|
||||
|
||||
runcmd:
|
||||
- sed -i "s|^# *${locale} UTF-8|${locale} UTF-8|" /etc/locale.gen
|
||||
- locale-gen
|
||||
- update-locale LANG=${locale}
|
||||
- sysctl --system > /dev/null
|
||||
- systemctl enable --now qemu-guest-agent
|
||||
- systemctl enable --now nftables
|
||||
- systemctl enable --now unattended-upgrades
|
||||
- systemctl restart ssh
|
||||
- apt-get -y autoremove --purge
|
||||
- apt-get -y clean
|
||||
|
||||
final_message: "cloud-init termine apres $UPTIME s - ${fqdn} est pret pour Ansible"
|
||||
@@ -0,0 +1,30 @@
|
||||
# Copier en terraform.tfvars et adapter.
|
||||
# Les deux secrets ne sont PAS dans ce fichier : ils passent par l'environnement
|
||||
# export TF_VAR_pve_api_token='terraform@pve!provisioner=xxxxxxxx-...'
|
||||
# export TF_VAR_pve_ssh_password='...'
|
||||
|
||||
pve_endpoint = "https://10.0.4.5:8006/"
|
||||
pve_node = "pve"
|
||||
pve_node_address = "10.0.4.5"
|
||||
pve_insecure = true
|
||||
|
||||
vm_id = 120
|
||||
vm_hostname = "centreon"
|
||||
vm_bridge = "vmbr3"
|
||||
|
||||
vm_ipv4_address = "10.0.5.20"
|
||||
vm_ipv4_gateway = "10.0.5.1"
|
||||
dns_servers = ["10.0.5.1"]
|
||||
dns_domain = "tips-of-mine.local"
|
||||
|
||||
vm_cores = 2
|
||||
vm_memory = 4096
|
||||
vm_disk_size = 40
|
||||
|
||||
ansible_user = "ansible"
|
||||
|
||||
ssh_public_keys = [
|
||||
"ssh-ed25519 AAAA... hcornet@poste",
|
||||
]
|
||||
|
||||
ssh_allowed_cidrs = ["10.0.4.0/24", "10.0.5.0/24"]
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
############################################
|
||||
# Accès au nœud Proxmox
|
||||
############################################
|
||||
|
||||
variable "pve_endpoint" {
|
||||
description = "URL de l'API Proxmox (ex. https://10.0.4.5:8006/)."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "pve_api_token" {
|
||||
description = "Jeton d'API au format user@realm!tokenid=uuid. À fournir par TF_VAR_pve_api_token."
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "pve_insecure" {
|
||||
description = "Ne pas vérifier le certificat TLS de l'API (nécessaire si l'endpoint est appelé par IP)."
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "pve_node" {
|
||||
description = "Nom du nœud Proxmox cible."
|
||||
type = string
|
||||
default = "pve"
|
||||
}
|
||||
|
||||
variable "pve_node_address" {
|
||||
description = "Adresse IP du nœud, utilisée pour la connexion SSH de dépôt du snippet."
|
||||
type = string
|
||||
default = "10.0.4.5"
|
||||
}
|
||||
|
||||
variable "pve_ssh_username" {
|
||||
description = "Compte SSH sur le nœud Proxmox (doit pouvoir écrire dans le répertoire des snippets)."
|
||||
type = string
|
||||
default = "root"
|
||||
}
|
||||
|
||||
variable "pve_ssh_password" {
|
||||
description = "Mot de passe SSH du nœud. À fournir par TF_VAR_pve_ssh_password."
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
############################################
|
||||
# Image Debian
|
||||
############################################
|
||||
|
||||
variable "debian_image_url" {
|
||||
description = "URL de l'image cloud Debian 12 (Centreon 25.10 ne supporte que Debian 12)."
|
||||
type = string
|
||||
default = "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2"
|
||||
}
|
||||
|
||||
variable "debian_image_file_name" {
|
||||
description = "Nom du fichier stocké sur le nœud. L'extension .img est imposée par Proxmox pour le contenu iso."
|
||||
type = string
|
||||
default = "debian-12-genericcloud-amd64.img"
|
||||
}
|
||||
|
||||
variable "debian_image_checksum" {
|
||||
description = "Empreinte de l'image (facultatif). Laisser à null pour ne pas vérifier."
|
||||
type = string
|
||||
default = null
|
||||
sensitive = false
|
||||
}
|
||||
|
||||
variable "debian_image_checksum_algorithm" {
|
||||
description = "Algorithme de l'empreinte fournie (sha256, sha512...)."
|
||||
type = string
|
||||
default = "sha512"
|
||||
}
|
||||
|
||||
variable "image_datastore_id" {
|
||||
description = "Stockage recevant l'image téléchargée (doit accepter le contenu iso)."
|
||||
type = string
|
||||
default = "local"
|
||||
}
|
||||
|
||||
variable "snippet_datastore_id" {
|
||||
description = "Stockage recevant le snippet cloud-init (doit accepter le contenu snippets)."
|
||||
type = string
|
||||
default = "local"
|
||||
}
|
||||
|
||||
############################################
|
||||
# Définition de la VM
|
||||
############################################
|
||||
|
||||
variable "vm_id" {
|
||||
description = "VMID de la machine."
|
||||
type = number
|
||||
default = 120
|
||||
}
|
||||
|
||||
variable "vm_hostname" {
|
||||
description = "Nom court de la machine (nom de VM et hostname système)."
|
||||
type = string
|
||||
default = "centreon"
|
||||
}
|
||||
|
||||
variable "vm_datastore_id" {
|
||||
description = "Stockage du disque système et du disque cloud-init."
|
||||
type = string
|
||||
default = "local"
|
||||
}
|
||||
|
||||
variable "vm_cores" {
|
||||
description = "Nombre de cœurs. 2 est le plancher réaliste pour un central avec base locale."
|
||||
type = number
|
||||
default = 2
|
||||
|
||||
validation {
|
||||
condition = var.vm_cores >= 2
|
||||
error_message = "Centreon a besoin d'au moins 2 cœurs (moteur + base + PHP-FPM)."
|
||||
}
|
||||
}
|
||||
|
||||
variable "vm_memory" {
|
||||
description = "Mémoire en Mio."
|
||||
type = number
|
||||
default = 4096
|
||||
|
||||
validation {
|
||||
condition = var.vm_memory >= 4096
|
||||
error_message = "Centreon a besoin d'au moins 4096 Mio : en dessous, l'installation web tombe en timeout."
|
||||
}
|
||||
}
|
||||
|
||||
variable "vm_disk_size" {
|
||||
description = "Taille du disque système en Gio."
|
||||
type = number
|
||||
default = 40
|
||||
}
|
||||
|
||||
variable "vm_bridge" {
|
||||
description = "Bridge de rattachement de la carte réseau."
|
||||
type = string
|
||||
default = "vmbr3"
|
||||
}
|
||||
|
||||
############################################
|
||||
# Réseau
|
||||
############################################
|
||||
|
||||
variable "vm_ipv4_address" {
|
||||
description = "Adresse IPv4 fixe de la VM."
|
||||
type = string
|
||||
default = "10.0.5.20"
|
||||
}
|
||||
|
||||
variable "vm_ipv4_prefix" {
|
||||
description = "Longueur du préfixe IPv4."
|
||||
type = number
|
||||
default = 24
|
||||
}
|
||||
|
||||
variable "vm_ipv4_gateway" {
|
||||
description = "Passerelle IPv4 (interface LAN d'OPNsense)."
|
||||
type = string
|
||||
default = "10.0.5.1"
|
||||
}
|
||||
|
||||
variable "dns_servers" {
|
||||
description = "Serveurs DNS poussés par cloud-init."
|
||||
type = list(string)
|
||||
default = ["10.0.5.1"]
|
||||
}
|
||||
|
||||
variable "dns_domain" {
|
||||
description = "Domaine de recherche et suffixe du FQDN."
|
||||
type = string
|
||||
default = "tips-of-mine.local"
|
||||
}
|
||||
|
||||
############################################
|
||||
# Système et accès
|
||||
############################################
|
||||
|
||||
variable "timezone" {
|
||||
description = "Fuseau horaire du système. Centreon reprend ce réglage pour PHP à l'installation."
|
||||
type = string
|
||||
default = "Europe/Paris"
|
||||
}
|
||||
|
||||
variable "locale" {
|
||||
description = "Locale générée sur le système."
|
||||
type = string
|
||||
default = "fr_FR.UTF-8"
|
||||
}
|
||||
|
||||
variable "ansible_user" {
|
||||
description = "Compte unix créé par cloud-init, utilisé ensuite par Ansible."
|
||||
type = string
|
||||
default = "ansible"
|
||||
}
|
||||
|
||||
variable "ssh_public_keys" {
|
||||
description = "Clés publiques autorisées pour le compte d'administration. Aucun mot de passe n'est défini."
|
||||
type = list(string)
|
||||
|
||||
validation {
|
||||
condition = length(var.ssh_public_keys) > 0
|
||||
error_message = "Au moins une clé publique est nécessaire : l'authentification par mot de passe est désactivée."
|
||||
}
|
||||
}
|
||||
|
||||
variable "ssh_allowed_cidrs" {
|
||||
description = "Réseaux autorisés à joindre le port 22 (pare-feu local nftables)."
|
||||
type = list(string)
|
||||
default = ["10.0.4.0/24", "10.0.5.0/24"]
|
||||
}
|
||||
|
||||
############################################
|
||||
# Sortie pour Ansible
|
||||
############################################
|
||||
|
||||
variable "ansible_inventory_path" {
|
||||
description = "Chemin du fichier d'inventaire généré à la fin de l'apply."
|
||||
type = string
|
||||
default = "generated/inventory.yml"
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
terraform {
|
||||
required_version = ">= 1.6.0"
|
||||
|
||||
required_providers {
|
||||
proxmox = {
|
||||
source = "bpg/proxmox"
|
||||
version = ">= 0.69.0"
|
||||
}
|
||||
local = {
|
||||
source = "hashicorp/local"
|
||||
version = ">= 2.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user