Fediversity/infra/sync-nix/main.tf
Kiara Grouwstra dd5a6335b1
proxmox
pass in description

fix syntax

configure proxmox provider

typo

add doc comment in existing modules

add comment

allow insecure proxmox connection for use in dev

wip proxmox progress

use service configurations moved to machine-independent location

wire settings directly without option block terraform

adjust cwd

try tf on null input

update .envrc.sample with sample proxmox credentials
2025-05-11 19:22:49 +02:00

224 lines
6.6 KiB
HCL

terraform {
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "= 0.76.1"
}
}
}
locals {
system = "x86_64-linux"
node_name = "node051"
dump_name = "vzdump-qemu-nixos-fediversity-${var.category}.vma.zst"
# dependency paths pre-calculated from npins
pins = jsondecode(file("${path.module}/.npins.json"))
# nix path: expose pins, use nixpkgs in flake commands (`nix run`)
nix_path = "${join(":", [for name, dir in local.pins : "${name}=${dir}"])}:flake=${local.pins["nixpkgs"]}:flake"
config_tf = merge(var.config_tf, {
})
}
data "external" "base-hash" {
program = ["sh", "-c", "echo \"{\\\"hash\\\":\\\"$(nix-hash ${path.module}/../common/nixos/base.nix)\\\"}\""]
}
# hash of our code directory, used to trigger re-deploy
# FIXME calculate separately to reduce false positives
data "external" "hash" {
program = ["sh", "-c", "echo \"{\\\"hash\\\":\\\"$(nix-hash ..)\\\"}\""]
}
resource "terraform_data" "template" {
triggers_replace = [
data.external.base-hash.result,
]
provisioner "local-exec" {
working_dir = path.root
environment = {
NIX_PATH = local.nix_path
}
command = <<-EOF
set -euo pipefail
nixos-generate -f proxmox -o /tmp/nixos-image
ln -s /tmp/nixos-image/vzdump-qemu-nixos-*.vma.zst /tmp/nixos-image/${local.dump_name}
EOF
}
}
resource "proxmox_virtual_environment_file" "upload" {
lifecycle {
replace_triggered_by = [
terraform_data.template,
]
}
content_type = "images"
datastore_id = "local"
node_name = local.node_name
overwrite = true
source_file {
path = "/tmp/nixos-image/${local.dump_name}"
file_name = local.dump_name
}
}
data "proxmox_virtual_environment_vms" "nixos_base" {
node_name = local.node_name
filter {
name = "template"
values = [true]
}
}
resource "proxmox_virtual_environment_vm" "nix_vm" {
lifecycle {
replace_triggered_by = [
proxmox_virtual_environment_file.upload,
]
}
node_name = local.node_name
pool_id = "Fediversity"
description = var.description
started = true
agent {
enabled = true
}
cpu {
type = "x86-64-v2-AES"
cores = var.cores
sockets = var.sockets
numa = true
}
memory {
dedicated = var.memory
}
efi_disk {
datastore_id = "linstor_storage"
type = "4m"
}
disk {
datastore_id = "linstor_storage"
interface = "scsi0"
discard = "on"
iothread = true
size = var.disk_size
ssd = true
}
clone {
datastore_id = "local"
node_name = data.proxmox_virtual_environment_vms.nixos_base.vms[0].node_name
vm_id = data.proxmox_virtual_environment_vms.nixos_base.vms[0].vm_id
full = true
}
network_device {
model = "virtio"
bridge = "vnet1306"
}
operating_system {
type = "l26"
}
scsi_hardware = "virtio-scsi-single"
bios = "ovmf"
}
# TF resource to build and deploy NixOS instances.
resource "terraform_data" "nixos" {
# trigger rebuild/deploy if (FIXME?) any potentially used config/code changed,
# preventing these (20+s, build being bottleneck) when nothing changed.
# terraform-nixos separates these to only deploy if instantiate changed,
# yet building even then - which may be not as bad using deploy on remote.
# having build/deploy one resource reflects wanting to prevent no-op rebuilds
# over preventing (with less false positives) no-op deployments,
# as i could not find a way to do prevent no-op rebuilds without merging them:
# - generic resources cannot have outputs, while we want info from the instantiation (unless built on host?).
# - `data` always runs, which is slow for deploy and especially build.
triggers_replace = [
data.external.hash.result,
var.config_nix,
var.config_tf,
]
provisioner "local-exec" {
# directory to run the script from. we use the TF project root dir,
# here as a path relative from where TF is run from,
# matching calling modules' expectations on config_nix locations.
# note that absolute paths can cause false positives in triggers,
# so are generally discouraged in TF.
working_dir = path.root
environment = {
# nix path used on build, lets us refer to e.g. nixpkgs like `<nixpkgs>`
NIX_PATH = local.nix_path
}
# TODO: refactor back to command="ignoreme" interpreter=concat([]) to protect sensitive data from error logs?
# TODO: build on target?
command = <<-EOF
set -euo pipefail
# INSTANTIATE
command=(
nix-instantiate
--expr
'let
os = import <nixpkgs/nixos> {
system = "${local.system}";
configuration =
${var.config_nix} //
# template parameters passed in from TF thru json
builtins.fromJSON "${replace(jsonencode(var.config_tf), "\"", "\\\"")}" //
{
# nix path for debugging
nix.nixPath = [ "${local.nix_path}" ];
};
};
in
# info we want to get back out
{
substituters = builtins.concatStringsSep " " os.config.nix.settings.substituters;
trusted_public_keys = builtins.concatStringsSep " " os.config.nix.settings.trusted-public-keys;
drv_path = os.config.system.build.toplevel.drvPath;
out_path = os.config.system.build.toplevel;
}'
)
# instantiate the config in /nix/store
"$${command[@]}" -A out_path
# get the other info
json="$("$${command[@]}" --eval --strict --json)"
# DEPLOY
declare substituters trusted_public_keys drv_path
# set our variables using the json object
eval "export $(echo $json | jaq -r 'to_entries | map("\(.key)=\(.value)") | @sh')"
host="root@${var.hostname}.${var.vm_domain}" # FIXME: #24
buildArgs=(
--option extra-binary-caches https://cache.nixos.org/
--option substituters $substituters
--option trusted-public-keys $trusted_public_keys
)
sshOpts=(
-o BatchMode=yes
-o StrictHostKeyChecking=no
)
# get the realized derivation to deploy
outPath=$(nix-store --realize "$drv_path" "$${buildArgs[@]}")
# deploy the config by nix-copy-closure
NIX_SSHOPTS="$${sshOpts[*]}" nix-copy-closure --to "$host" "$outPath" --gzip --use-substitutes
# switch the remote host to the config
ssh "$${sshOpts[@]}" "$host" "nix-env --profile /nix/var/nix/profiles/system --set $outPath; $outPath/bin/switch-to-configuration switch"
EOF
}
}