39be9fafe7
- Move group_vars into inventory/ so playbooks can find them (was only visible to ad-hoc commands via CWD) - Add Ansible Vault for sensitive variables (gitea/grafana passwords, tokens, db credentials) with vault_password_file outside the repo - Enable Gitea Actions and deploy act_runner with Docker backend on the gitea VM - Add .gitea/workflows/lint.yml to run ansible-lint on every push - Set up Gitea → GitHub push mirror (sync_on_commit) - Fix ansible.cfg stdout_callback for ansible-core 2.20 compatibility - Add python-psycopg2 to gitea role (required for postgresql modules) - Add docker to gitea_runner role (required by act_runner at startup) - Exclude password hashes and VM images from git Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
290 lines
13 KiB
Markdown
290 lines
13 KiB
Markdown
# Homelab Setup Requirements
|
|
|
|
## Hardware Context
|
|
- Host machine with Intel i7-8700, 32GB RAM
|
|
- Two disks: one smaller SSD (primary), one larger WD Black HDD (secondary)
|
|
- Complete fresh install, nothing to preserve
|
|
|
|
---
|
|
|
|
## Non-Negotiable Requirements
|
|
|
|
1. Claude Code sessions can SSH into multiple VMs in the same session with full sudo access inside the VM.
|
|
2. Claude Code sessions cannot execute any commands on the host — only read and write files in designated folders.
|
|
3. A Windows VM with Visual Studio must be runnable and accessible via RDP.
|
|
|
|
---
|
|
|
|
## 1. Disk Layout
|
|
|
|
- Proxmox installed on the SSD using ZFS (single-disk pool)
|
|
- ZFS chosen for native snapshots, send/receive, and compression
|
|
- VM disk images stored in a ZFS pool on the SSD (`rpool` or a dedicated dataset)
|
|
- HDD formatted as a ZFS pool, used for:
|
|
- Receiving ZFS send/receive snapshots from SSD (local backup)
|
|
- Storage for non-critical / parked VMs
|
|
- Snapshot schedule: daily snapshots retained for 7 days, weekly retained for 4 weeks
|
|
- Snapshot tooling: `sanoid` (policy-based ZFS snapshots) + `syncoid` (ZFS send/receive to HDD)
|
|
|
|
---
|
|
|
|
## 2. Host OS
|
|
|
|
- **Proxmox VE** (latest stable release, Debian-based)
|
|
- Installed via the official Proxmox ISO — no custom OS required
|
|
- No desktop environment on the host
|
|
- Minimal additional packages — Proxmox manages the hypervisor; everything else runs in VMs
|
|
- Locale: `en_US.UTF-8`, keyboard layout: Swiss German, timezone: `Europe/Zurich`
|
|
- Hostname: `homelab`
|
|
- Automatic security updates: `unattended-upgrades` configured for security patches only; full updates manual
|
|
- Proxmox web UI accessible from local network / VPN only
|
|
|
|
---
|
|
|
|
## 3. Networking & Remote Access
|
|
|
|
### SSH
|
|
- SSH access to host is **only permitted from within the local network or VPN** — Proxmox firewall blocks SSH from WAN
|
|
- Key-based authentication only, password auth disabled
|
|
- Root login disabled (admin user only)
|
|
- A dedicated SSH keypair for this project; public key committed to repo, private key kept by operator
|
|
- Dedicated non-default SSH port — to be decided during setup
|
|
|
|
### RDP
|
|
- RDP is for VMs only — no RDP on the host
|
|
- VM RDP accessible through VPN from outside the network
|
|
|
|
### Firewall
|
|
- Proxmox built-in firewall enabled at datacenter and host level
|
|
- Default deny inbound from WAN
|
|
- Allow inbound from WAN: VPN port only
|
|
- Allow inbound from local network / VPN: SSH (host), Proxmox web UI (8006), RDP (VMs), monitoring ports (Grafana, Prometheus)
|
|
- VM-level firewall rules managed per VM in Proxmox
|
|
|
|
### VPN (Internet-Box)
|
|
- Internet-Box 3 or 4 — use **IKEv2** (supported on both; WireGuard only on 4+, cannot confirm model)
|
|
- VPN server configured on the Internet-Box itself (not on the host)
|
|
- DynDNS configured on the Internet-Box for stable external hostname
|
|
- All external access (SSH, RDP, Gitea, monitoring dashboards) routes through this VPN
|
|
- Document VPN client setup steps for Windows and Linux clients in the repo README
|
|
|
|
---
|
|
|
|
## 4. Hypervisor
|
|
|
|
- **Proxmox VE** — KVM/QEMU managed via Proxmox (not libvirt)
|
|
- VM management via Proxmox web UI and `qm` / `pvesh` CLI
|
|
- VM networks (Proxmox Linux bridges):
|
|
- `infra-net` (`vmbr1`): isolated NAT for infrastructure VMs (Gitea, monitoring)
|
|
- `dev-net` (`vmbr2`): isolated NAT for Claude Code workload VMs
|
|
- `desktop-net` (`vmbr3`): NAT for desktop VMs
|
|
- No VM has bridged access to the physical LAN unless explicitly required
|
|
- UEFI support via OVMF (included in Proxmox)
|
|
- TPM 2.0 emulation via `swtpm` (required for Windows 11)
|
|
- Infrastructure VMs (Gitea, monitoring) set to autostart on host boot via Proxmox autostart
|
|
- VM configs (`.conf` files from `/etc/pve/qemu-server/`) committed to Ansible repo
|
|
|
|
---
|
|
|
|
## 5. Users & Permissions
|
|
|
|
### Host Users
|
|
- One admin user (human operator):
|
|
- SSH key login only, no password SSH
|
|
- Full `sudo` access
|
|
- One `claude-code` service user — enforces non-negotiable requirement 2:
|
|
- **Shell set to `/usr/lib/openssh/sftp-server`** — SFTP-only, zero execution rights on host
|
|
- **Chroot or path restriction** to designated read/write folders only (e.g. `/home/claude-code/workspace`)
|
|
- SSH access restricted to a dedicated key
|
|
- No access to Proxmox tooling, VM management, or other users' files
|
|
- Cannot be used as a jump host — Claude Code SSHes directly into VMs
|
|
|
|
### VM Users (all VMs)
|
|
- `root` account: password set, SSH login disabled
|
|
- `vmuser` account: default non-root user, SSH key login, full sudo inside the VM
|
|
- Additional users may be added per VM as needed
|
|
|
|
---
|
|
|
|
## 6. Virtual Machines
|
|
|
|
### 6.1 Gitea VM (Infrastructure)
|
|
- **Distro:** Arch Linux minimal (provisioned via `archinstall` JSON config)
|
|
- **Purpose:** Self-hosted Git, mirrors all repos to GitHub automatically
|
|
- **Setup:** Provisioned manually as bootstrap step — must exist before Ansible automation can run
|
|
- **Storage:** SSD ZFS pool (infrastructure-critical)
|
|
- **Access:** SSH from host admin user; Gitea web UI accessible from local network / VPN
|
|
- **Gitea config:**
|
|
- Admin account set up manually
|
|
- Mirror job configured for every repo to sync to GitHub
|
|
- The Ansible homelab repo is the primary repo hosted here
|
|
- **Backups:** Proxmox VM snapshot + ZFS send/receive to HDD; Gitea data directory snapshotted daily
|
|
|
|
### 6.2 Monitoring VM (Infrastructure)
|
|
- **Distro:** Arch Linux minimal
|
|
- **Purpose:** Centralised observability for host and all VMs
|
|
- **Setup:** Provisioned via Ansible after Gitea bootstrap; autostart on host boot
|
|
- **Storage:** SSD ZFS pool (infrastructure-critical)
|
|
- **Access:** Grafana web UI accessible from local network / VPN only; no WAN exposure
|
|
- **Backups:** Proxmox VM snapshot + ZFS send/receive to HDD
|
|
|
|
#### Stack
|
|
| Component | Role |
|
|
|---|---|
|
|
| **Prometheus** | Metrics collection and storage |
|
|
| **Grafana** | Dashboards and alerting UI |
|
|
| **Node Exporter** | Host and VM system metrics (CPU, RAM, disk, network) |
|
|
| **Alertmanager** | Alert routing (email or other notification channel) |
|
|
| **Loki** | Log aggregation |
|
|
| **Promtail** | Log shipping agent (runs on host and each VM) |
|
|
|
|
#### What Is Monitored
|
|
- **Host system:** CPU, RAM, disk usage/IO, network throughput, ZFS pool health, Proxmox VM states
|
|
- **All VMs:** CPU, RAM, disk, network via Node Exporter installed in each VM by Ansible
|
|
- **Gitea VM:** Service health, disk usage of repo storage
|
|
- **Windows VM:** Basic ping/availability check only (no agent)
|
|
- **ZFS snapshots:** Alert if daily snapshot has not run within expected window
|
|
- **VM availability:** Alert if any infrastructure VM (Gitea, monitoring itself) goes unreachable
|
|
- **Disk space:** Alert at 75% and 90% on SSD and HDD ZFS pools
|
|
|
|
#### Alerting
|
|
- Alertmanager configured with at least one notification channel (email recommended as default)
|
|
- Alert on: host down, infrastructure VM down, disk >75%, snapshot missed, high CPU/RAM sustained >15 min
|
|
|
|
#### Ansible Integration
|
|
- Node Exporter and Promtail installed and enabled on every Linux VM by the base VM playbook
|
|
- Prometheus scrape config updated automatically when a new VM is provisioned
|
|
- Monitoring VM definition and Prometheus/Grafana configs committed to Ansible repo
|
|
- Grafana dashboards exported as JSON and committed to repo for full reproducibility
|
|
|
|
### 6.3 Windows VM
|
|
- **Purpose:** Visual Studio development (extension building) — non-negotiable requirement 3
|
|
- **License:** Activated via personal Microsoft account
|
|
- **UEFI + TPM:** OVMF + swtpm for Windows 11 compatibility
|
|
- **Resources:** 8 cores, 16GB RAM (adjustable)
|
|
- **Storage:** SSD ZFS pool (active use); snapshot to HDD after each milestone
|
|
- **Snapshot strategy:** ZFS snapshot of VM disk taken after:
|
|
1. Clean Windows install + activation
|
|
2. Visual Studio install + configuration
|
|
- Snapshots sent to HDD ZFS pool; rebuild = `zfs receive` from HDD
|
|
- **Access:** RDP via VPN from outside network
|
|
- **Network:** `desktop-net`, no access to host or other VM networks
|
|
- **Monitoring:** Ping/availability check only
|
|
|
|
### 6.4 Fedora KDE VM
|
|
- **Purpose:** General purpose Linux desktop
|
|
- **Distro:** Fedora (latest stable) with KDE Plasma desktop
|
|
- **Resources:** 4 cores, 8GB RAM (adjustable)
|
|
- **Storage:** HDD ZFS pool (non-critical)
|
|
- **Users:** `root` + `vmuser`
|
|
- **Access:** RDP via `xrdp` or VNC; SSH
|
|
- **Network:** `desktop-net`
|
|
- **Monitoring:** Node Exporter + Promtail installed via Ansible
|
|
|
|
### 6.5 Arch Desktop VM
|
|
- **Purpose:** General purpose Linux desktop
|
|
- **Distro:** Arch Linux with desktop environment (to be chosen at setup time)
|
|
- **Resources:** 4 cores, 8GB RAM (adjustable)
|
|
- **Storage:** HDD ZFS pool (non-critical)
|
|
- **Users:** `root` + `vmuser`
|
|
- **Access:** RDP or VNC; SSH
|
|
- **Network:** `desktop-net`
|
|
- **Monitoring:** Node Exporter + Promtail installed via Ansible
|
|
|
|
### 6.6 Claude Code Dev VMs
|
|
- **Purpose:** Isolated environments for Claude Code to operate in — enforces non-negotiable requirement 1
|
|
- **Distro:** Arch Linux minimal (provisioned via `archinstall` JSON config)
|
|
- **Provisioning:** Cloned from a base template VM, then configured via Ansible
|
|
- **Persistence:** VMs are persistent (not ephemeral per session)
|
|
- **Multi-VM sessions:** Claude Code may SSH into multiple dev VMs in one session
|
|
- **Isolation requirements:**
|
|
- No shared folders with host
|
|
- No access to `infra-net` or `desktop-net`
|
|
- Operates on `dev-net` only
|
|
- No route to host system
|
|
- `vmuser` is the SSH target for Claude Code with full sudo inside the VM
|
|
- **Resources:** 2 cores, 4GB RAM per VM (adjustable)
|
|
- **Storage:** SSD ZFS pool for active VMs, HDD ZFS pool for parked/unused ones
|
|
- **Monitoring:** Node Exporter + Promtail installed via Ansible base VM playbook
|
|
|
|
---
|
|
|
|
## 7. Ansible Automation
|
|
|
|
- All post-install configuration managed via Ansible playbooks
|
|
- Repo hosted on Gitea VM, mirrored to GitHub
|
|
- Secrets managed via `ansible-vault`; vault password stored only by the operator
|
|
- **Playbook structure:**
|
|
```
|
|
homelab/
|
|
├── archinstall-config.json # reproducible base config for Linux guest VMs
|
|
├── inventory.ini # host + VM inventory
|
|
├── playbooks/
|
|
│ ├── host.yml # Proxmox host: users, SSH, firewall, sanoid/syncoid
|
|
│ ├── snapshots.yml # ZFS snapshot schedules (sanoid) + send/receive (syncoid)
|
|
│ ├── users.yml # host users, SSH keys, claude-code SFTP restriction
|
|
│ ├── monitoring.yml # monitoring VM, Prometheus, Grafana, Loki
|
|
│ └── vms/
|
|
│ ├── gitea.yml
|
|
│ ├── windows.yml
|
|
│ ├── fedora-kde.yml
|
|
│ ├── arch-desktop.yml
|
|
│ └── dev-template.yml
|
|
├── templates/ # Jinja2 config templates
|
|
│ ├── prometheus.yml.j2
|
|
│ ├── promtail.yml.j2
|
|
│ ├── alertmanager.yml.j2
|
|
│ └── sanoid.conf.j2
|
|
├── files/
|
|
│ └── grafana-dashboards/ # exported dashboard JSON files
|
|
├── vars/
|
|
│ └── vault.yml # encrypted secrets
|
|
└── README.md
|
|
```
|
|
- Every playbook must be idempotent (safe to re-run)
|
|
- README must document:
|
|
- Full rebuild procedure from bare metal
|
|
- VPN client setup (Windows + Linux)
|
|
- How to provision a new dev VM
|
|
- How to restore a VM from ZFS snapshot
|
|
- How to access the Proxmox web UI and Grafana dashboard
|
|
- How to add a new VM to monitoring
|
|
|
|
---
|
|
|
|
## 8. Backup & Recovery
|
|
|
|
- **Primary backup mechanism:** `syncoid` ZFS send/receive from SSD pool to HDD pool
|
|
- **Snapshot policy:** managed by `sanoid` on both pools
|
|
- **Scope of backups:**
|
|
- All VM disks on SSD ZFS pool (daily incremental send/receive to HDD)
|
|
- Gitea data directory (daily snapshot)
|
|
- Monitoring VM data directory including Prometheus data (daily snapshot)
|
|
- Grafana dashboards as JSON in git repo (always up to date)
|
|
- Windows VM disk snapshot after each milestone (stored on HDD ZFS pool)
|
|
- **No external/cloud backup initially** — architecture must make it easy to add (e.g. `restic` to Backblaze B2) later
|
|
- **Recovery procedure documented in README**
|
|
|
|
---
|
|
|
|
## 9. Rebuild Order (Disaster Recovery Sequence)
|
|
|
|
In the event of full hardware loss, the rebuild order is:
|
|
|
|
1. Install Proxmox on new hardware (ISO installer, ~10 min)
|
|
2. Restore SSD ZFS pool from HDD send/receive backups (`zfs receive`)
|
|
3. Run `host.yml` Ansible playbook (cloned from GitHub mirror) to configure host users, SSH, firewall
|
|
4. Start Gitea VM (restored from ZFS snapshot) and clone Ansible repo from it
|
|
5. Run `monitoring.yml` to restore monitoring VM
|
|
6. Run remaining playbooks to restore all VMs
|
|
7. Import Grafana dashboards from JSON files in repo
|
|
8. Reconfigure Internet-Box VPN and DynDNS if hardware changed
|
|
|
|
---
|
|
|
|
## 10. Out of Scope (for now)
|
|
|
|
- External/cloud backups (architecture must not preclude adding later)
|
|
- Additional VM distros beyond those listed — template mechanism should make adding easy
|
|
- Monitoring of Windows internals beyond availability ping
|