Reverse Proxy
Put Opengram behind a reverse proxy for HTTPS termination with Caddy or nginx.
If you are not using Tailscale for HTTPS, a reverse proxy is the standard way to terminate TLS in front of Opengram.
Caddy
Caddy is the simplest option because it handles HTTPS certificates automatically:
opengram.example.com {
reverse_proxy 127.0.0.1:3000
}That is the entire configuration. Caddy will obtain and renew a Let's Encrypt certificate, handle TLS termination, and proxy all traffic to Opengram. SSE streaming works without any additional configuration.
nginx
For nginx, a minimal configuration looks like this:
server {
listen 80;
server_name opengram.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name opengram.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
client_max_body_size 50m; # Match Opengram's maxUploadBytes
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off; # Required for SSE
}
}Trust proxy headers
When Opengram runs behind a reverse proxy, it needs to trust forwarded IP headers so that rate limiting uses the real client IP instead of the proxy's IP. The trusted headers are X-Forwarded-For, X-Real-IP, and CF-Connecting-IP (Cloudflare).
Set the following environment variable:
OPENGRAM_TRUST_PROXY_HEADERS=trueAdd this to your opengram.env file or pass it as a Docker environment variable. Without this setting, all requests will appear to come from 127.0.0.1 and rate limiting will not work correctly.
SSE streaming
Opengram uses Server-Sent Events (SSE) for real-time message streaming. Reverse proxies must not buffer these responses, or users will see messages arrive in delayed chunks instead of streaming smoothly.
- Caddy -- handles SSE correctly by default with no additional configuration.
- nginx -- requires
proxy_buffering off;inside thelocationblock as shown above. Opengram also sends anX-Accel-Buffering: noheader on SSE responses, but setting the directive explicitly is recommended as a safeguard.
Public base URL
After setting up your reverse proxy, configure Opengram to know its public URL. In your opengram.config.json, set:
{
"server": {
"publicBaseUrl": "https://opengram.example.com"
}
}Or use the environment variable instead:
OPENGRAM_PUBLIC_BASE_URL=https://opengram.example.comThis URL is used for generating links in push notifications and other features that need to reference the server externally. Restart Opengram after making this change.