docs: add Proxmox setup guide for Terraform (#2)

## Summary

Add Proxmox setup documentation for Terraform with dedicated role and minimal privileges.

## Changes

- Add `docs/proxmox-setup.md` with complete setup guide
- Dedicated `TerraformRole` (no Administrator role needed)
- Both Web UI and CLI procedures
- SSH configuration for bpg/proxmox provider

## Privileges (Proxmox 9.1)

| Category  | Privileges |
|-----------|------------|
| Datastore | `Allocate`, `AllocateSpace`, `AllocateTemplate`, `Audit` |
| System    | `Audit`, `Console`, `Modify` |
| VM        | `Allocate`, `Audit`, `Clone`, `Config.*`, `Console`, `Migrate`, `PowerMgmt`, `Snapshot`, `Snapshot.Rollback`, `GuestAgent.Audit`, `GuestAgent.FileRead` |
| Pool      | `Allocate`, `Audit` |
| SDN       | `Use` |

> ⚠️ `VM.Monitor` deprecated in Proxmox 9 — use `VM.GuestAgent.Audit` and `VM.GuestAgent.FileRead` instead.

## Related

Closes #1

Co-authored-by: darnodo <sepales.pret0h@icloud.com>
Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
2025-12-07 13:08:16 +00:00
parent 531a05a173
commit 90232da467
4 changed files with 172 additions and 19 deletions

153
docs/proxmox-setup.md Normal file
View File

@@ -0,0 +1,153 @@
# Proxmox Setup for Terraform
Configuration guide for the `bpg/proxmox` Terraform provider on Proxmox VE 9.1.
> Related issue: [#1 - Proxmox 9.1 upgrade: Terraform API user disabled](https://gitea.arnodo.fr/Damien/iac-homelab/issues/1)
## Overview
Instead of using the `Administrator` role, we create a dedicated `TerraformRole` with minimal required privileges.
## Required Privileges (Proxmox 9.1)
| Category | Privileges |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Datastore | `Allocate`, `AllocateSpace`, `AllocateTemplate`, `Audit` |
| System | `Audit`, `Console`, `Modify` |
| VM | `Allocate`, `Audit`, `Clone`, `Config.*`, `Console`, `Migrate`, `PowerMgmt`, `Snapshot`, `Snapshot.Rollback`,`GuestAgent.Audit`, `GuestAgent.FileRead` |
| Pool | `Allocate`, `Audit` |
| SDN | `Use` |
> ⚠️ `VM.Monitor` was deprecated in Proxmox 9 — do not include it.
---
## Option A: Web Interface
### 1. Create Role
**Datacenter → Permissions → Roles → Create**
- **Name**: `TerraformRole`
- **Privileges**: Select all from the table above
### 2. Create User
**Datacenter → Permissions → Users → Add**
| Field | Value |
| --------- | ---------------------------------- |
| User name | `terraform` |
| Realm | `Proxmox VE authentication server` |
| Password | *(set a strong password)* |
| Enabled | ☑️ |
| Expire | `never` |
### 3. Create API Token
**Datacenter → Permissions → API Tokens → Add**
| Field | Value |
| -------------------- | ----------------- |
| User | `terraform@pve` |
| Token ID | `terraform_token` |
| Privilege Separation | ☐ *(unchecked)* |
| Expire | `never` |
> 📋 **Save the token secret** — it won't be shown again!
### 4. Assign Permissions
**Datacenter → Permissions → Add → User Permission**
| Field | Value |
| --------- | --------------- |
| Path | `/` |
| User | `terraform@pve` |
| Role | `TerraformRole` |
| Propagate | ☑️ |
---
## Option B: CLI
```bash
# 1. Create role
pveum role add TerraformRole -privs "Datastore.Allocate,Datastore.AllocateSpace,Datastore.AllocateTemplate,Datastore.Audit,Pool.Allocate,Pool.Audit,SDN.Use,Sys.Audit,Sys.Console,Sys.Modify,VM.Allocate,VM.Audit,VM.Clone,VM.Config.CDROM,VM.Config.Cloudinit,VM.Config.CPU,VM.Config.Disk,VM.Config.HWType,VM.Config.Memory,VM.Config.Network,VM.Config.Options,VM.Console,VM.Migrate,VM.PowerMgmt,VM.Snapshot,VM.Snapshot.Rollback,VM.GuestAgent.Audit,VM.GuestAgent.FileRead"
# 2. Create user
pveum user add terraform@pve --comment "Terraform automation"
# 3. Create API token (save the output!)
pveum user token add terraform@pve terraform_token --privsep 0
# 4. Assign permissions
pveum acl modify / --user terraform@pve --role TerraformRole
```
---
## SSH Access (Required)
The `bpg/proxmox` provider uses SSH to upload cloud-init files.
```bash
# Create system user
useradd -m -s /bin/bash terraform
# Configure passwordless sudo
echo 'terraform ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/terraform
chmod 440 /etc/sudoers.d/terraform
# Setup SSH key
mkdir -p /home/terraform/.ssh
echo "YOUR_PUBLIC_KEY" > /home/terraform/.ssh/authorized_keys
chmod 700 /home/terraform/.ssh
chmod 600 /home/terraform/.ssh/authorized_keys
chown -R terraform:terraform /home/terraform/.ssh
```
---
## Terraform Configuration
```hcl
provider "proxmox" {
endpoint = "https://pve01.example.com:8006"
api_token = "terraform@pve!terraform_token=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
insecure = true
ssh {
agent = true
username = "terraform"
}
}
```
Or use environment variables:
```bash
export PROXMOX_VE_ENDPOINT="https://pve01.example.com:8006"
export PROXMOX_VE_API_TOKEN="terraform@pve!terraform_token=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
```
---
## Verification
```bash
# Test API token
curl -k -H "Authorization: PVEAPIToken=terraform@pve!terraform_token=YOUR_SECRET" \
https://pve01.example.com:8006/api2/json/version
# Test Terraform
terraform init && terraform plan
```
---
## References
- [bpg/proxmox provider](https://github.com/bpg/terraform-provider-proxmox)
- [Proxmox User Management](https://pve.proxmox.com/wiki/User_Management)
- [Proxmox API](https://pve.proxmox.com/wiki/Proxmox_VE_API)

View File

@@ -2,23 +2,23 @@
# Manual edits may be lost in future updates.
provider "registry.terraform.io/bpg/proxmox" {
version = "0.43.0"
constraints = "0.43.0"
version = "0.89.0"
hashes = [
"h1:T1KwNv9zR6q+UTTa7cXa6qAsV1IR4YEkrCpZkM5xAdo=",
"zh:15be827515be0e5fee5128a82f294a9eba9b1dde22a203dc40f6d604832cf5e6",
"zh:1afbe8d25ad1acff6e01f0746df204e43d9841603bc68c47efbd78acb94d09e6",
"zh:1c3873fb2eee657c6acc035b52fd1fea1b8d8173651ae59d9dbd809d9586d5c7",
"zh:2a6f20b2e12b583b9cc53e3e9304a542da8ddb2ac1ba0c4eaf7963702e6d127c",
"zh:3c5fda4aac500ca49c9c33f5de08c9f5abe89106eb7e1546543678d83c189a8b",
"zh:7fb4de0b5fb2cfd57071675c0e118268eff04b2fda73e7f48251b93e1810b83a",
"zh:8fdec222b07106e011722163e1bd6b69bce866a63a1be55b724da8c271f62405",
"zh:900b297a21bdb2bf55e247e2a69e55563cf31f8ff189c2134612c7a5aedea970",
"zh:a24713eace6ba6ae0d19429c083b6bb2d88421d476819df62ccd9e0bb646410f",
"zh:b3267ca029946881b367baa579d49751e0f04f42f5cca1bbab34d02dad844bcd",
"zh:c5bf667aa91cd3fa17b3ef3f3020bd5984996eccc554c28990b5aba70bce4717",
"zh:db3cfe28bd077012804c3cb255771b8c13ffe37e6ffe9c7730ee3192ad974c93",
"zh:f11feed213e61cac4e00f568a6fdcee7eef9a4e3a28b605e7e0419ab36ccee49",
"zh:ff79ccc3535cce0aa00e77f2c3979ef492b9aa611aee643aadb104cffd591c46",
"h1:K+x0TE7ly2q7E8F1p+1HdBdW7Dpu7/y7KtzHVwUnlaU=",
"zh:0ac841733348a529a53552fbca2ec1c2a3765cab9a27c224c11f49ca0282f38e",
"zh:11fc498398efefe246ea7b9efd9a3a8cde875837875e8f15c89e501285f975aa",
"zh:2a4e9d5bd70112628b065c3f987bedb0d71ab1fa67f2e6c9589fd0f268fa81fa",
"zh:40fe200d655034c409b4dbb44f7999f3fef8bf82204b1c2faaba5fb3b9ed033d",
"zh:5a839039660c501b4b849d161734d663b7cae3efa4c8a301e73c8d1ae127b384",
"zh:7f8987ad04f2f6c1d2fb20ec1fe4391cf671d069dc310f9430cd707d2af8b235",
"zh:8c32f27e0da716116f65c1013c520d63074db07548c32732fd296a31587d17c4",
"zh:9384b2f2d899cf44662ffacbdf6bc268fecb9291755a633957a3413f109bdee6",
"zh:a62920cdfcd6f6a3af1887ba8159648b71a689a8109d4ce6506d90db6ba506db",
"zh:db864d419becc2a541f5db5df5d8325057e8e11ca2cd97d884507c5667466b46",
"zh:dc6072f36559444744a5ce551ac8b8ed160f8d8d0677eb9b740128cde8adb57a",
"zh:e23933741de78132b22ad356b2e81108a2d8322a29804702bc4a6c214843937d",
"zh:ea937465c1c757fd520e9a61eae749b20106a34d99dbe678d884b6b2fa763145",
"zh:ef3ae28ba0449c61f951ea11fe53626e7d32bcee2dcbf25ab47b7cc5b8fe2f32",
"zh:f26e0763dbe6a6b2195c94b44696f2110f7f55433dc142839be16b9697fa5597",
]
}

View File

@@ -10,7 +10,7 @@ terraform {
required_providers {
proxmox = {
source = "bpg/proxmox"
version = "0.43.0"
version = "0.89.0"
}
}
}

View File

@@ -59,7 +59,7 @@ variable "virtual_machines" {
disk_format = optional(string, "raw")
network_bridge = optional(string, "vmbr0")
network_model = optional(string, "virtio")
username = optional(string)
username = optional(string, "damien")
on_boot = optional(bool, true)
tags = optional(list(string), [])