diverter-device-emulator/deploy
2026-09-24 10:57:06 +01:00
..
Caddyfile another commit 2026-09-24 10:57:06 +01:00
docker-compose.yml another commit 2026-09-24 10:57:06 +01:00
README.md another commit 2026-09-24 10:57:06 +01:00
ship.sh another commit 2026-09-24 10:57:06 +01:00

Deploy on Lightsail

Build the app image on your machine and copy it over SSH. Caddy on the instance terminates HTTPS and proxies to the app container. The app is not published on port 3080. .env is copied from this machine on each deploy. The SQLite file stays in /opt/diverter-device-emulator/data, and the Let's Encrypt certificate stays in a Docker volume.

One-time setup

  1. Create an Ubuntu 24.04 Lightsail instance and attach a static IP.
  2. Pick a hostname and set a DNS A record to that IP. Put the hostname in .env as PORTAL_HOST. Set PORTAL_USER and PORTAL_PASSWORD. Leave ALLOWED_IPS unset.
  3. In the Lightsail IPv4 firewall, allow SSH (22) from your IP, and TCP 80 and 443 from any IPv4 address.
  4. Install Docker and Compose on the instance:
sudo apt-get update && sudo apt-get install -y docker.io docker-compose-v2 && sudo systemctl enable --now docker

Deploy

From this repo, with Docker Desktop running:

./deploy/ship.sh

That uses the diverter-emu host in ~/.ssh/config, including its user and key. The script builds the app image for the server's CPU, copies it with the Caddy image, and runs both. The site is https://<PORTAL_HOST>. Caddy requests the certificate on first start, which needs the DNS record and ports 80 and 443 already open.

Responses send Cache-Control / Cloudflare-CDN-Cache-Control: no-store so Cloudflare does not cache HTML, CSS, or JS. CSS and JS URLs are also versioned, so a deploy does not keep serving a stale edge copy. After this change is live, purge Cloudflare once (Caching → Purge Everything) so the old /styles.css and /app.js drop out.

Logs:

ssh diverter-emu sudo bash -c 'cd /opt/diverter-device-emulator && docker compose logs -f'