Operations runbook

What Where
Host OpenClaw EC2 i-013cea9c6cd35a538, EIP 34.198.157.4, Amazon Linux 2023
Shell ssh-ec2 ssh --instance-id i-013cea9c6cd35a538 '<cmd>'
Service systemd location-service (user location), 127.0.0.1:18810
Code / venv /opt/location-service/app, /opt/location-service/venv (python3.13)
Data /var/lib/location-service/location.db (SQLite, WAL)
Secrets (box) /etc/location-service/location.env (600, location)
Secrets (Mac) location-tracking/secrets/location.env (gitignored): LOCATION_API_TOKEN, LOCATION_OVERLAND_TOKEN, LOCATION_OWNTRACKS_TOKEN, LOCATION_OPENCLAW_HOOK_TOKEN
TLS Caddy, /etc/caddy/sites/location.caddy (imported by /etc/caddy/Caddyfile)
DNS terraform/ → Route53 A location.evanrthomas.com → OpenClaw EIP (state s3://evanrthomas-tfstate/location-tracking/terraform.tfstate)

Deploy

cd ~/github.com/ethomas2/location-tracking
(cd backend && venv/bin/python -m pytest tests)   # optional
scripts/deploy.sh

Idempotent: copies code/docs/secrets, installs deps only when requirements.txt changed, restarts the service, installs the Caddy site + import, and syncs OpenClaw's hooks config, LOCATION_API_* gateway env and the location skill (from ../openclaw-ec2/skills/location); restarts the OpenClaw gateway only if those changed.

Logs, status, restart

ssh-ec2 ssh --instance-id i-013cea9c6cd35a538 'sudo journalctl -u location-service -n 100 --no-pager'
ssh-ec2 ssh --instance-id i-013cea9c6cd35a538 'systemctl status location-service --no-pager'
ssh-ec2 ssh --instance-id i-013cea9c6cd35a538 'sudo systemctl restart location-service'
curl -s https://location.evanrthomas.com/healthz

The access log is off on purpose (Overland's token may be in the query string).

Rotate a token

  1. Edit secrets/location.env (new value: openssl rand -hex 24).
  2. scripts/deploy.sh (updates the box env file, the gateway env / hooks token, restarts what changed).
  3. Update the client: Overland URL (LOCATION_OVERLAND_TOKEN), OwnTracks password, or anything using the API token. LOCATION_OPENCLAW_HOOK_TOKEN and LOCATION_API_TOKEN are only used on the box; deploy handles them.

Backups

SQLite online backup (safe while running), streamed to the Mac as base64 so the ssh-ec2 banner can't corrupt it:

ssh-ec2 ssh --instance-id i-013cea9c6cd35a538 \
  'sudo -u location python3 -c "import sqlite3; s=sqlite3.connect(\"/var/lib/location-service/location.db\"); d=sqlite3.connect(\"/var/lib/location-service/backup.db\"); s.backup(d); d.close()" && sudo base64 /var/lib/location-service/backup.db && sudo rm /var/lib/location-service/backup.db' \
  2>/dev/null | grep -E '^[A-Za-z0-9+/=]+$' | base64 -d > location-$(date +%F).db
sqlite3 location-$(date +%F).db 'select count(*) from fixes'

Restore: stop the service, copy the file to /var/lib/location-service/location.db owned by location, start it. The root EBS volume is the only other copy; there is no automatic off-box backup yet.

Inspect / clean data

H="Authorization: Bearer $LOCATION_API_TOKEN"
curl -s -H "$H" https://location.evanrthomas.com/events?limit=20 | jq
curl -s -H "$H" -X DELETE "https://location.evanrthomas.com/location/history?device=test-device"

Caddy

/etc/caddy/Caddyfile (owned by openclaw-ec2/scripts/web-proxy.sh) ends with import /etc/caddy/sites/*.caddy; each extra site is a file there. After editing: caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile && sudo systemctl reload caddy. openclaw.evanrthomas.com must keep redirecting to Google login (302).