mirror of
https://github.com/ArchiveBox/ArchiveBox.git
synced 2026-09-14 11:06:13 +05:00
fix(proxy): address review — secure cookies, zone lookup, token perms
- settings.py: gate CSRF_COOKIE_SECURE/SESSION_COOKIE_SECURE on REVERSE_PROXY_TRUST_FORWARDED_PROTO so HTTPS deployments never send auth cookies over plain HTTP (default-off path unchanged). - docker-compose.yml tunnel-init: resolve the Cloudflare zone by walking the domain labels to the registrable zone, so a subdomain BASE_URL no longer crashes provisioning; write the connector token with 0o600 perms. - Remove .env.example; the env vars are documented inline in docker-compose.yml. - etc/README.md: drop the .env.example reference.
This commit is contained in:
parent
66fea50e81
commit
102a3ab4bc
16
.env.example
16
.env.example
@ -1,16 +0,0 @@
|
||||
# Copy to `.env` next to docker-compose.yml; `docker compose up -d` reads it automatically.
|
||||
# Local default needs none of this — it's only for a public/HTTPS deployment.
|
||||
|
||||
BASE_URL=https://archive.example.com
|
||||
SERVER_SECURITY_MODE=safe-subdomains-fullreplay
|
||||
REVERSE_PROXY_TRUST_FORWARDED_PROTO=True
|
||||
|
||||
# Pick ONE ingress (see docker-compose.yml). Activates its profile with no extra flags:
|
||||
# tunnel = Cloudflare Tunnel (no public IP needed) https = Caddy + Let's Encrypt (public IP)
|
||||
COMPOSE_PROFILES=tunnel
|
||||
|
||||
# Cloudflare API token. For `tunnel`: Account:Cloudflare Tunnel:Edit + Zone:DNS:Edit + Zone:Read.
|
||||
# For `https` (lego DNS-01): Zone:DNS:Edit + Zone:Read. Everything else is provisioned for you.
|
||||
CLOUDFLARE_DNS_API_TOKEN=
|
||||
# CLOUDFLARE_ACCOUNT_ID= # optional (tunnel only); first account is used if unset
|
||||
# ARCHIVEBOX_ACME_EMAIL=admin@example.com # https profile: ACME contact email
|
||||
@ -432,8 +432,11 @@ SECURE_REFERRER_POLICY = "strict-origin-when-cross-origin"
|
||||
if CONFIG.REVERSE_PROXY_TRUST_FORWARDED_PROTO:
|
||||
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
||||
|
||||
CSRF_COOKIE_SECURE = False
|
||||
SESSION_COOKIE_SECURE = False
|
||||
# When the proxy is trusted the deployment is HTTPS end-to-end, so also mark the
|
||||
# admin session + CSRF cookies Secure (never sent over plain HTTP). Scoped to the
|
||||
# same flag so the default http://localhost:8000 setup keeps working unchanged.
|
||||
CSRF_COOKIE_SECURE = CONFIG.REVERSE_PROXY_TRUST_FORWARDED_PROTO
|
||||
SESSION_COOKIE_SECURE = CONFIG.REVERSE_PROXY_TRUST_FORWARDED_PROTO
|
||||
SESSION_COOKIE_HTTPONLY = True
|
||||
SESSION_COOKIE_NAME = f"archivebox_sessionid_{CONSTANTS.COLLECTION_ID}"
|
||||
CSRF_COOKIE_NAME = f"archivebox_csrftoken_{CONSTANTS.COLLECTION_ID}"
|
||||
|
||||
@ -127,7 +127,11 @@ services:
|
||||
except urllib.error.HTTPError as e: return json.load(e)
|
||||
assert DOMAIN and TOKEN, "set BASE_URL (https://archive.example.com) + CLOUDFLARE_DNS_API_TOKEN"
|
||||
acct = os.environ.get("CLOUDFLARE_ACCOUNT_ID", "").strip() or call("GET", "/accounts")["result"][0]["id"]
|
||||
zone = call("GET", f"/zones?name={DOMAIN}")["result"][0]["id"]
|
||||
labels = DOMAIN.split("."); zone = None # DOMAIN may be a subdomain; find its registrable zone
|
||||
for i in range(len(labels) - 1):
|
||||
res = call("GET", f"/zones?name={'.'.join(labels[i:])}")["result"]
|
||||
if res: zone = res[0]["id"]; break
|
||||
assert zone, f"no Cloudflare zone found for {DOMAIN}"
|
||||
NAME = "archivebox-" + DOMAIN.replace(".", "-")
|
||||
ts = call("GET", f"/accounts/{acct}/cfd_tunnel?name={NAME}&is_deleted=false")["result"]
|
||||
tid = ts[0]["id"] if ts else call("POST", f"/accounts/{acct}/cfd_tunnel", {"name": NAME,
|
||||
@ -144,7 +148,7 @@ services:
|
||||
desired = {"type": "CNAME", "name": name, "content": target, "proxied": True, "ttl": 1}
|
||||
call("PUT", f"/zones/{zone}/dns_records/{cname[0]['id']}", desired) if cname else call("POST", f"/zones/{zone}/dns_records", desired)
|
||||
tok = call("GET", f"/accounts/{acct}/cfd_tunnel/{tid}/token")["result"]
|
||||
os.makedirs(os.path.dirname(OUT) or ".", exist_ok=True); open(OUT, "w").write(tok)
|
||||
os.makedirs(os.path.dirname(OUT) or ".", exist_ok=True); open(OUT, "w").write(tok); os.chmod(OUT, 0o600)
|
||||
print(f"[tunnel-init] {NAME} ({tid}): *.{DOMAIN} + {DOMAIN} -> {SERVICE}; connector token -> {OUT}")
|
||||
|
||||
cloudflared:
|
||||
|
||||
@ -6,7 +6,8 @@ E.g. see `nginx.conf` for an example nginx config to serve your archive with SSL
|
||||
|
||||
For the recommended, batteries-included reverse proxy and TLS, you don't need a file
|
||||
here at all — it's built into the main `../docker-compose.yml` as two opt-in, env-var
|
||||
driven profiles (no extra files, Dockerfiles, or scripts). See `../.env.example`:
|
||||
driven profiles (no extra files, Dockerfiles, or scripts) — set the documented env
|
||||
vars in a `.env` next to `../docker-compose.yml`:
|
||||
|
||||
- `https` — Caddy + a `goacme/lego` DNS-01 sidecar fetch a single `*.<your-domain>`
|
||||
wildcard cert (covering unlimited `snap-*` subdomains, ~150 DNS providers, no
|
||||
|
||||
Loading…
Reference in New Issue
Block a user