Skip to content

Apps VPS

Dedicated server for product applications. Platform tools stay on the infra VPS.

Field Value
IP 82.165.177.110
Path /opt/apps
Edge proxy Traefik in /opt/apps/traefik
Staging bays testing1testing3.${DOMAIN} via slot-manager.sh; Traefik dynamic/ + Let's Encrypt

Staging slots (Ship human QA)

DNS A records testing1 / testing2 / testing3 → this VPS (82.165.177.110). Traefik must mount ./dynamic and enable the file provider (see templates/apps-vps/traefik/). After updating templates on the VPS:

mkdir -p /opt/apps/traefik/dynamic
# sync templates, then:
cd /opt/apps/traefik && docker compose up -d --force-recreate
# one-time bootstrap (root on Apps VPS) — deploy gets harden-only sudo, not full root:
bash scripts/bootstrap-apps-staging-slots.sh
# docs golden-path preview:
bash /opt/apps/scripts/slot-manager.sh claim testing1 INFRA-101 docs
bash /opt/apps/scripts/slot-manager.sh deploy testing1 https://git.${DOMAIN}/infra/devops.git main
# open https://testing1.${DOMAIN}/architecture/ship-golden-path-diagram/
bash /opt/apps/scripts/slot-manager.sh wipe testing1

Deploy user permissions (Infra vs Apps)

VPS CI user Owns Root?
Infra (85.215.32.166) deploy /opt/devops No — admins (rafael.gonzalez.albes, alex) have sudo
Apps (82.165.177.110) deploy /opt/apps/slots, /opt/apps/scripts, /opt/apps/traefik/dynamic No — deploy may run only /opt/apps/scripts/harden-apps-dir-perms.sh via sudo to fix slot ownership after smoke tests

Woodpecker CI syncs slot-manager.sh to Apps on every platform deploy (scripts/sync-slot-manager-to-apps.sh).

| SSH alias | apps-vps (after scripts/setup-apps-vps-ssh.ps1) |

Bootstrap

# Fill local/apps-vps.env first
powershell -File scripts/setup-apps-vps-ssh.ps1
ansible-playbook -i ansible/inventories/hosts.yml ansible/playbooks/site-apps.yml --limit apps
# or legacy: bash scripts/bootstrap-apps-vps.sh

Per-app layout

/opt/apps/wearlab/
/opt/apps/bioscan/
/opt/apps/dronecolonies/
/opt/apps/cat-tree/

Planned hostnames and when to buy branded domains: Products, domains & legal.

Woodpecker deploys from CI on infra VPS via SSH to deploy@82.165.177.110. Build steps run on the apps Woodpecker agent (labels: location: apps-vps).

Secrets and deploy (WearLab)

Layer Location
Encrypted in git secrets/projects/wearlab.enc.env (infra-devops)
On apps VPS /opt/apps/wearlab/secrets/wearlab.enc.env (mode 600)
At deploy Decrypted to /home/deploy/.cache/apps-secrets/wearlab.env (not plain .env on disk)
Woodpecker secrets ssh_*, registry_*, sops_age_key on alex/wearlab-main

Deploy command (Woodpecker SSH): bash /opt/apps/wearlab/run-deploy.sh → Ansible deploy-wearlab.yml.

Bootstrap/sync: bash scripts/sync-wearlab-ansible-to-apps.sh or ansible-playbook ansible/playbooks/site-apps.yml --limit apps.

Legacy bash (deprecated): bootstrap-apps-vps.sh, setup-apps-vps-foundation.sh — prefer Ansible site-apps.yml.

See Woodpecker agents, WearLab, and migrate-app-to-apps-vps.md.

Observability

Apps VPS is monitored from the infra VPS — no duplicate Kuma/Netdata/DefectDojo here:

Signal How
Uptime Kuma HTTP checks (wearlab.*, bioscan.*, …) — Monitoring
Metrics Netdata child streams to metrics.* parent — Metrics
Security Woodpecker CI uploads to central security.* DefectDojo

Deploy Netdata child: bash scripts/deploy-apps-netdata-child.sh