# J621 — frontend-only deployment: SPA + nginx proxy + Tailscale sidecar. # # cd deploy && cp .env.example .env # TS_AUTHKEY at minimum # docker compose -f compose.frontend.yml up -d # # Funnel: https://..ts.net (443) serves the SPA. # On first start the SPA asks for a backend (/setup): point it at a # backend-only deployment (e.g. https://j621-backend..ts.net:8443), # leave it blank to serve one yourself, or stay in local mode. # # There is no backend in this compose, so /api answers 502 here until the SPA # is configured to call one elsewhere. name: j621-frontend-deploy services: frontend: image: ${J621_REGISTRY:-gitea.rainbow-herring.ts.net/jakebreath}/j621-frontend:${J621_TAG:-latest} build: context: .. dockerfile: deploy/J621-Frontend restart: unless-stopped nginx: image: nginx:1.29-alpine restart: unless-stopped volumes: - ./nginx-proxy.conf:/etc/nginx/conf.d/default.conf:ro depends_on: frontend: condition: service_healthy healthcheck: test: ["CMD-SHELL", "wget -q --spider http://127.0.0.1/nginx-health || exit 1"] interval: 30s timeout: 3s retries: 3 start_period: 10s tailscale: image: tailscale/tailscale:latest restart: unless-stopped # Shares the nginx service's network namespace: 127.0.0.1:80 is the proxy. network_mode: "service:nginx" environment: TS_AUTHKEY: ${TS_AUTHKEY:?Set TS_AUTHKEY in deploy/.env} TS_HOSTNAME: ${TS_HOSTNAME:-j621-frontend} TS_AUTH_ONCE: "true" TS_STATE_DIR: /var/lib/tailscale TS_SERVE_CONFIG: /config/serve.json volumes: - ./tailscale-state:/var/lib/tailscale - ./serve.frontend.json:/config/serve.json:ro - /etc/ssl/certs:/etc/ssl/certs:ro depends_on: nginx: condition: service_healthy healthcheck: test: ["CMD", "tailscale", "status"] interval: 30s timeout: 5s retries: 3 start_period: 30s