Merge pull request 'docs: generalize deployment section to any reverse proxy' (#73) from docs/reverse-proxy-generic into main
Reviewed-on: #73 Reviewed-by: Colby Whitlock <whitlocktech@gmail.com>
This commit is contained in:
49
README.md
49
README.md
@@ -8,7 +8,7 @@ A full-stack app in one repo:
|
||||
|
||||
- **Backend** — Node.js + Express REST API (layered `router → controller → model → db`), MariaDB, a provider-agnostic session layer (JWT cookie for web, bearer tokens for mobile, pluggable SSO).
|
||||
- **Frontend** — React + Vite single-page app (public site, wiki, and the admin panel), dark "gothic" theme (Cinzel + Georgia).
|
||||
- **Deploy** — Docker Compose (app + MariaDB) behind a Pangolin reverse proxy. Express serves the built SPA in production.
|
||||
- **Deploy** — Docker Compose (app + MariaDB) behind a reverse proxy (Pangolin, Nginx, Caddy, Traefik, …). Express serves the built SPA in production.
|
||||
- **Shard link** — a live bridge to the in-game ServUO shard through the **uo-link** sidecar ([RunicGateway/link](https://gitea.whitlocktech.com/RunicGateway/link)): the site ingests a live event feed and makes server-side REST calls to show shard status, economy, staff presence, IDOCs, live activity, and per-character sheets. See [Shard integration (uo-link)](#shard-integration-uo-link).
|
||||
|
||||
The design reference is [BACKEND_DESIGN.md](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/website/BACKEND_DESIGN.md) (API contract, schema, security), in the [**RunicGateway/docs**](https://gitea.whitlocktech.com/RunicGateway/docs) repo — where all project documentation now lives.
|
||||
@@ -32,7 +32,7 @@ The design reference is [BACKEND_DESIGN.md](https://gitea.whitlocktech.com/Runic
|
||||
- [Environment variables](#environment-variables)
|
||||
- [Security](#security)
|
||||
- [Logging](#logging)
|
||||
- [Deployment behind Pangolin](#deployment-behind-pangolin)
|
||||
- [Deployment behind a reverse proxy](#deployment-behind-a-reverse-proxy)
|
||||
|
||||
---
|
||||
|
||||
@@ -46,7 +46,7 @@ The design reference is [BACKEND_DESIGN.md](https://gitea.whitlocktech.com/Runic
|
||||
| Frontend | React 18, Vite 5, React Router 6 |
|
||||
| Email | Nodemailer via Gmail OAuth2 (configured in admin), with a `mailto:` fallback |
|
||||
| API docs | OpenAPI 3.0 via `swagger-autogen`, served with `swagger-ui-express` at `/api/docs` |
|
||||
| Deploy | Docker Compose, Pangolin reverse proxy |
|
||||
| Deploy | Docker Compose, any reverse proxy (Pangolin, Nginx, Caddy, Traefik, …) |
|
||||
|
||||
---
|
||||
|
||||
@@ -355,7 +355,7 @@ Copy `.env.example` (Compose) or `server/.env.example` (local) and fill in. **`.
|
||||
| `DB_ROOT_PASSWORD` | — | MariaDB root (Compose only) |
|
||||
| `JWT_SECRET` | — | **required** — long random string; signs session, mobile, and SSO-flow tokens |
|
||||
| `JWT_EXPIRES_IN` | `1d` | web session token + cookie lifetime |
|
||||
| `COOKIE_SECURE` | `auto` | `auto` = Secure only over HTTPS (works on LAN HTTP + Pangolin HTTPS) |
|
||||
| `COOKIE_SECURE` | `auto` | `auto` = Secure only over HTTPS (works on LAN HTTP + proxy HTTPS) |
|
||||
| `COOKIE_NAME` | `rg_token` | changing it on a live instance invalidates existing sessions |
|
||||
| `BRAND_*` | Runic Gateway | instance branding (name, tagline, colors, logo/hero/favicon) — see [Branding](#branding) |
|
||||
| `SECRET_ENC_KEY` | — | **required in prod** — key for AES-256-GCM encryption of stored OAuth client secrets. Dev falls back to a key derived from `JWT_SECRET` (with a warning) |
|
||||
@@ -460,7 +460,7 @@ run this repo as UOMysticmoon.
|
||||
**Platform**
|
||||
|
||||
- `helmet`, admin routes `noindex` + `robots.txt` disallow, `trust proxy` for correct client IPs
|
||||
behind Pangolin (see `TRUST_PROXY`), first admin seeded from env (no hardcoded credentials),
|
||||
behind a reverse proxy (see `TRUST_PROXY`), first admin seeded from env (no hardcoded credentials),
|
||||
`.env` git-ignored. Passwords and request bodies are never logged. Email sends through Gmail
|
||||
OAuth2 configured in the admin (refresh token stored AES-GCM-encrypted, never in env); the
|
||||
contact form falls back to a `mailto:` link when unconfigured.
|
||||
@@ -487,13 +487,42 @@ bind-mounted to `./logs/app.log` and `docker compose logs -f app` shows the cons
|
||||
|
||||
---
|
||||
|
||||
## Deployment behind Pangolin
|
||||
## Deployment behind a reverse proxy
|
||||
|
||||
`docker compose up -d --build` exposes the `app` container on `0.0.0.0:3000` (no `127.0.0.1`
|
||||
binding) so Pangolin can reach it. Point a Pangolin resource at `app:3000`. Because `COOKIE_SECURE`
|
||||
defaults to `auto`, the admin login works both directly via the LAN IP over HTTP **and** through
|
||||
Pangolin over HTTPS — no config change needed. MariaDB stays on the private Compose network
|
||||
(no published port by default); data persists in the `dbdata` volume, uploads in `uploads`.
|
||||
binding) so a reverse proxy — Pangolin, Nginx, Caddy, Traefik, etc. — can reach it. Point the
|
||||
proxy at `app:3000` (or the host's `:3000` if the proxy runs outside Compose) and terminate TLS
|
||||
there. Because `COOKIE_SECURE` defaults to `auto`, the admin login works both directly via the
|
||||
LAN IP over HTTP **and** through the proxy over HTTPS — no config change needed. MariaDB stays on
|
||||
the private Compose network (no published port by default); data persists in the `dbdata` volume,
|
||||
uploads in `uploads`.
|
||||
|
||||
Set `TRUST_PROXY` so Express reads the real client IP from the proxy's `X-Forwarded-For` header
|
||||
(see [Environment variables](#environment-variables)) — required for rate limiting, bot scoring,
|
||||
and correct logging. Forward the standard `X-Forwarded-For` and `X-Forwarded-Proto` headers from
|
||||
your proxy.
|
||||
|
||||
Minimal proxy examples:
|
||||
|
||||
```nginx
|
||||
# Nginx
|
||||
location / {
|
||||
proxy_pass http://app:3000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
```
|
||||
|
||||
```caddy
|
||||
# Caddy — Caddyfile (automatic HTTPS; forwards X-Forwarded-* by default)
|
||||
your.domain {
|
||||
reverse_proxy app:3000
|
||||
}
|
||||
```
|
||||
|
||||
**Pangolin:** create a resource targeting `app:3000`; it forwards the required headers and
|
||||
terminates HTTPS out of the box, so no extra configuration is needed.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user