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 |
||
|---|---|---|
| .. | ||
| main.tf | ||
| outputs.tf | ||
| README.md | ||
| terraform.tfvars.example | ||
| variables.tf | ||
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:
- Datacenter → Permissions → API Tokens
- Add → User:
root@pam, Token ID:terraform - Uncheck "Privilege Separation"
- 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 secretvm_ssh_keys- Your SSH public keyvm_password- Set a secure password
Optional changes:
vm_name- Change VM namevm_cores/vm_memory- Adjust resourcesvm_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
- Edit
terraform.tfvars:
vm_cores = 8 # Increase from 4
vm_memory = 16384 # Increase from 8192
- 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
- ✅ Deploy core services (Traefik, LLDAP, Tinyauth)
- ✅ Configure SSL certificates
- ✅ Deploy media services
- ✅ Set up backups (Restic)
- ✅ Add monitoring (Prometheus/Grafana)