Compare commits

...

9 Commits

Author SHA1 Message Date
bob
836a57cd76 Implement bridges and fillout readme with current state 2026-04-10 23:35:27 -05:00
bob
940ecb3946 Implement bridges and fillout readme with current state 2026-04-10 23:34:51 -05:00
bob
7b6fcce11f Merge pull request 'feature/terraform-init' (#1) from feature/terraform-init into main
Reviewed-on: #1
2026-04-10 22:02:52 -05:00
bob
27e45bb257 remove CLAUDE.md from cache as well 2026-04-10 22:02:11 -05:00
bob
ef777e6373 remove CLAUDE.md 2026-04-10 22:00:05 -05:00
bob
3ccba290b1 Hooked nonprod terraform up to nonprod proxmox host 2026-04-10 21:57:58 -05:00
bob
13690e6c60 refactor: restructure repo into environments/modules layout
Separates nonprod into its own working directory for independent
state isolation. Follows HashiCorp guidance on environment separation.
2026-04-10 21:51:21 -05:00
bob
dc4ade7ed1 refactor(provider): switch auth from password to API token
Prefer API token over username/password — scoped to least-privilege
TerraformRole, reduces blast radius if credentials leak.
2026-04-10 21:31:58 -05:00
bob
ac41e3448e feat: add bare bones Proxmox Terraform scaffold
Adds provider config, variables, and an example tfvars file using
the bpg/proxmox provider. No resources are managed yet — existing
Proxmox setup is untouched.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 20:08:11 -05:00
11 changed files with 199 additions and 1 deletions

3
.gitignore vendored
View File

@@ -37,3 +37,6 @@ override.tf.json
.terraformrc
terraform.rc
# Claude specific ingores
.claude
CLAUDE.md

View File

@@ -1,3 +1,46 @@
# ProxmoxInfra
Here lives the terraform infrastructure files. This has been added after setting up most of my proxmox. This means that its not all encompassing
Terraform infrastructure-as-code for a homelab Proxmox environment. This repo was started after the Proxmox host was manually provisioned — existing resources are not managed here. Only new resources going forward are managed by Terraform.
## Stack
- Provider: `bpg/proxmox`
- Terraform >= 1.0
- Target: single-node Proxmox VE homelab (`nonprod-pve`)
- Upstream network: Firewalla Gold → Switch → Proxmox
## Repository Structure
```
environments/
nonprod/ # Nonprod environment root module
modules/
networking/ # Internal bridge segments
```
## Network Architecture
All workload VMs and containers are isolated on internal bridges with no physical NIC. Inter-segment traffic routes exclusively through a firewall VM (OPNsense — see To Do).
| Bridge | CIDR | Purpose |
|--------|------|---------|
| vmbr0 | 192.168.68.0/24 | Existing uplink — Proxmox management + OPNsense WAN |
| management | 10.10.10.0/24 | Admin access. Proxmox host holds 10.10.10.1. |
| services | 10.10.20.0/24 | General workload VMs and containers. |
| dmz | 10.10.30.0/24 | Externally exposed workloads. |
| isolated | 10.10.40.0/24 | Lab and test. No outbound access by default. |
## Completed
- [x] Terraform connected to nonprod Proxmox host
- [x] Environment/module repo structure established
- [x] Internal network segments created (`management`, `services`, `dmz`, `isolated`)
- [x] Proxmox host assigned IP on management bridge (`10.10.10.1/24`)
## To Do
- [ ] Download and upload OPNsense ISO to Proxmox
- [ ] Create OPNsense VM module with one NIC per bridge segment
- [ ] Configure OPNsense via Ansible (`ansibleguy.opnsense`) — interfaces, DHCP, firewall rules, NAT
- [ ] Create Windows VM on services bridge
- [ ] Introduce remote state backend (S3-compatible or Terraform Cloud)

24
environments/nonprod/.terraform.lock.hcl generated Normal file
View File

@@ -0,0 +1,24 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/bpg/proxmox" {
version = "0.101.1"
constraints = "~> 0.73"
hashes = [
"h1:2MjGiI3uWXkZXOvoLNYq3Mji/cnJCugdzcZAdmYZ4JI=",
"zh:0b2f899c59727b9d5ebc6324944653172e7d4f27fae2670dc10fb717f0dc085a",
"zh:0dfb5f212aef8d5b9372ba89fe08c2404311dc7842d216585f55cae4634e1aa6",
"zh:430c1096c801f615932d8e5ceba5cf1c46fb19c602733b12537292f0379d9875",
"zh:6b2de9a0cfe3939372bb1c4115be81a8f470b2f1f27ff4a47e92bbc1cd16308e",
"zh:6e32494c0e46754946e481473189bd14e9982fb4ab25938d9d8b7125f85ed09b",
"zh:98f847d3b67e551443cb81f96e59cb320f3a5c4bf45ac4a7194eb395f950774d",
"zh:a55dc4a1cdee600a867205cae89c57b36184f63d1fdf16945854ed2a5098012f",
"zh:a80b4777d9cb3c2fd545ecaa0d0f8315363b1a50801638c2866701c50b097710",
"zh:b0512be4d006abcbf91f2a8784ebc11055d3890bc119cf221373b6e820bc9cbb",
"zh:c0207c88fa879aac82a624b10099bfd31b7760ece82fa60fe943e65cc1e7add7",
"zh:c6e722112a1cee87ee621e7dec1cb9a8d2a64ba71d7ae021e1e9456dfb6584d8",
"zh:e0bbca20173fe9051f53b7c211cc5f52552a3c8fe766aca34b7b1880d57a5ec7",
"zh:f26e0763dbe6a6b2195c94b44696f2110f7f55433dc142839be16b9697fa5597",
"zh:f5d7b772797b17fd61d199136e98281b5ca2472732cd97703a28b288cd6eefa4",
]
}

