initial upload

This commit is contained in:
Ubuntu
2026-01-08 19:41:23 +00:00
commit ae4f1ad1cc
42 changed files with 1371 additions and 0 deletions

5
terraform/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# Terraform
.terraform/
.terraform.lock.hcl
terraform.tfstate*
terraform.tfvars

16
terraform/data.tf Normal file
View File

@@ -0,0 +1,16 @@
# Expects secrets at specific paths in Vault KV v2 (mount point 'secret/')
data "vault_generic_secret" "proxmox" {
count = var.use_vault ? 1 : 0
path = "secret/infrastructure/proxmox"
}
data "vault_generic_secret" "opnsense" {
count = var.use_vault ? 1 : 0
path = "secret/infrastructure/opnsense"
}
data "vault_generic_secret" "vm_creds" {
count = var.use_vault ? 1 : 0
path = "secret/infrastructure/vm-credentials"
}

25
terraform/locals.tf Normal file
View File

@@ -0,0 +1,25 @@
locals {
# SSH Public Key for Provisioning
ssh_key = var.use_vault ? data.vault_generic_secret.vm_creds[0].data["ssh_public_key"] : var.ssh_public_key
# CI Credentials
ci_user = var.use_vault ? data.vault_generic_secret.vm_creds[0].data["ci_user"] : var.ci_user
ci_password = var.use_vault ? data.vault_generic_secret.vm_creds[0].data["ci_password"] : var.ci_password
vms = {
# VLAN 30: Docker
"vm-docker-mailcow-300" = { id = 300, cores = 4, memory = 8192, vlan = 30, tags = "docker,mailcow", ip = "10.100.30.10", gw = "10.100.30.1" }
"vm-docker-apps-301" = { id = 301, cores = 2, memory = 4096, vlan = 30, tags = "docker,apps", ip = "10.100.30.11", gw = "10.100.30.1" }
"vm-docker-traefik-302" = { id = 302, cores = 1, memory = 2048, vlan = 30, tags = "docker,ingress", ip = "10.100.30.12", gw = "10.100.30.1" }
# VLAN 40: K3s
"vm-k3s-master-400" = { id = 400, cores = 2, memory = 4096, vlan = 40, tags = "k3s,master", ip = "10.100.40.10", gw = "10.100.40.1" }
"vm-k3s-worker-401" = { id = 401, cores = 2, memory = 4096, vlan = 40, tags = "k3s,worker", ip = "10.100.40.11", gw = "10.100.40.1" }
"vm-k3s-worker-402" = { id = 402, cores = 2, memory = 4096, vlan = 40, tags = "k3s,worker", ip = "10.100.40.12", gw = "10.100.40.1" }
"vm-k3s-worker-403" = { id = 403, cores = 2, memory = 4096, vlan = 40, tags = "k3s,worker", ip = "10.100.40.13", gw = "10.100.40.1" }
# VLAN 90: Bastion
"vm-bastion-900" = { id = 900, cores = 1, memory = 2048, vlan = 90, tags = "bastion", ip = "10.100.90.10", gw = "10.100.90.1" }
"vm-bastion-901" = { id = 901, cores = 1, memory = 2048, vlan = 90, tags = "bastion", ip = "10.100.90.11", gw = "10.100.90.1" }
}
}

79
terraform/main.tf Normal file
View File

