bluewave-labs / bluewave-labs/Checkmate

Reverse Proxy Configuration

Open
#3,396 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.