ansible/docs/guides/app_stack_proxmox.md
ilia c2e797a027
All checks were successful
CI / skip-ci-check (pull_request) Successful in 1m22s
CI / lint-and-test (pull_request) Successful in 1m27s
CI / ansible-validation (pull_request) Successful in 2m53s
CI / secret-scanning (pull_request) Successful in 1m24s
CI / dependency-scan (pull_request) Successful in 1m28s
CI / sast-scan (pull_request) Successful in 2m32s
CI / license-check (pull_request) Successful in 1m28s
CI / vault-check (pull_request) Successful in 2m30s
CI / playbook-test (pull_request) Successful in 2m32s
CI / container-scan (pull_request) Successful in 1m53s
CI / sonar-analysis (pull_request) Successful in 2m40s
CI / workflow-summary (pull_request) Successful in 1m22s
feat(app_setup): improve deployment reliability and add mirrormatch support
- Fix deploy script to handle non-git directories by cloning to temp
  location and moving contents, preserving .env files during clone
- Remove comment lines from env.j2 template to prevent xargs errors
- Add initial deploy task to app_setup role to ensure app is deployed
  before service starts
- Fix migrate command precedence to check env-specific overrides first
- Add sudo to systemctl restart commands in deploy script
- Update documentation with project-specific configuration notes

These changes improve deployment reliability for all app projects while
adding support for mirrormatch-specific requirements (db:push, seeding).
All changes are backward-compatible with existing projects (pote, punimTag).
2026-01-04 16:50:54 -05:00

4.9 KiB

Proxmox App Projects (LXC-first)

This guide documents the modular app-project stack that provisions Proxmox guests (dev/qa/prod) and configures a full-stack app layout on them.

What you get

  • Proxmox provisioning via API (currently LXC; VM support remains via existing roles/proxmox_vm KVM path)
  • A deployment user (appuser) with your SSH key
  • /srv/app/backend and /srv/app/frontend
  • Env file /srv/app/.env.<dev|qa|prod>
  • /usr/local/bin/deploy_app.sh to pull the right branch and restart services
  • systemd services:
    • app-backend.service
    • app-frontend.service

Where to configure projects

Edit:

  • inventories/production/group_vars/all/main.yml

Under app_projects, define projects like:

  • projectA.repo_url
  • projectA.envs.dev|qa|prod.ip/gateway/branch
  • projectA.guest_defaults (cores/memory/rootfs sizing)
  • projectA.deploy.* (install/build/migrate/start commands)
  • Optional: per-env backend_seed_cmd (e.g., npm run db:seed for dev/qa)

Adding projectB is just adding another top-level app_projects.projectB entry.

Proxmox credentials (vault)

This repo already expects Proxmox connection vars in vault (see existing Proxmox playbooks). Ensure these exist in:

  • inventories/production/group_vars/all/vault.yml (encrypted)

Common patterns:

  • vault_proxmox_host: 10.0.10.201
  • vault_proxmox_user: e.g. root@pam or ansible@pve
  • vault_proxmox_node: e.g. pve
  • Either:
    • vault_proxmox_password, or
    • vault_proxmox_token + vault_proxmox_token_id

Debian LXC template

The LXC provisioning uses lxc_ostemplate, defaulting to a Debian 12 template string like:

local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst

If your Proxmox has a different template filename, change lxc_ostemplate in inventories/production/group_vars/all/main.yml.

Running it

Provision + configure one project:

ansible-playbook -i inventories/production playbooks/app/site.yml -e app_project=projectA

Provision + configure all projects in app_projects:

ansible-playbook -i inventories/production playbooks/app/site.yml

Only provisioning (Proxmox API):

ansible-playbook -i inventories/production playbooks/app/provision_vms.yml -e app_project=projectA

Only OS/app configuration:

ansible-playbook -i inventories/production playbooks/app/configure_app.yml -e app_project=projectA

Limiting to a single env (dev/qa/prod)

  • Pass -e app_env=dev (or qa/prod) to provision/configure only that environment for the selected project.
  • Example (provision dev only):
    ansible-playbook -i inventories/production playbooks/app/provision_vms.yml -e app_project=mirrormatch -e app_env=dev
    
    Configure/dev only:
    ansible-playbook -i inventories/production playbooks/app/configure_app.yml -e app_project=mirrormatch -e app_env=dev
    

Example: mirrormatch project

  • Config lives in inventories/production/group_vars/all/main.yml under app_projects.mirrormatch (dev/qa/prod guests, repo URL, migrate/start commands, env vars).
  • Secrets live in the vault: vault_mirrormatch_database_url_* (and optional vault_mirrormatch_shadow_database_url_*), plus an optional repo deploy key vault_mirrormatch_git_ssh_key.
  • Run end-to-end:
make app PROJECT=mirrormatch

Run provisioning only / configure only:

make app-provision PROJECT=mirrormatch
make app-configure PROJECT=mirrormatch

Optional: SSH aliases on your workstation

To write ~/.ssh/config entries (disabled by default):

ansible-playbook -i inventories/production playbooks/app/ssh_client_config.yml -e manage_ssh_config=true -e app_project=projectA

This creates aliases like projectA-dev, projectA-qa, projectA-prod.

Project-Specific Configuration

Environment-Specific Commands

Projects can override deploy commands per environment:

envs:
  dev:
    backend_migrate_cmd: "npm run db:push"  # Override default migrate command
    backend_seed_cmd: "npm run db:seed"      # Optional: seed database

Precedence order:

  1. env_def.backend_migrate_cmd (per-environment override)
  2. project_def.deploy.backend_migrate_cmd (project default)
  3. Global default (npm run migrate)

Environment File Naming

The systemd service uses EnvironmentFile=/srv/app/.env.<env> (e.g., .env.dev). Systemd loads these variables into the service environment.

Note: Next.js has its own env file loading that looks for .env, .env.local, .env.production, etc. If your Next.js app isn't reading env vars, consider:

  • Using .env.local for dev (Next.js loads this automatically)
  • Or ensure your app reads from process.env (systemd-injected vars)

Project Types

  • Standard Node.js apps (mirrormatch, punimTagBE/FE): Use app_setup role
  • Python apps (pote): Use pote role (completely separate deployment path)

Changes to app_setup role affect all Node.js projects but are backward-compatible.