No description
- Just 43.8%
- HCL 29.1%
- Jinja 21.3%
- Shell 5.8%
|
Some checks failed
Infrastructure / terraform (push) Failing after 12m54s
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> |
||
|---|---|---|
| .forgejo/workflows | ||
| .githooks | ||
| iac | ||
| playbooks | ||
| scripts | ||
| specs | ||
| .gitignore | ||
| CLAUDE.md | ||
| Justfile | ||
| README.md | ||
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
- Add resource in
iac/containers.tf - Add variables in
iac/variables.tf - Add values in tfvars and tfvars.example
- Create
scripts/setup-<name>.sh - Add setup call in infra.yml
- 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/