getRemoteIp took a trusted proxy's X-Real-IP first, otherwise the leftmost
X-Forwarded-For entry. A proxy that forwards a client-sent X-Real-IP
unchanged (Caddy, HAProxy) or appends to X-Forwarded-For leaves both values
to the client. X-Forwarded-For is now read from the right, skipping trusted
proxies. X-Real-IP is believed only when it agrees with that hop or stands
alone, and a disagreement falls back to the proxy's own address.
The documented Caddyfile and the docs reverse-proxy generator now overwrite
X-Real-IP with the address Caddy saw.
Fold the standalone 3x-ui-docs project (Next.js 16 + Fumadocs, deployed to
docs.sanaei.dev) into docs/ so the panel and its documentation share a single
source of truth, the way sing-box keeps its docs in-tree. The old repo becomes
redundant and can be retired.
- Import the full site under docs/ (app, components, content, lib, public,
scripts, config). The self-contained pnpm project sits alongside the existing
engineering notes with no filename collisions.
- Re-point "Edit on GitHub" links from MHSanaei/3x-ui-docs to this repo's
docs/content/docs path (docs/lib/shared.ts, docs/app/.../page.tsx).
- Add docs-ci.yml and docs-deploy.yml under .github/workflows/, scoped to
docs/** and run with working-directory: docs, since GitHub only runs
workflows from the repo-root .github/. deploy-static.yml's GitHub Pages
publish (CNAME docs.sanaei.dev) carries over unchanged.
Follow-up (outside this commit): attach the docs.sanaei.dev custom domain to
this repository's Pages (or set the Vercel project's root directory to docs),
confirm the site is live from the monorepo, then delete MHSanaei/3x-ui-docs.