4.6 KiB
Arvan VPS — Deploy Guide
Battle-tested steps for deploying to the Arvan cloud server. Written after a deploy where we hit every trap below — follow this and they won't bite again.
Server facts
| Thing | Value |
|---|---|
| SSH host (inbound) | 94.101.187.12 |
| Egress IP (outbound — for API whitelists, e.g. Asian Metal) | 31.171.101.234 ⚠️ different from SSH IP |
| SSH user | root only (key auth) — ubuntu does NOT work |
| SSH key | ~/.ssh/yz_deploy_ed25519 (public key is in root's authorized_keys) |
| Code on server | /root/statista — plain copied tree, NOT a git repo |
| Live config | /root/statista/deploy/.env (root-only, untracked — never in git) |
| Stack | docker compose -f deploy/docker-compose.yml → nginx + frontend (:3000) + backend (:8000) |
| Public URL | http://94.101.187.12 (nginx on :80) |
The deploy (copy-paste, run from your local repo)
KEY=~/.ssh/yz_deploy_ed25519
BR=deploy-vps-restructure # branch to deploy
# 1) ship the committed tree (NOT a git pull — server isn't a git repo).
# git archive only includes tracked files, so deploy/.env + data are untouched.
git archive --format=tar "$BR" | \
ssh -i "$KEY" root@94.101.187.12 'cd /root/statista && tar -xf -'
# 2) rebuild images + recreate containers
ssh -i "$KEY" root@94.101.187.12 \
'cd /root/statista && docker compose -f deploy/docker-compose.yml up -d --build'
# 3) ⚠️ ALWAYS restart nginx afterwards (see Trap #2)
ssh -i "$KEY" root@94.101.187.12 \
'cd /root/statista && docker compose -f deploy/docker-compose.yml restart nginx'
# 4) verify (all must be 200)
ssh -i "$KEY" root@94.101.187.12 \
'for p in / /manifest.webmanifest /sw.js /api/currency; do
echo "$p -> $(curl -s -o /dev/null -w "%{http_code}" http://localhost$p)"; done'
Commit + push first (git push origin deploy-vps-restructure) if you want the
GitHub copy current — but the archive deploys your local committed tree
regardless, so step 1 is the source of truth for the server.
Traps we hit (and the fixes)
Trap #1 — Server is NOT a git repo
/root/statista was copied (rsync/scp), not cloned. git pull fails with
"not a git repository". Fix: deploy with git archive | ssh … tar -xf -
(above). It overwrites only tracked files; untracked deploy/.env, the SQLite
DB, and /data reports are left alone.
Trap #2 — nginx 502 after rebuild (stale upstream IP)
up -d --build recreates frontend/backend with new Docker IPs, but
nginx keeps running and caches the old IPs → every route returns 502
even though the containers are healthy and listening. Fix: always
docker compose restart nginx as the last step. (Confirmed: frontend logs show
Listening on :3000 while nginx still 502s — that's this, not an app bug.)
Trap #3 — SSH access
- Only
root+ key works.ubuntuis rejected. - Password login is unreliable via Arvan's web console — the noVNC keyboard layout mistypes mixed-case/symbol passwords, so a correct password reads as "wrong". Always SSH from a real terminal, not the web console. If you must reset the password (panel) use all-lowercase + digits and reboot after (resets often don't apply until restart).
- To grant a new machine access: append its public key to
/root/.ssh/authorized_keys(don't rebuild the server to inject keys).
Trap #4 — never "Rebuild / reinstall OS"
Rebuild/reinstall wipes the disk (DB + reports gone) and can change the
IP (breaks API whitelists). Updates go through the deploy steps above —
only ever reboot, never rebuild. Reboots keep IP + data.
Trap #5 — egress ≠ inbound IP
APIs that whitelist by IP (Asian Metal: "1 API = 1 IP") see the egress IP
31.171.101.234, not the SSH IP. Verify any time with:
ssh -i $KEY root@94.101.187.12 'curl -s https://api.ipify.org'
Rollback
up -d --build keeps the previous images. If a deploy is bad:
ssh -i $KEY root@94.101.187.12 \
'cd /root/statista && docker compose -f deploy/docker-compose.yml down && \
docker compose -f deploy/docker-compose.yml up -d && \
docker compose -f deploy/docker-compose.yml restart nginx'
For a code rollback, git archive an earlier commit/tag in step 1, then rebuild.
Health check anytime
ssh -i $KEY root@94.101.187.12 'docker compose -f /root/statista/deploy/docker-compose.yml ps'
ssh -i $KEY root@94.101.187.12 'docker logs deploy-frontend-1 --tail 20'
ssh -i $KEY root@94.101.187.12 'docker logs deploy-backend-1 --tail 20'