diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..fae8d64 --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +# Traefik (set TRAEFIK_ENABLED=true when deploying behind Traefik, e.g. via Coolify) +TRAEFIK_ENABLED=false +TRAEFIK_HOST=vpinball.example.com +NETWORK_NAME=traefik-network diff --git a/.gitignore b/.gitignore index bf56352..6386fe6 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ yarn-error.log* # env files (can opt-in for committing if needed) .env* +!.env.example # vercel .vercel diff --git a/README.md b/README.md index 8d40a34..67e0cc7 100644 --- a/README.md +++ b/README.md @@ -67,13 +67,24 @@ server needed to serve it. ## Docker deploy +No secrets or registry authentication are required to build the image. + +The compose file is set up for a [Coolify](https://coolify.io)/Traefik deployment: it joins an +external Docker network and routes entirely through Traefik labels, with no host port published. +Copy `.env.example` to `.env` and set: + +- `TRAEFIK_ENABLED=true` +- `TRAEFIK_HOST` — the domain to route to this service +- `NETWORK_NAME` — the external Docker network Traefik and this service both join (Coolify + provisions this automatically for projects deployed through it) + ```bash -docker compose build -docker compose up -d +docker compose up -d --build ``` -Serves the static build via nginx on `http://localhost:8080`. No secrets or registry -authentication are required to build the image. +There's no local-only mode — without Traefik routing to it, the container isn't reachable from +the host. To preview the static build locally instead, run `pnpm build` and serve `out/` with any +static file server (e.g. `npx serve out`). ## PWA diff --git a/docker-compose.yml b/docker-compose.yml index 40c13ea..f59ccdb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,23 @@ services: web: build: . - ports: - - "8080:80" restart: unless-stopped + labels: + - "traefik.enable=${TRAEFIK_ENABLED:-false}" + - "traefik.http.middlewares.vpinball-redirect-web-secure.redirectscheme.scheme=https" + - "traefik.http.routers.vpinball-web.middlewares=vpinball-redirect-web-secure" + - "traefik.http.routers.vpinball-web.rule=Host(`${TRAEFIK_HOST}`)" + - "traefik.http.routers.vpinball-web.entrypoints=web" + - "traefik.http.routers.vpinball-web-secure.rule=Host(`${TRAEFIK_HOST}`)" + - "traefik.http.routers.vpinball-web-secure.tls.certresolver=resolver" + - "traefik.http.routers.vpinball-web-secure.entrypoints=web-secure" + - "traefik.http.routers.vpinball-web-secure.middlewares=security-headers@file" + - "traefik.http.services.vpinball-web-secure.loadbalancer.server.port=80" + - "traefik.docker.network=${NETWORK_NAME}" + networks: + - compose_network + +networks: + compose_network: + name: ${NETWORK_NAME} + external: true