bluewave-labs / bluewave-labs/Checkmate
Reverse Proxy Configuration
- Dominant language
- TypeScript
- Stars
- 10.8k
- Forks
- 1.2k
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 68
Description
**Is your feature request related to a problem? Please describe.**
It would be great if Reverse Proxy Setup could be officially documented.
This is also asked in:
- https://github.com/bluewave-labs/Checkmate/issues/2096
- https://github.com/bluewave-labs/Checkmate/discussions/3022
- https://github.com/bluewave-labs/Checkmate/issues/1734#issuecomment-3190384811
**Describe the solution you'd like**
Document how to implement Reverse Proxies.
I use this with Caddy.
`Caddyfile`:
```
# Example and Guide
# https://caddyserver.com/docs/caddyfile/options
# General Options
{
# (Optional) Debug Mode
# debug
# Disable Admin API
admin off
# TLS Options
# (Optional) Disable Certificates Management (only if SSL/TLS Certificates are managed by certbot or other external Tools)
auto_https disable_certs
}
# (Optional) Only if SSL/TLS Certificates are managed by certbot or other external Tools and Custom Logging is required
{$APPLICATION_HOSTNAME} {
tls /certificates/{$APPLICATION_CERTIFICATE_DOMAIN}/{$APPLICATION_CERTIFICATE_CERT_FILE:fullchain.pem} /certificates/{$APPLICATION_CERTIFICATE_DOMAIN}/{$APPLICATION_CERTIFICATE_KEY_FILE:privkey.pem}
log {
output file /var/log/{$APPLICATION_HOSTNAME}/access.json {
roll_size 100MiB
roll_keep 5000
roll_keep_for 720h
roll_uncompressed
}
format json
}
# Backend Reverse Proxy goes to a different Container (use IPv4 Connection)
# reverse_proxy /api/* http://0.0.0.0:52345
# Application Reverse Proxy goes to a different IP Address (use IPv6 Connection)
reverse_proxy /api/* http://[::1]:52345
# Default Reverse Proxy (use IPv4 Connection)
# reverse_proxy http://0.0.0.0:{$APPLICATION_PORT}
# Default Reverse Proxy (use IPv6 Connection)
reverse_proxy http://[::1]:{$APPLICATION_PORT}
}
```
Environment Variables:
```
Environment=UPTIME_APP_API_BASE_URL=https://checkmate.MYDOMAIN.TLD/api/v1
Environment=UPTIME_APP_CLIENT_HOST=https://checkmate.MYDOMAIN.TLD
```
Since I use `podman` with `pasta`, I cannot have 2 containers use the same Port Number, thus I need to bind-mount a Custom `/etc/nginx/conf.d/default.conf` File inside the `client` Container, so that Caddy can bind to Port 80/443, while nginx can e.g. usee Port 8080:
```
server {
listen 8080;
listen [::]:8080;
server_name checkmate.MYDOMAIN.TLD;
server_tokens off;
# location /.well-known/acme-challenge/ {
# root /var/www/certbot;
# }
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
# location /api/ {
# proxy_pass http://server:5000/api/;
# proxy_http_version 1.1;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# }
location /api-docs/ {
proxy_pass http://checkmate-server:5000/api-docs/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
**Describe alternatives you've considered**
N/A
**Additional context**
Some thoughts should also be put into security, particularly with regards to CORS.
In particular the `TOKEN_TTL` Environment Variable must **NOT** be set, otherwise the Server will Issue the following Message in the Logs:
```
ValidationError: The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false (default). This could indicate a misconfiguration which would prevent express-rate-limit from accurately identifying users. See https://express-rate-limit.github.io/ERR_ERL_UNEXPECTED_X_FORWARDED_FOR/ for more information.
at Object.xForwardedForHeader (file:///app/node_modules/express-rate-limit/dist/index.mjs:335:13)
at wrappedValidations. [as xForwardedForHeader] (file:///app/node_modules/express-rate-limit/dist/index.mjs:577:22)
at Object.keyGenerator (file:///app/node_modules/express-rate-limit/dist/index.mjs:679:20)
at file:///app/node_modules/express-rate-limit/dist/index.mjs:737:32
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async file:///app/node_modules/express-rate-limit/dist/index.mjs:718:5 {
code: 'ERR_ERL_UNEXPECTED_X_FORWARDED_FOR',
help: 'https://express-rate-limit.github.io/ERR_ERL_UNEXPECTED_X_FORWARDED_FOR/'
}
```
There is a workaround at https://github.com/bluewave-labs/Checkmate/issues/2937#issuecomment-3567726643
Or you can write a custom entrypoint such as:
```
#!/bin/bash
# Enable trust_proxy
sed -i "s|const app = express();|const app = express();\n app.set('trust proxy', 1);|" dist/app.js
# Run app
node dist/index.js
```
With `podman` you can just use it within your `server.container` File:
```
# Patch to allow trust_proxy
Entrypoint=/patched_entrypoint.sh
# Volumes
Volume=./patched_entrypoint.sh:/patched_entrypoint.sh:ro,Z
```
EDIT 1: but what would be way better, would be to have an Environment Variable we can use to specify how many Proxies to trust, then set that within `app.js` such as (pseudo-code) ` app.set('trust proxy', {ENV:CHECKMATE_TRUST_PROXY_NUMBER=0});` (default to 0).
Contributor guide
Research direction
Use the supplied Caddyfile and /etc/nginx/conf.d/default.conf examples as starting references, along with the app.js and dist/app.js entry points mentioned for trust-proxy behavior. Document reverse-proxy setup, environment variables, and the relevant CORS and trust-proxy security considerations; done means a newcomer can configure a supported proxy without relying on the linked discussions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- express, nginx
- Domain
- backend, documentation, infrastructure
- Issue type
- Documentation
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100