Automatyczne zarządzanie LXC w Proxmox za pomocą OpenTofu

IAC do zarządzania środowiskiem Proxmox.

Nie ma nic bardziej satysfakcjonującego niż kliknięcie tofu apply i zobaczenie, jak Proxmox sam pobiera template LXC, tworzy kontenery i konfiguruje dostęp. Poniżej opisuję, jak wygląda ten proces w moim repozytorium iac-proxmox i na co warto zwrócić uwagę, jeśli chcesz to odwzorować u siebie.

Dlaczego LXC do IaC w Proxmox

  • Kontenery startują w sekundy i zużywają minimalne zasoby w porównaniu z pełnymi VM.
  • Wspólny kernel i brak emulacji sprzętu sprawiają, że świetnie nadają się do mikroserwisów, proxy, workerów CI czy środowisk testowych.
  • Dzięki OpenTofu cały cykl życia kontenera (tworzenie, aktualizacja, usuwanie) jest wersjonowany w Git i odtwarzalny na innym hoście.

Jak zorganizowałem repozytorium iac-proxmox

Wydzielam dwa kluczowe katalogi:

  • containers_templates/ – zasoby odpowiedzialne za pobieranie obrazów LXC do magazynu Proxmoxa.
  • machines/ – pojedyncze pliki ctXXXXX.tf, każdy opisuje wygląd kontenera.

Krok 1. Pobieranie template: jeden zasób, zero ręcznych klików

Szablon Ubuntu 24.04 LTS pobieram wprost z repozytorium Proxmoxa:

resource "proxmox_virtual_environment_download_file" "ubuntu24-10" {
  content_type       = "vztmpl"
  datastore_id       = local.storage_name
  node_name          = local.default_node
  file_name          = "ubuntu-24.04.tar.zst"
  url                = "http://download.proxmox.com/images/system/ubuntu-24.04-standard_24.04-2_amd64.tar.zst"
  checksum           = "4030982618eeae70854e8f9711adbd09"
  checksum_algorithm = "md5"
}

Kluczowe jest ustawienie checksum i checksum_algorithm – mam pewność, że obraz nie został uszkodzony, a plan w razie różnic przerwie się na weryfikacji.

Krok 2. Tworzenie kontenera – minimalny moduł

Każdy kontener to osobny moduł z jednoznacznym ct_id:

module "ct01011" {
  source = "git@gitlab.rachuna-net.pl:pl.rachuna-net/infrastructure/opentofu/modules/proxmox-container.git?ref=v1.0.0"

  hostname      = "ct01011.rachuna-net.pl"
  description   = "example-service"
  node_name     = "pve-s1"
  ct_id         = 1011
  pool_id       = "web-proxy"
  start_on_boot = true
  tags          = ["example", "ubuntu"]

  cpu_cores = 2
  memory = { dedicated = 2048, swap = 1024 }
  disk   = { storage_name = "local-lvm", disk_size = 32 }

  operating_system = {
    template_file = "local:vztmpl/ubuntu-24.04.tar.zst"
    type          = "ubuntu"
  }

  user_account = {
    username       = "techuser"
    password       = "change-me"
    public_ssh_key = "ssh-ed25519 AAAA..."
  }
}

Najważniejsze parametry, które zawsze ustawiam:

Parametr Co robi
hostname Pełna nazwa DNS kontenera
node_name Węzeł Proxmoxa, na którym zostanie utworzony
ct_id Stałe ID kontenera – ułatwia śledzenie i logging
pool_id Przynależność do puli logicznej (np. web, db, proxy)
start_on_boot Autostart po restarcie noda
cpu_cores/memory/disk Twarda kontrola zasobów hosta
operating_system.template_file Ścieżka do wcześniej pobranego template
user_account Automatycznie zakładane konto i klucz SSH

Krok 3. Bezpieczeństwo: sekrety z Vault zamiast w pliku

Hasła i klucze trzymam poza repozytorium. Wartości w user_account mogą pochodzić z Vault:

user_account = {
  username       = data.vault_kv_secret_v2.ct.data["username"]
  password       = data.vault_kv_secret_v2.ct.data["password"]
  public_ssh_key = data.vault_kv_secret_v2.ct.data["ssh_key"]
}

Zyskuję rotację haseł, brak sekretów w Git i spójny audyt dostępu.

Last modified December 19, 2025: docs: Update (72bba37)