From a60f2cc484c953e70934ce187f68a2106a15081b Mon Sep 17 00:00:00 2001 From: Glazzze <2050408913@qq.com> Date: Fri, 7 Aug 2026 23:27:31 +0800 Subject: [PATCH 1/4] docs(readme): document secure VPS deployment --- README.md | 36 +++++++++++++++++++-- docker/Caddyfile | 3 ++ docker/docker-compose.vps.yaml | 59 ++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 docker/Caddyfile create mode 100644 docker/docker-compose.vps.yaml diff --git a/README.md b/README.md index f055f6f39..496870c6b 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,38 @@ curl -O https://raw.githubusercontent.com/bluewave-labs/checkmate/master/docker/ JWT_SECRET="$(openssl rand -hex 32)" docker compose up -d ``` -Then open http://localhost:52345. If the app is reached at another origin (domain or LAN IP), set `CLIENT_HOST` accordingly. To build the image yourself, run `docker build -f docker/Dockerfile -t checkmate .` from a checkout. For TLS, put any reverse proxy (Caddy, Traefik, nginx) in front of port 52345. +Then open http://localhost:52345. This is the only current Compose file for a direct HTTP installation; the retired `docker/dist-mono/`, `docker/dist/`, and `docker/dist-arm/` directories must not be used. If the app is reached at another origin (domain or LAN IP), set `CLIENT_HOST` accordingly. To build the image yourself, run `docker build -f docker/Dockerfile -t checkmate .` from a checkout. + +### VPS deployment with HTTPS (Caddy) + +For a public VPS, use the dedicated Compose file below. It runs the same all-in-one Checkmate image and MongoDB, adds Caddy for automatic HTTPS, and deliberately does **not** publish Checkmate's internal port `52345` to the host. + +Before starting, point an A/AAAA record for your domain at the VPS and allow inbound TCP ports `80` and `443`. Then download the two VPS deployment files into an empty directory: + +```bash +mkdir checkmate && cd checkmate +curl -O https://raw.githubusercontent.com/bluewave-labs/checkmate/master/docker/docker-compose.vps.yaml +curl -O https://raw.githubusercontent.com/bluewave-labs/checkmate/master/docker/Caddyfile +``` + +Create `.env`, replacing `checkmate.example.com` with your domain: + +```bash +export CHECKMATE_DOMAIN=checkmate.example.com +export CLIENT_HOST="https://${CHECKMATE_DOMAIN}" +export JWT_SECRET="$(openssl rand -hex 32)" +printf 'CHECKMATE_DOMAIN=%s\nCLIENT_HOST=%s\nJWT_SECRET=%s\n' \ + "$CHECKMATE_DOMAIN" "$CLIENT_HOST" "$JWT_SECRET" > .env +``` + +Start the stack and check its status: + +```bash +docker compose -f docker-compose.vps.yaml up -d +docker compose -f docker-compose.vps.yaml ps +``` + +Open `https://checkmate.example.com`, replacing the example domain with yours. Caddy obtains and renews the TLS certificate automatically. Keep the generated `.env` private: `JWT_SECRET` signs login tokens and must not be committed or shared. ### Configuration @@ -110,7 +141,7 @@ The web client needs no configuration by default: it calls the API on the same o | `CLIENT_CONFIG_CLIENT_HOST` | Origin used when the client builds absolute links (invites, status pages); defaults to the browser's current origin | | `CLIENT_CONFIG_LOG_LEVEL` | Browser console log level: `error`, `warn`, `info`, or `debug` (default `error`) | -> **Upgrading from an older image?** The `UPTIME_APP_*` variables (`UPTIME_APP_API_BASE_URL`, `UPTIME_APP_CLIENT_HOST`, `UPTIME_APP_LOG_LEVEL`) are no longer read. In most setups no replacement is needed — the same-origin defaults cover them; if you pointed the client at a different origin, use the `CLIENT_CONFIG_*` equivalents above. The `checkmate-client`, `checkmate-backend`, `checkmate-mongo`, and `checkmate-backend-mono-multiarch` images are no longer updated — switch to `ghcr.io/bluewave-labs/checkmate`, keeping your existing MongoDB service and data volume. +> **Upgrading from an older image?** The `UPTIME_APP_*` variables (`UPTIME_APP_API_BASE_URL`, `UPTIME_APP_CLIENT_HOST`, `UPTIME_APP_LOG_LEVEL`) are no longer read. In most deployments no replacement is needed — the same-origin defaults cover them, including the Caddy example above. If you intentionally serve the API from another origin, use the `CLIENT_CONFIG_*` equivalents. The `checkmate-client`, `checkmate-backend`, `checkmate-mongo`, and `checkmate-backend-mono-multiarch` images are no longer updated — switch to `ghcr.io/bluewave-labs/checkmate`, keeping your existing MongoDB service and data volume. See full installation instructions in the [Checkmate documentation portal](https://checkmate.so/docs). @@ -228,4 +259,3 @@ Here's how you can contribute: [![Star History Chart](https://api.star-history.com/svg?repos=bluewave-labs/checkmate&type=Date)](https://star-history.com/#bluewave-labs/Checkmate&Date) - diff --git a/docker/Caddyfile b/docker/Caddyfile new file mode 100644 index 000000000..3b36e1402 --- /dev/null +++ b/docker/Caddyfile @@ -0,0 +1,3 @@ +{$CHECKMATE_DOMAIN} { + reverse_proxy checkmate:52345 +} diff --git a/docker/docker-compose.vps.yaml b/docker/docker-compose.vps.yaml new file mode 100644 index 000000000..d2daf5027 --- /dev/null +++ b/docker/docker-compose.vps.yaml @@ -0,0 +1,59 @@ +services: + checkmate: + image: ghcr.io/bluewave-labs/checkmate:latest + pull_policy: always + restart: always + environment: + - DB_CONNECTION_STRING=mongodb://mongodb:27017/uptime_db + - CLIENT_HOST=${CLIENT_HOST:?set CLIENT_HOST in your environment} + - JWT_SECRET=${JWT_SECRET:?set JWT_SECRET in your environment} + stop_grace_period: 60s + healthcheck: + test: + [ + "CMD", + "node", + "-e", + "require('http').get('http://localhost:52346/livez',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))", + ] + interval: 15s + timeout: 3s + start_period: 60s + retries: 3 + depends_on: + mongodb: + condition: service_healthy + + mongodb: + image: mongo:8.0 + restart: always + command: ["mongod", "--quiet", "--bind_ip_all"] + volumes: + - mongo-data:/data/db + healthcheck: + test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')", "--quiet"] + interval: 5s + timeout: 30s + start_period: 0s + retries: 30 + + caddy: + image: caddy:2 + restart: always + ports: + - "80:80" + - "443:443" + environment: + - CHECKMATE_DOMAIN=${CHECKMATE_DOMAIN:?set CHECKMATE_DOMAIN in your environment} + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile:ro + - caddy-data:/data + - caddy-config:/config + depends_on: + checkmate: + condition: service_healthy + +volumes: + mongo-data: + caddy-data: + caddy-config: From 6a6c6f07efd6260981a261c43156de5613ac8d7a Mon Sep 17 00:00:00 2001 From: Glazzze <2050408913@qq.com> Date: Sat, 8 Aug 2026 10:13:48 +0800 Subject: [PATCH 2/4] fix(compose): restore healthcheck start intervals Signed-off-by: Glazzze <2050408913@qq.com> --- docker/docker-compose.vps.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/docker-compose.vps.yaml b/docker/docker-compose.vps.yaml index d2daf5027..61c3472c6 100644 --- a/docker/docker-compose.vps.yaml +++ b/docker/docker-compose.vps.yaml @@ -19,6 +19,7 @@ services: interval: 15s timeout: 3s start_period: 60s + start_interval: 2s retries: 3 depends_on: mongodb: @@ -35,6 +36,7 @@ services: interval: 5s timeout: 30s start_period: 0s + start_interval: 1s retries: 30 caddy: From d94347ef4ff99cc202301b96e099acf96616496e Mon Sep 17 00:00:00 2001 From: Glazzze <2050408913@qq.com> Date: Sun, 9 Aug 2026 09:40:05 +0800 Subject: [PATCH 3/4] docs(readme): remove obsolete Docker directory warning Signed-off-by: Glazzze <2050408913@qq.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 496870c6b..f19e7cdf6 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ curl -O https://raw.githubusercontent.com/bluewave-labs/checkmate/master/docker/ JWT_SECRET="$(openssl rand -hex 32)" docker compose up -d ``` -Then open http://localhost:52345. This is the only current Compose file for a direct HTTP installation; the retired `docker/dist-mono/`, `docker/dist/`, and `docker/dist-arm/` directories must not be used. If the app is reached at another origin (domain or LAN IP), set `CLIENT_HOST` accordingly. To build the image yourself, run `docker build -f docker/Dockerfile -t checkmate .` from a checkout. +Then open http://localhost:52345. If the app is reached at another origin (domain or LAN IP), set `CLIENT_HOST` accordingly. To build the image yourself, run `docker build -f docker/Dockerfile -t checkmate .` from a checkout. ### VPS deployment with HTTPS (Caddy) From a43c3cc8702e258c25a946f10f815f47de7d356e Mon Sep 17 00:00:00 2001 From: Glazzze <2050408913@qq.com> Date: Wed, 12 Aug 2026 10:58:28 +0800 Subject: [PATCH 4/4] fix(vps): enable production proxy settings Signed-off-by: Glazzze <2050408913@qq.com> --- docker/docker-compose.vps.yaml | 1 + server/src/app.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/docker/docker-compose.vps.yaml b/docker/docker-compose.vps.yaml index 61c3472c6..d384f2b2c 100644 --- a/docker/docker-compose.vps.yaml +++ b/docker/docker-compose.vps.yaml @@ -7,6 +7,7 @@ services: - DB_CONNECTION_STRING=mongodb://mongodb:27017/uptime_db - CLIENT_HOST=${CLIENT_HOST:?set CLIENT_HOST in your environment} - JWT_SECRET=${JWT_SECRET:?set JWT_SECRET in your environment} + - NODE_ENV=production stop_grace_period: 60s healthcheck: test: diff --git a/server/src/app.ts b/server/src/app.ts index 12e552406..26ea91521 100644 --- a/server/src/app.ts +++ b/server/src/app.ts @@ -31,6 +31,7 @@ export const createApp = ({ }) => { const allowedOrigin = envSettings.clientHost; const app = express(); + app.set("trust proxy", 1); const defaultCorsOptions: CorsOptions = { origin: allowedOrigin, methods: "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS",