homelab/terraform/proxmox-examples/docker-host/README.md
Claude cce203ed62
feat: Add service template, backup solution, dashboard, and IaC tooling
This commit adds several new features to enhance homelab management:

## New Services

### Backrest (backup.fig.systems)
- Modern web UI for managing Restic backups
- Encrypted, deduplicated backups to Backblaze B2
- Automated scheduling and retention policies
- Pre-configured to backup Immich photos and homelab configs
- SSO protected via tinyauth

### Homarr (home.fig.systems)
- Auto-discovery dashboard for all homelab services
- Docker socket integration for service monitoring
- Clean, modern interface with customizable widgets
- SSO protected via tinyauth

## Infrastructure

### Service Template System (templates/service-template/)
- Complete template with all common patterns
- Traefik labels, health checks, dependencies
- Environment variable examples
- Comprehensive README with usage instructions
- Ensures consistency across all new services

### OpenTofu/Terraform IaC (terraform/)
- Complete Proxmox VM provisioning setup
- Cloud-init automation for Docker host creation
- Automated Docker installation and configuration
- Media directory structure creation
- Step-by-step documentation including:
  - Cloud template creation guide
  - Variable configuration examples
  - Resource sizing recommendations
  - Security hardening options

## Documentation Updates
- Updated README with new service URLs
- Added Homarr and Backrest to directory structure
- Updated deployment instructions
- Added service table entries for new services

All new services follow established patterns:
- External homelab network
- Let's Encrypt SSL via Traefik
- Dual domain support (fig.systems + edfig.dev)
- Consistent naming and structure
2025-11-05 21:54:30 +00:00

6.6 KiB

Docker Host VM with OpenTofu

This configuration creates a VM optimized for running Docker containers in your homelab.

What This Creates

  • Ubuntu VM (from cloud template)
  • Docker & Docker Compose installed
  • Homelab network created
  • /media directories structure
  • SSH key authentication
  • Automatic updates enabled

Prerequisites

1. Create Ubuntu Cloud Template

First, create a cloud-init enabled template in Proxmox:

# SSH to Proxmox server
ssh root@proxmox.local

# Download Ubuntu cloud image
wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img

# Create VM
qm create 9000 --name ubuntu-cloud-template --memory 2048 --net0 virtio,bridge=vmbr0

# Import disk
qm importdisk 9000 jammy-server-cloudimg-amd64.img local-lvm

# Attach disk
qm set 9000 --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-9000-disk-0

# Add cloud-init drive
qm set 9000 --ide2 local-lvm:cloudinit

# Set boot disk
qm set 9000 --boot c --bootdisk scsi0

# Add serial console
qm set 9000 --serial0 socket --vga serial0

# Convert to template
qm template 9000

# Cleanup
rm jammy-server-cloudimg-amd64.img

2. Create API Token

In Proxmox UI:

  1. Datacenter → Permissions → API Tokens
  2. Add → User: root@pam, Token ID: terraform
  3. Uncheck "Privilege Separation"
  4. Save the secret!

3. Install OpenTofu

# Linux/macOS
curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh | sh

# Verify
tofu version

Quick Start

1. Configure Variables

cd terraform/proxmox-examples/docker-host

# Copy example config
cp terraform.tfvars.example terraform.tfvars

# Edit with your values
nano terraform.tfvars

Required changes:

  • pm_api_token_secret - Your Proxmox API secret
  • vm_ssh_keys - Your SSH public key
  • vm_password - Set a secure password

Optional changes:

  • vm_name - Change VM name
  • vm_cores / vm_memory - Adjust resources
  • vm_ip_address - Set static IP (or keep DHCP)

2. Initialize

tofu init

3. Plan

tofu plan

Review what will be created.

4. Apply

tofu apply

Type yes to confirm.

5. Connect

# Get SSH command from output
tofu output ssh_command

# Or manually
ssh ubuntu@<VM-IP>

# Verify Docker
docker --version
docker ps
docker network ls | grep homelab

Configuration Options

Resource Sizing

Light workload (1-5 containers):

vm_cores  = 2
vm_memory = 4096
disk_size = "30"

