infra: introduce terraform/opentofu for proxmox management

- move ansible project within infra
- introduce terraform/opentofu for proxmox VM management
This commit is contained in:
2025-06-30 19:16:14 +03:00
parent a79de74a6a
commit 03c882f311
24 changed files with 882 additions and 0 deletions

5
infra/terraform/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.env
.terraform/
.terraform.lock.hcl
terraform.tfstate
terraform.tfstate.backup

25
infra/terraform/README.md Normal file
View File

@ -0,0 +1,25 @@
# Terraform Configuration
> This project uses OpenTofu instead of Terraform. OpenTofu is a fork of
> Terraform that is compatible with Terraform configurations and provides
> similar functionality.
This directory contains Terraform configurations for managing
infrastructure resources. It includes configurations for Proxmox.
The plan is to eventually migrate all infrastructure management to Terraform,
including Kubernetes clusters and other resources. Currently, the Proxmox
configuration is fully managed by Terraform, while Kubernetes resources are
managed using Helm charts and kubectl commands. Previously, the Proxmox
configuration was managed using Ansible, but it has been migrated to Terraform
for better consistency and state management.
The terraform state files are stored in a remote backend, which allows for
collaboration and state management across different environments. The backend
configuration is defined in the `backend.tf` file. The backend is set up to use
minio as the storage backend.
## Proxmox
The Proxmox configuration is located in the `proxmox` directory.
It uses the Proxmox provider to manage virtual machines and other resources.

View File

@ -0,0 +1,14 @@
terraform {
backend "s3" {
bucket = "terraform-state" # Name of the MinIO bucket
key = "proxmox/terraform.tfstate" # Path to the state file in the bucket
endpoint = var.minio_endpoint # MinIO API endpoint
access_key = var.minio_access_key # MinIO access key
secret_key = var.minio_secret_key # MinIO secret key
region = "us-east-1" # Arbitrary region (MinIO ignores this)
skip_credentials_validation = true # Skip AWS-specific credential checks
skip_metadata_api_check = true # Skip AWS metadata API checks
skip_region_validation = true # Skip AWS region validation
use_path_style = true # Use path-style URLs[](http://<host>/<bucket>)
}
}

View File

@ -0,0 +1,95 @@
terraform {
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "0.78.2"
}
}
}
provider "proxmox" {
endpoint = var.pm_api_url
api_token = var.pm_api_token
insecure = var.pm_insecure
ssh {
agent = false
username = var.pm_user
private_key = file(var.pm_ssh_private_key_path)
}
}
data "local_file" "ssh_public_key" {
filename = var.pm_ssh_public_key_path
}
resource "proxmox_virtual_environment_vm" "ubuntu_vm" {
for_each = { for vm in var.vms : vm.name => vm }
name = each.value.name
node_name = each.value.node_name
vm_id = each.value.vm_id
stop_on_destroy = true
keyboard_layout = "fi"
initialization {
ip_config {
ipv4 {
address = each.value.ip_address
gateway = each.value.gateway
}
}
dns {
servers = each.value.dns_servers
}
datastore_id = "local"
user_account {
username = var.vm_user_name
password = var.vm_user_password
keys = [trimspace(data.local_file.ssh_public_key.content)]
}
}
cpu {
cores = each.value.cores
sockets = 1
}
memory {
dedicated = each.value.memory
}
disk {
datastore_id = "local"
file_id = proxmox_virtual_environment_download_file.ubuntu_cloud_image[each.value.node_name].id
interface = "virtio0"
iothread = true
discard = "on"
size = each.value.disk_size
}
network_device {
bridge = "vmbr0"
}
depends_on = [proxmox_virtual_environment_download_file.ubuntu_cloud_image]
}
resource "proxmox_virtual_environment_download_file" "ubuntu_cloud_image" {
for_each = toset(var.nodes)
content_type = "iso"
datastore_id = "local"
node_name = each.key
url = "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img"
}
data "proxmox_virtual_environment_hosts" "hosts" {
for_each = toset(var.nodes)
node_name = each.key
depends_on = [proxmox_virtual_environment_vm.ubuntu_vm]
}

View File

@ -0,0 +1,52 @@
# Proxmox configuration =
pm_ssh_public_key_path = "/home/taqi/.ssh/homeserver.pub"
pm_ssh_private_key_path = "/home/taqi/.ssh/homeserver"
vms = [
{
name = "vm6"
node_name = "homeserver1"
vm_id = 105
ip_address = "192.168.1.151/24"
gateway = "192.168.1.1"
dns_servers = ["192.168.1.145", "1.1.1.1"]
cores = 2
memory = 2048
disk_size = 20
},
{
name = "vm7"
node_name = "homeserver1"
vm_id = 106
ip_address = "192.168.1.152/24"
gateway = "192.168.1.1"
dns_servers = ["192.168.1.145", "1.1.1.1"]
cores = 2
memory = 2048
disk_size = 20
},
{
name = "vm8"
node_name = "homeserver2"
vm_id = 205
ip_address = "192.168.1.161/24"
gateway = "192.168.1.1"
dns_servers = ["192.168.1.145", "1.1.1.1"]
cores = 2
memory = 2048
disk_size = 20
},
{
name = "vm9"
node_name = "homeserver2"
vm_id = 206
ip_address = "192.168.1.162/24"
gateway = "192.168.1.1"
dns_servers = ["192.168.1.145", "1.1.1.1"]
cores = 2
memory = 2048
disk_size = 20
}
]
nodes = ["homeserver1", "homeserver2"]

View File

@ -0,0 +1,81 @@
# variables for minio backend configuration
variable "minio_access_key" {
description = "MinIO access key"
type = string
}
variable "minio_secret_key" {
description = "MinIO secret key"
type = string
}
variable "minio_endpoint" {
description = "MinIO API endpoint"
type = string
}
# Variables for Proxmox configuration
variable "pm_api_url" {
description = "Proxmox API URL"
type = string
sensitive = true
}
variable "pm_api_token" {
description = "Proxmox password"
type = string
sensitive = true
}
variable "pm_insecure" {
description = "Allow insecure connections to Proxmox API"
type = bool
default = true
}
variable "pm_user" {
description = "Proxmox user"
type = string
sensitive = true
}
variable "pm_ssh_public_key_path" {
description = "Path to SSH public key file"
type = string
}
variable "pm_ssh_private_key_path" {
description = "Path to SSH private key file"
type = string
}
variable "vms" {
description = "List of VMs to create"
type = list(object({
name = string
node_name = string
vm_id = number
ip_address = string
dns_servers = list(string)
gateway = string
cores = number
memory = number
disk_size = number
}))
}
variable "nodes" {
type = list(string)
default = ["homeserver1", "homeserver2"]
}
variable "vm_user_name" {
description = "Username for the VM"
type = string
}
variable "vm_user_password" {
description = "Password for the VM user"
type = string
sensitive = true
}