diff --git a/DOCKER.md b/DOCKER.md index 05ec0c4..a5ceda5 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -61,6 +61,8 @@ Additional environment variables are optional: | `FEDERATION` | `1` | Controls whether the instance announces itself and crawls peers (`1`) or stays isolated (`0`). | | `PRIVATE` | `0` | Restricts public visibility and disables chat/message endpoints when set to `1`. | | `CONNECTION` | `/dev/ttyACM0` | Serial device, TCP endpoint, or Bluetooth target used by the ingestor to reach the radio. | +| `MIN_THREADS` | `16` | Minimum Puma worker threads kept warm on the web service. | +| `MAX_THREADS` | `96` | Maximum Puma worker threads on the web service. Each active `/api/events` (SSE) stream pins one thread, so keep this above your peak concurrent SSE clients plus API/ingest headroom. | The ingestor posts to the URL configured via `INSTANCE_DOMAIN` (defaulting to `http://web:41447` in the provided compose file). Use `CHANNEL_INDEX` to select @@ -116,6 +118,84 @@ docker compose pull docker compose up -d ``` +## Running behind a reverse proxy (TLS + static assets) + +The web container serves plain HTTP on port `41447`. For any public deployment, +terminate TLS in a reverse proxy in front of it. A ready-to-adapt nginx example +lives at [`deploy/nginx.example.conf`](deploy/nginx.example.conf); the notes +below explain the parts that matter. + +**Forwarded headers (required).** The app derives its public scheme and host — +used for `INSTANCE_DOMAIN`, page metadata, the sitemap, and federation links — +from `X-Forwarded-Proto` and the `Host` header. Forward both, or generated URLs +resolve to the wrong scheme/host: + +```nginx +proxy_set_header Host $host; +proxy_set_header X-Forwarded-Proto $scheme; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +``` + +**Static-asset caching.** Every JS module and `base.css` is served with a +`?v=` query, and the layout emits one `