No description
  • Just 43.8%
  • HCL 29.1%
  • Jinja 21.3%
  • Shell 5.8%
Find a file
Charles Jacquin 8b95481e88
Some checks failed
Infrastructure / terraform (push) Failing after 12m54s
fix: just destroy also removes tfvars for clean regeneration
Without this, just init skips tfvars generation (file exists)
and Terraform prompts for variables added since the last init.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 15:37:36 +02:00
.forgejo/workflows feat: CI and just init now use Ansible (Phase 4 & 5) 2026-03-29 23:36:20 +02:00
.githooks feat: add git hooks with qa and conventional commit validation 2026-03-23 16:54:57 +01:00
iac feat: add mail server container with LDAP-backed email 2026-03-30 15:10:08 +02:00
playbooks feat: add mail server container with LDAP-backed email 2026-03-30 15:10:08 +02:00
scripts chore: remove shell setup scripts, replaced by Ansible 2026-03-30 01:12:45 +02:00
specs docs: add AdGuard Home to migration specs with forward auth 2026-03-28 04:30:02 +01:00
.gitignore feat: add Caddy, Authelia, LLDAP containers (phase 0) 2026-03-28 18:46:45 +01:00
CLAUDE.md feat: add just install-deps for dev tool setup 2026-03-28 17:34:04 +01:00
Justfile fix: just destroy also removes tfvars for clean regeneration 2026-03-30 15:37:36 +02:00
README.md feat: add just install-deps for dev tool setup 2026-03-28 17:34:04 +01:00

Proxmox Infrastructure as Code

Terraform-managed infrastructure for a self-hosted Proxmox homelab. One command to bootstrap, then CI handles everything.

Infrastructure

                     ┌──────────────────────────┐
                     │   Proxmox Host (.79)      │
                     │                           │
┌────────────┐       │ ┌───────────────────────┐ │
│ just init  │──────►│ │ VM 200 forgejo        │ │
│ (once)     │       │ │ Ubuntu / Docker        │ │
└────────────┘       │ │ Forgejo server+runner  │ │
                     │ └───────────────────────┘ │
┌────────────┐       │        │                  │
│ git push   │──CI──►│        ▼                  │
│forgejo main│       │ ┌───────┐┌──────┐┌─────┐ │
└────────────┘       │ │CT 210 ││CT 220││CT230│ │
                     │ │Postgre││AdGuar││Redis│ │
  *.app.internal     │ │:5432  ││:53   ││:6379│ │
  ┌─────────────────►│ └───────┘└──────┘└─────┘ │
  │  DNS             │                           │
  │                  │ ┌───────────────────────┐ │
  │                  │ │ VM 100 YunoHost       │ │
  │                  │ │ Reverse proxy + SSO   │ │
  │                  │ └───────────────────────┘ │
  │                  └───────────────────────────┘
  │
┌─┴────────┐
│ LAN      │
│ clients  │
└──────────┘

Services

ID Name Role IP
200 forgejo Forgejo + CI runner 192.168.1.200
210 postgres Shared PostgreSQL 15 192.168.1.210
220 adguard AdGuard Home (DNS) 192.168.1.220
230 valkey Redis 7 (valkey) 192.168.1.230
100 YunoHost Reverse proxy, SSO 192.168.1.100

Internal domains

Domain Resolves to
*.app.internal 192.168.1.100 (YunoHost)
pve.internal 192.168.1.79 (Proxmox UI)
postgres.internal 192.168.1.210
dns.internal 192.168.1.220
valkey.internal 192.168.1.230

Workflow

edit .tf ──► git push forgejo main ──► CI ──► done

Prerequisites

  • just (task runner)
  • SSH access to the Proxmox host

All other tools (terraform, shellcheck, yamlfmt, rumdl) can be installed with just install-deps.

Getting started

# 1. Clone
git clone <repo-url>
cd proxmox-iac

# 2. Install development tools
just install-deps

# 3. Add SSH key to Proxmox host
ssh-copy-id root@192.168.1.79

# 4. Bootstrap everything
just init

# 5. Push to deploy
git push forgejo main

After this, CI handles everything. Edit, commit, push.

Commands

just install-deps           # Install dev tools
just init                   # Full bootstrap (once)
just init -y                # Bootstrap, all defaults
just ssh postgres           # SSH into a container
just status                 # Check all containers
just logs valkey            # View service logs
just create-db myapp s3cret # Create app database

CI pipelines

infra.yml (automatic on push to main)

Runs terraform apply and provisions new containers. State is stored in Forgejo generic packages. If a container's setup script fails, the container is destroyed and will be recreated on next push.

bind-domain.yml (manual trigger)

Binds a domain to an app via YunoHost reverse proxy. Inputs: domain, IP, port, auth mode.

unbind-domain.yml (manual trigger)

Removes a domain binding from YunoHost.

Adding a new container

  1. Add resource in iac/containers.tf
  2. Add variables in iac/variables.tf
  3. Add values in tfvars and tfvars.example
  4. Create scripts/setup-<name>.sh
  5. Add setup call in infra.yml
  6. Push

Creating an app database

just create-db myapp "$(openssl rand -base64 24)"
# postgresql://myapp:****@192.168.1.210:5432/myapp

Project structure

.
├── iac/
│   ├── main.tf               # Provider, shared
│   ├── forgejo.tf             # Forgejo VM
│   ├── containers.tf          # LXC containers
│   ├── variables.tf           # Variable definitions
│   ├── terraform.tfvars.example
│   └── cloud-init.yml.tftpl   # Forgejo cloud-init
├── scripts/
│   ├── setup-postgres.sh
│   ├── setup-dnsmasq.sh
│   └── setup-valkey.sh
├── .forgejo/workflows/
│   ├── infra.yml              # CI: terraform
│   ├── bind-domain.yml        # CI: domain binding
│   └── unbind-domain.yml      # CI: domain removal
├── .githooks/
│   ├── pre-commit
│   └── commit-msg
├── Justfile
└── specs/