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 | testing1–testing3.${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