Medium workload (5-15 containers):

vm_cores  = 4
vm_memory = 8192
disk_size = "50"

Heavy workload (15+ containers):

vm_cores  = 8
vm_memory = 16384
disk_size = "100"

Network Configuration

DHCP (easiest):

vm_ip_address = "dhcp"

Static IP:

vm_ip_address = "192.168.1.100"
vm_ip_netmask = 24
vm_gateway    = "192.168.1.1"

Multiple SSH Keys

vm_ssh_keys = [
  "ssh-rsa AAAAB3... user1@laptop",
  "ssh-rsa AAAAB3... user2@desktop"
]

Post-Deployment

Deploy Homelab Services

# SSH to VM
ssh ubuntu@<VM-IP>

# Clone homelab repo (if not auto-cloned)
git clone https://github.com/efigueroa/homelab.git
cd homelab

# Deploy services
cd compose/core/traefik
docker compose up -d

cd ../lldap
docker compose up -d

# Continue with other services...

Verify Setup

# Check Docker
docker --version
docker compose version

# Check network
docker network ls | grep homelab

# Check media directories
ls -la /media

# Check system resources
htop
df -h

Managing the VM

View State

tofu show
tofu state list

Update VM

  1. Edit terraform.tfvars:
vm_cores  = 8  # Increase from 4
vm_memory = 16384  # Increase from 8192
  1. Apply changes:
tofu plan
tofu apply

Note: Some changes require VM restart.

Destroy VM

# Backup any data first!
tofu destroy

Type yes to confirm deletion.

Troubleshooting

Template Not Found

Error: template with ID 9000 not found

Solution: Create cloud template (see Prerequisites)

API Permission Error

Error: permission denied

Solution: Check API token permissions:

pveum acl modify / -token 'root@pam!terraform' -role Administrator

Cloud-Init Not Working

Check cloud-init status:

ssh ubuntu@<VM-IP>
sudo cloud-init status
sudo cat /var/log/cloud-init-output.log

Docker Not Installed

Manual installation:

ssh ubuntu@<VM-IP>
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker ubuntu

VM Won't Start

Check Proxmox logs:

# On Proxmox server
qm status <VM-ID>
tail -f /var/log/pve/tasks/active

Advanced Usage

Multiple VMs

Create docker-host-02.tfvars:

vm_name = "docker-host-02"
vm_ip_address = "192.168.1.101"

Deploy:

tofu apply -var-file="docker-host-02.tfvars"

Custom Cloud-Init

Edit main.tf to add custom cloud-init sections:

users:
  - name: myuser
    groups: sudo, docker
    shell: /bin/bash
    sudo: ALL=(ALL) NOPASSWD:ALL

packages:
  - zsh
  - tmux
  - neovim

runcmd:
  - sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

Attach Additional Disk

Add to main.tf:

disk {
  datastore_id = var.storage
  size         = 200
  interface    = "scsi1"
}

Mount in cloud-init:

mounts:
  - ["/dev/sdb", "/mnt/data", "ext4", "defaults", "0", "0"]

Cost Analysis

Resource Usage:

  • 4 cores, 8GB RAM, 50GB disk
  • Running 24/7

Homelab Cost: $0 (uses existing hardware)

If in cloud (comparison):

  • AWS: ~$50-100/month
  • DigitalOcean: ~$40/month
  • Linode: ~$40/month

Homelab ROI: Pays for itself in ~2-3 months!

Security Hardening

Enable Firewall

Add to cloud-init:

runcmd:
  - ufw default deny incoming
  - ufw default allow outgoing
  - ufw allow ssh
  - ufw allow 80/tcp
  - ufw allow 443/tcp
  - ufw --force enable

Disable Password Authentication

After SSH key setup:

ssh_pwauth: false

Automatic Updates

Already enabled in cloud-init. Verify:

sudo systemctl status unattended-upgrades

Next Steps

  1. Deploy core services (Traefik, LLDAP, Tinyauth)
  2. Configure SSL certificates
  3. Deploy media services
  4. Set up backups (Restic)
  5. Add monitoring (Prometheus/Grafana)

Resources