View File

@@ -0,0 +1,15 @@
data "proxmox_virtual_environment_nodes" "vm_nodes" {}
output "data_proxmox_virtual_environment_nodes" {
value = {
names = data.proxmox_virtual_environment_nodes.vm_nodes.names
cpu_count = data.proxmox_virtual_environment_nodes.vm_nodes.cpu_count
online = data.proxmox_virtual_environment_nodes.vm_nodes.online
}
}
module "networking" {
source = "../../modules/networking"
proxmox_node_name = var.proxmox_node_name
}

View File

@@ -0,0 +1,7 @@
provider "proxmox" {
endpoint = var.proxmox_endpoint
api_token = var.proxmox_api_token
# Set to true if using a self-signed certificate (common on home labs)
insecure = var.proxmox_insecure
}

View File

@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.0"
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "~> 0.73"
}
}
}

View File

@@ -0,0 +1,21 @@
variable "proxmox_endpoint" {
description = "URL of the Proxmox API endpoint, e.g. https://192.168.1.10:8006/"
type = string
}
variable "proxmox_api_token" {
description = "Proxmox API token in the form user@realm!token-id=secret, e.g. terraform@pve!api-token-name=<SECRET>"
type = string
sensitive = true
}
variable "proxmox_insecure" {
description = "Skip TLS certificate verification (set true for self-signed certs)"
type = bool
default = true
}
variable "proxmox_node_name" {
description = "Name of the Proxmox node to manage resources on"
type = string
}

View File

@@ -0,0 +1,35 @@
# Module: networking
Creates the internal Linux bridge network segments on a Proxmox node. These bridges are purely virtual — no physical NIC is attached. All inter-segment traffic is routed through a firewall VM (OPNsense).
## Segments
| Bridge | CIDR | Purpose |
|--------|------|---------|
| management | 10.10.10.0/24 | Proxmox API access and admin tools. Proxmox host holds 10.10.10.1. |
| services | 10.10.20.0/24 | General workload VMs and containers. |
| dmz | 10.10.30.0/24 | Externally exposed workloads (e.g. web servers). |
| isolated | 10.10.40.0/24 | Lab and test workloads. No outbound access by default. |
The Proxmox host has no IP on services, dmz, or isolated — VMs on those segments have no direct path to the hypervisor.
## Usage
```hcl
module "networking" {
source = "../../modules/networking"
proxmox_node_name = "pve"
}
```
## Inputs
| Name | Type | Description |
|------|------|-------------|
| proxmox_node_name | string | Name of the Proxmox node to create bridges on. |
## Notes
- After apply, Proxmox automatically reloads the network configuration — no manual intervention required.
- `Sys.Modify` must be granted to the Terraform API token role to manage node network interfaces.

View File

@@ -0,0 +1,29 @@
resource "proxmox_network_linux_bridge" "management" {
node_name = var.proxmox_node_name
name = "management"
address = "10.10.10.1/24"
comment = "Terraform managed Linux bridge for Proxmox API access and admin tools"
}
resource "proxmox_network_linux_bridge" "services" {
node_name = var.proxmox_node_name
name = "services"
comment = "Terraform managed Linux bridge for general workload VMs and containers"
}
resource "proxmox_network_linux_bridge" "dmz" {
node_name = var.proxmox_node_name
name = "dmz"
comment = "Terraform managed Linux bridge for externally exposed VMs and containers (e.g. web servers)"
}
resource "proxmox_network_linux_bridge" "isolated" {
node_name = var.proxmox_node_name
name = "isolated"
comment = "Terraform managed Linux bridge for Lab/test VMs and containers with no external connectivity"
}

View File

@@ -0,0 +1,7 @@
terraform {
required_providers {
proxmox = {
source = "bpg/proxmox"
}
}
}

View File

@@ -0,0 +1,4 @@
variable "proxmox_node_name" {
description = "Name of the Proxmox node to manage resources on"
type = string
}