Skip to content
antalos

Deploy and maintain Debian VMs

Start with Debian application VMs to choose the project. These workloads use VM-specific settings and credentials; apps/variables.yaml configures their Kubernetes consumers only.

1. Prepare the VM project

Read the selected OpenTofu project’s variables.tf and terraform.tfvars.example. Supply your Proxmox access, VM identity, network, storage, and hardware mapping. Preserve an existing installation’s state before planning changes.

For RTX and Arc, confirm the intended PCI mapping in Proxmox before provisioning. A GPU passed through to a guest cannot be assumed available to another workload on the host. Review changes to the VM’s hardware and disks as infrastructure changes.

Example: plan the RTX VM from the repository root
tofu -chdir=infrastructure/opentofu/rtxtofu init
tofu -chdir=infrastructure/opentofu/rtxtofu plan

Apply the reviewed plan when ready. Use arctofu for Arc or lefttofu for the base Debian left VM. Complete cloud-init before running guest configuration. Reboot, storage, VM recreation, and disruptive network changes require the approval described in the repository instructions.

2. Prepare the matching Ansible project

VM Read first Inputs to prepare
Left infrastructure/ansible/leftansible/README.md Inventory, NFS export, and media Compose credentials
RTX infrastructure/ansible/rtxansible/README.md Inventory, VM variables, encrypted vault, Compose model definitions, required local models
Arc infrastructure/ansible/arcansible/README.md Inventory, encrypted vault, media storage, and access to the Nextcloud Talk Secret

For a new RTX or Arc vault, copy its vars/vault.yml.example, encrypt the new vars/vault.yml, and edit it with ansible-vault edit. For an existing vault, edit it without replacing its contents from the example. Keep original integration secrets when reconnecting existing applications.

3. Configure the guest

The working directory selects the project’s Ansible configuration and inventory:

Deploy the RTX guest configuration
cd infrastructure/ansible/rtxansible
ansible-playbook site.yml --ask-vault-pass

Arc uses the same command from arcansible/. Left runs ansible-playbook site.yml from leftansible/, mounts the shared media export, and copies the Caddy and media Compose projects without starting them.

Read the playbook before a maintenance run. These playbooks can install packages, change kernels, restart containers, run their own checks, and in some cases reboot. Arc also reads the Kubernetes Talk Secret and writes Nextcloud recording configuration. A run is more than copying a Compose file.

4. Connect the consumer

Backend Complete the integration
llama-swap / Speaches Match endpoints and credentials in LiteLLM, then select a discovered model in the consuming application
Talk recording Keep the recorder secret and Talk internal secret aligned; use Nextcloud integrations
Immich Machine Learning Register the remote endpoint in the separately managed Immich server
Jellyfin / media stack Prepare the 10.30.0.5:/mnt/warm/jellyfin NFS export for UID:GID 1008:1008, fill the protected Debian Left media environment, then configure each application and test a representative import or encode
Docling Configure the client endpoint and its X-Api-Key credential
Storyteller Create the admin account at http://10.30.0.28:8001, upload ebooks/audiobooks or configure auto-import under /media, then test an alignment with Intel SYCL transcription
LazyLibrarian Open http://10.30.0.28:5299/home, configure authorized search providers, follow authors, and select ebook/audiobook Wanted status; qBittorrent downloads and Storyteller watch rules are declared by Arc Ansible

Successful container startup does not finish an application integration. Use a small representative request through the actual consumer after deployment.

Inspect without changing the VM

Use SSH aliases from the workstation configuration:

Inspect declared VM workloads
ssh debian-rtx 'cd /opt/compose && docker compose ps'
ssh debian-arc 'cd /opt/compose && docker compose ps'

Use ssh proxmox for hypervisor diagnostics and ssh nas for storage diagnostics. Do not replace configured aliases with copied IP addresses. For the left VM, use the alias established in your own SSH configuration before issuing guest commands.

Keep the source and guest aligned

Make durable Compose changes in the Ansible project, then deploy through that project. Changes made only in /opt/compose can be overwritten on the next playbook run. Cloud-init changes are provisioning changes and do not automatically rerun on an existing guest.

Recover persistent data and original secrets before reconnecting consumers. A newly reachable endpoint with an empty data directory is not evidence that the former service has been restored.

For Storyteller, preserve /opt/compose/data/storyteller (database and generated secret_key) and /mnt/warm/jellyfin/storyteller (books, audio, and covers). Ansible generates the authentication key only when absent. The application uses UID:GID 1008:1008 through PUID/PGID and receives the Arc render device; its SQLite database and processing scratch space stay on the VM while assets use Jellyfin’s existing NFS export. A successful HTTP response does not prove that a book alignment uses GPU transcription.

LazyLibrarian and Storyteller share completed libraries at /media/books/ebooks and /media/books/audiobooks. LazyLibrarian’s qBittorrent category list is books,audiobooks; their download paths are /media/downloads/books and /media/downloads/audiobooks. The configured downloader is Debian Left’s existing endpoint; do not change its VPN routing to connect a new client.

Arc Ansible preserves the protected guest downloader identity, or accepts vault_books_qbittorrent_username and vault_books_qbittorrent_password in the existing encrypted vault. First-installation discovery can reuse Sonarr’s configured identity through ssh debian-left, but stale credentials must be replaced with a working login. Back up /opt/compose/data/lazylibrarian along with the completed NFS libraries. Storyteller’s reference watch rules come from arcansible/compose/storyteller.json; they preserve the source libraries and do not automatically merge matching formats stored in separate folders.