From 5d9c2d4d8a9e11a50843e9331795ef6ef36ef662 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 16 Aug 2026 23:54:26 +0000 Subject: [PATCH] initial commit --- .gitignore | 3 + main.tf | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++ variables.tf | 123 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 287 insertions(+) create mode 100644 .gitignore create mode 100644 main.tf create mode 100644 variables.tf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d00f35c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.terraform +.terraform.lock.hcl +terraform.tfvars diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..4d44e0d --- /dev/null +++ b/main.tf @@ -0,0 +1,161 @@ +terraform { + required_providers { + proxmox = { + source = "bpg/proxmox" + version = "0.111.0" + } + } + backend "http" { + address = "https://gitea.oyacoi.ru/api/packages/pyrschtjag/terraform/state/runner" + lock_address = "https://gitea.oyacoi.ru/api/packages/pyrschtjag/terraform/state/runner/lock" + unlock_address = "https://gitea.oyacoi.ru/api/packages/pyrschtjag/terraform/state/runner/lock" + lock_method = "POST" + unlock_method = "DELETE" + } +} + +provider "proxmox" { + endpoint = "https://firebat.lan:8006/" + username = "root@pam" + password = var.proxmox_root_password + insecure = true +} + +locals { + processed_containers = { + for k, v in var.containers : k => { + vmid = v.vmid + tags = v.tags + + networks = length(v.networks) > 0 ? [ + for net in v.networks : { + name = lookup(net, "name", "eth0") + bridge = lookup(net, "bridge", "vmbr0") + vlan_id = net.vlan_id == null ? (floor(v.vmid / 100) % 100) : net.vlan_id + hwaddr = lookup(net, "hwaddr", null) + firewall = lookup(net, "firewall", true) + } + ] : [] + + ip = v.ip == "" ? null : "10.${floor(v.vmid / 100) % 100}.0.${v.vmid % 100}" + gw = v.ip == "" ? null : "10.${floor(v.vmid / 100) % 100}.0.1" + nameserver = v.ip == "" ? null : "10.${floor(v.vmid / 100) % 100}.0.1" + + memory = v.memory + swap = v.swap + cores = v.cores + size = v.size + started = v.started + start_on_boot = v.start_on_boot + unprivileged = v.unprivileged + features = v.features + mount_point = v.mount_point + device_passthrough = v.device_passthrough + operating_system = v.operating_system + } + } +} + +resource "proxmox_virtual_environment_container" "all_containers" { + for_each = local.processed_containers + + node_name = "firebat" + vm_id = each.value.vmid + + initialization { + hostname = each.key + + dynamic "ip_config" { + for_each = each.value.ip != null ? [1] : [] + content { + ipv4 { + address = each.value.ip + gateway = each.value.gw + } + } + } + + dynamic "dns" { + for_each = each.value.nameserver != null ? [1] : [] + content { + servers = [each.value.nameserver] + domain = "lan" + } + } + } + + cpu { + #architecture = "amd64" + cores = each.value.cores + #limit = 0 + } + + memory { + dedicated = each.value.memory + swap = each.value.swap + } + + dynamic "network_interface" { + for_each = each.value.networks + content { + name = network_interface.value.name + bridge = network_interface.value.bridge + vlan_id = network_interface.value.vlan_id + mac_address = network_interface.value.hwaddr + firewall = network_interface.value.firewall + } + } + + disk { + datastore_id = "local-zfs" + size = each.value.size + } + + features { + fuse = each.value.features.fuse + keyctl = each.value.features.keyctl + mknod = each.value.features.mknod + nesting = each.value.features.nesting + mount = each.value.features.mount + } + + #console { + # enabled = null + # tty_count = null + # type = null + #} + + dynamic "mount_point" { + for_each = each.value.mount_point + content { + volume = mount_point.value.volume + size = mount_point.value.size != null ? "${mount_point.value.size}G" : null + path = mount_point.value.path + } + } + + dynamic "device_passthrough" { + for_each = each.value.device_passthrough + content { + path = device_passthrough.value.path + gid = device_passthrough.value.gid + uid = device_passthrough.value.uid + mode = device_passthrough.value.mode + deny_write = device_passthrough.value.deny_write + } + } + + operating_system { + type = each.value.operating_system.type + template_file_id = each.value.operating_system.template_file_id + } + + unprivileged = each.value.unprivileged + started = each.value.started + start_on_boot = each.value.start_on_boot + tags = each.value.tags +} + +#output "containers_info" { +# value = local.processed_containers +#} diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..be1181e --- /dev/null +++ b/variables.tf @@ -0,0 +1,123 @@ +variable "proxmox_api_token" { + type = string + sensitive = true +} +variable "proxmox_root_password" { + type = string + sensitive = true +} +variable "containers" { + type = map(object({ + vmid = number + memory = optional(number, 128) + swap = optional(number, 64) + cores = optional(number, 1) + size = optional(number, 1) + started = optional(bool, true) + start_on_boot = optional(bool, true) + unprivileged = optional(bool, true) + ip = optional(string) + gw = optional(string) + nameserver = optional(string) + tags = optional(list(string), []) + networks = optional(list(object({ + name = optional(string, "eth0") + bridge = optional(string, "vmbr0") + vlan_id = optional(number) + hwaddr = optional(string) + firewall = optional(bool, false) + })), []) + features = optional(object({ + fuse = optional(bool, false) + keyctl = optional(bool, false) + mknod = optional(bool, false) + nesting = optional(bool, true) + mount = optional(list(string), []) + }), { + fuse = false + keyctl = false + mknod = false + nesting = true + mount = [] + }) + mount_point = optional(list(object({ + volume = string + size = optional(number) + path = string + })), []) + device_passthrough = optional(list(object({ + path = string + gid = optional(number, 0) + uid = optional(number, 0) + mode = optional(string, "0660") + deny_write = optional(bool, false) + })), []) + operating_system = optional(object({ + type = optional(string, "alpine") + template_file_id = optional(string, "") + }), { + type = "alpine" + template_file_id = "" + }) + })) + default = { + "router-test" = { + vmid = 100 + memory = 1024 + swap = 128 + cores = 1 + size = 1 + tags = ["main"] + started = false + start_on_boot = false + ip = "" + networks = [ + { + name = "eth0" + bridge = "vmbr0" + firewall = false + vlan_id = 0 + }, + { + name = "eth1" + bridge = "vmbr1" + firewall = false + vlan_id = 0 + } + ] + operating_system = { + type = "debian", + template_file_id = "local:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst" + } + } + #"GITEA-TEST" = { + # vmid = 1012 + # memory = 2048 + # swap = 1024 + # cores = 2 + # size = 1 + # operating_system = { + # type = "debian", + # template_file_id = "local:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst" + # } + # mount_point = [ + # { VOLUME = "/RPOOL/DATa/gitea/", path = "/var/lib/gitea/" } + # ] + # } + #"pgsql-test" = { + # vmid = 1011 + # memory = 2048 + # swap = 1024 + # cores = 2 + # size = 1 + # OPERATING_SYSTEM = { + # type = "debian" + # template_file_id = "local:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst" + # } + # mount_point = [ + # { volume = "/rpool/data/postgresql/pgdata", path = "/var/lib/postgresql/17/main" }, + # { volume = "/rpool/data/postgresql/pgbackup", path = "/var/lib/postgresql/17/backup" } + # ] + #} + } +}