@@ -0,0 +1,79 @@
resource "proxmox_vm_qemu" "vm_deployment" {
for_each = local.vms
target_node = var.pm_node
name = "${each.key}.stabify.de"
vmid = each.value.id
description = "Managed by Terraform. VLAN: ${each.value.vlan} Role: ${each.value.tags} IP: ${each.value.ip}"
clone = var.template_name
full_clone = true
agent = 1
start_at_node_boot = true
define_connection_info = false
cpu {
cores = each.value.cores
sockets = 1
}
memory = each.value.memory
balloon = 0
scsihw = "virtio-scsi-pci"
boot = "order=scsi0;net0"
serial {
id = 0
type = "socket"
}
disk {
slot = "scsi0"
size = "32G"
type = "disk"
storage = "local-lvm"
iothread = true
}
disk {
slot = "ide2"
type = "cloudinit"
storage = "local-lvm"
}
network {
id = 0
model = "virtio"
bridge = "vmbr1"
tag = each.value.vlan
}
os_type = "cloud-init"
searchdomain = "stabify.de"
nameserver = each.value.gw
ciuser = local.ci_user
cipassword = local.ci_password
sshkeys = local.ssh_key
ipconfig0 = "ip=${each.value.ip}/24,gw=${each.value.gw}"
tags = each.value.tags
lifecycle {
ignore_changes = [ network ]
}
}
resource "opnsense_unbound_host_override" "dns_entries" {
for_each = local.vms
enabled = true
hostname = each.key
domain = "stabify.de"
description = "Managed by Terraform: ${each.value.tags}"
server = each.value.ip
}

20
terraform/providers.tf Normal file
View File

@@ -0,0 +1,20 @@
provider "vault" {
# Configuration via VAULT_ADDR and VAULT_TOKEN env vars
}
provider "proxmox" {
pm_tls_insecure = true
pm_api_url = var.proxmox_api_url
# Logic: If use_vault is true, verify vault data exists, otherwise use vars
pm_api_token_id = var.use_vault ? data.vault_generic_secret.proxmox[0].data["api_token_id"] : var.proxmox_api_token_id
pm_api_token_secret = var.use_vault ? data.vault_generic_secret.proxmox[0].data["api_token_secret"] : var.proxmox_api_token_secret
}
provider "opnsense" {
uri = var.use_vault ? data.vault_generic_secret.opnsense[0].data["uri"] : var.opnsense_uri
allow_insecure = true
api_key = var.use_vault ? data.vault_generic_secret.opnsense[0].data["api_key"] : var.opnsense_api_key
api_secret = var.use_vault ? data.vault_generic_secret.opnsense[0].data["api_secret"] : var.opnsense_api_secret
}

67
terraform/variables.tf Normal file
View File

@@ -0,0 +1,67 @@
variable "use_vault" {
type = bool
default = true
description = "Set to false to bypass Vault and use local variables (Bootstrap Mode)"
}
variable "proxmox_api_token_id" {
type = string
sensitive = true
default = null
}
variable "proxmox_api_token_secret" {
type = string
sensitive = true
default = null
}
variable "opnsense_api_key" {
type = string
sensitive = true
default = null
}
variable "opnsense_api_secret" {
type = string
sensitive = true
default = null
}
variable "ci_user" {
type = string
default = null
}
variable "ci_password" {
type = string
sensitive = true
default = null
}
variable "ssh_public_key" {
type = string
default = null
}
variable "proxmox_api_url" {
type = string
default = "https://10.100.0.2:8006/api2/json"
}
variable "pm_node" {
type = string
default = "hzfsn-pve-01"
}
variable "template_name" {
type = string
default = "ubuntu-2404-ci"
description = "Name des Cloud-Init Templates auf dem Node"
}
variable "opnsense_uri" {
type = string
description = "URI to OPNsense API"
default = null
}

26
terraform/versions.tf Normal file
View File

@@ -0,0 +1,26 @@
terraform {
required_version = ">= 1.5.0"
# Enterprise: Remote State Management (Placeholder)
# backend "s3" {
# bucket = "terraform-state"
# key = "prod/infrastructure.tfstate"
# region = "eu-central-1"
# }
required_providers {
proxmox = {
source = "telmate/proxmox"
version = "3.0.2-rc07" # Pinned as requested
}
opnsense = {
source = "browningluke/opnsense"
version = "0.16.1"
}
vault = {
source = "hashicorp/vault"
version = "~> 3.24.0"
}
}
}