- Add adyrem.duckdns.org/Anki → claude-code VM:4002 via Traefik
- Add anki.homelab DNS entry to Pi-hole
- Mount Jellyfin transcode cache to /media/transcodes (HDD) instead of
anonymous Docker volume on root disk; prevents root disk from filling up
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Switch NVIDIA installer copy to get_url so the LXC downloads it
directly from NVIDIA's servers rather than expecting the file on the
Ansible controller
- Remove jellyfin-tools (original compose reference from upstream);
the Ansible template is now the authoritative compose file
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New Ansible role: jellyfin — Docker + nvidia-container-toolkit setup,
full *arr stack compose file (Jellyfin, qBittorrent, Radarr, Sonarr,
Prowlarr, FlareSolverr, Jellyseerr), systemd service for auto-start
- New playbook: jellyfin.yml targeting media_servers group
- Inventory: add media LXC (10.10.1.50) to media_servers group
- Traefik: add internal .homelab routes for all 6 media services
- Pi-hole: add DNS records for all 6 media services → Traefik
- network-interfaces: DNAT port 6881 TCP+UDP → 10.10.1.50 for BitTorrent
- homelab-requirements.md: document full Jellyfin stack requirements
including NVIDIA GTX 1060 passthrough approach and driver notes
- jellyfin-tools: original reference compose file from upstream
Infrastructure created on Proxmox:
- LXC 106 (media, Debian 12, privileged, nesting=1, 10.10.1.50/vmbr1)
- ZFS dataset hdd/media mounted at /media in LXC
- NVIDIA device passthrough entries in /etc/pve/lxc/106.conf
Note: NVIDIA driver 580.159.03 (.run) installed on Proxmox host — not
managed by apt (Debian only has 550.x which doesn't support kernel 7.x
or GTX 1060 Pascal as of this driver version).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a VM has firewall=1, Proxmox inserts a fwbr bridge and iptables
POSTROUTING fires at the bridge step (OUT=fwbrNNNi0) rather than at
vmbr0. The MASQUERADE rule (-o vmbr0) never matches, so the VM loses
internet access.
Adds an idempotent task to the proxmox_host role that strips
firewall=1 from VM 105's net0 config whenever the playbook runs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Routes adyrem.duckdns.org/mtg → http://10.10.2.10:3000 (claude-code-vm)
with StripPrefix so the app sees requests at /.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Without -d 192.168.1.10, the DNAT rule intercepted all TCP port 80/443
traffic arriving on vmbr0 — including LAN or routed traffic destined for
internal VMs like Pi-hole (10.10.1.2), redirecting it to Traefik instead.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
common role: add nmcli task that ensures the static IP, gateway, and DNS
are configured in NetworkManager — idempotent, only applies when
network_gateway is defined. Fixes Gitea going offline after reboot
because the NM connection had reverted to DHCP.
group_vars/infra: add network vars (10.10.1.0/24, gw 10.10.1.1)
group_vars/claude_code_vms: add network vars (10.10.2.0/24, gw 10.10.2.1)
also fix ProxyJump to use adyrem@:2222 (root login was disabled)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Arch Linux cloud image, 4 cores/8GB, dev-net (10.10.2.10), autostart.
Cloud-init handles user/SSH key/network on first boot. Ansible role
installs Claude Code CLI, tmux, SSH keys, SSH config for all managed
VMs via ProxyJump, homelab repo clone.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Set onboot=1 on VM 100 (gitea) and VM 101 (monitoring) so they start
automatically on Proxmox host boot.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
VM 102: Windows 11 Home N, 8 cores/16GB, OVMF+TPM2, QXL/SPICE display,
vmbr3 (desktop-net). SPICE used instead of RDP — Home N has no RDP server.
Clean-install snapshot taken and synced to HDD.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- sanoid: daily snapshots (7d) + weekly (4w) for rpool/data (VM disks)
and rpool/ROOT (Proxmox OS); runs every 15 min via systemd timer
- syncoid: daily replication from rpool/data and pve-root to hdd/backups
at 02:00; first full sync completed successfully
- All VM disks (gitea, monitoring) now backed up to HDD pool
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Create claude-code user on Proxmox with chroot + ForceCommand internal-sftp
- Add dedicated SSH keypair (public key committed, private key in keys/)
- Update requirements to document that Claude Code runs in a persistent VM,
connects to other VMs via SSH, and to the Proxmox host via SFTP only
- Session persistence via tmux allows reconnecting from any WireGuard device
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Old values were exposed in plaintext in the initial commit history.
New values generated via `gitea generate secret`.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Node.js is required by JS-based actions (e.g. actions/checkout@v4)
on native host runners. python-pip is needed for ansible-lint install.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>