hephaestus/docker-compose.yml
Local Dev fc43382d48 feat(gateway,hephaestus): forward proxied headers + trust Silent Mode CA
Two pieces from testing "login through hephaestus.x":

1. bns-gateway (public-gateway.mjs, ip: case) — forward the upstream's
   response headers, not just content-type. The old code stripped Location,
   Set-Cookie, and everything else, so redirects from a proxied hostname
   died silently in the browser ("Temporary Redirect" body with no Location
   header). Header set now respects RFC 7230 hop-by-hop exclusions and
   drops Content-Length (we may rewrite HTML for baseHref).

2. Hephaestus stack:
   - forgejo/Dockerfile: tiny extension of the official image that copies
     the Silent Mode Argonautica root CA into the OS trust store, so
     Forgejo's Go client can validate hephaestus.x's cert on OIDC discovery
     calls. Deliberately no `USER git` at the end — parent's s6-overlay
     needs to init as root.
   - docker-compose.yml: switch to `build: ./forgejo` and add
     `extra_hosts: - "hephaestus.x:host-gateway"` so Forgejo can resolve
     hephaestus.x back to the host's Caddy.

Both changes are inert at the moment because Forgejo's ROOT_URL is back at
code.silentmode.st (browsers-without-BCNR-resolvers couldn't complete
OAuth through hephaestus.x because session cookies don't cross origins —
the working UX has the "Sign in with wallet" button on hephaestus.x
delegate to code.silentmode.st). Keep the infrastructure in place for when
Theseus/Ariadne adoption makes it viable to flip ROOT_URL properly.
2026-08-31 16:23:43 +02:00

137 lines
5.6 KiB
YAML

services:
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp" # HTTP/3
environment:
SITE_HOSTNAME: ${SITE_HOSTNAME}
volumes:
# Mount the whole caddy/ dir so both Caddyfile AND certs/ are accessible.
- ./caddy:/etc/caddy:ro
# Static content for hephaestus.x — landing pages served before falling through to Forgejo.
- /var/www/hephaestus.x:/srv/hephaestus.x:ro
- caddy-data:/data
- caddy-config:/config
depends_on:
- forgejo
- auth-proxy
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
auth-proxy:
build: ./auth-proxy
restart: unless-stopped
environment:
ISSUER: ${AUTH_PROXY_ISSUER}
CLIENT_ID: ${AUTH_PROXY_CLIENT_ID}
CLIENT_SECRET: ${AUTH_PROXY_CLIENT_SECRET}
CHALLENGE_DOMAIN: ${AUTH_PROXY_CHALLENGE_DOMAIN}
FORGEJO_REDIRECT_URI: ${FORGEJO_ROOT_URL}user/oauth2/hephaestus-wallet/callback
# Caddy proxies /auth/* → auth-proxy:4000 over the internal network. No public port.
expose:
- "4000"
volumes:
- auth-proxy-keys:/data
forgejo:
# Small extension of the official image that adds the Silent Mode CA cert
# (Argonautica root) to the OS trust store, so Forgejo's Go client can
# validate hephaestus.x's cert on OIDC-discovery calls.
build: ./forgejo
restart: unless-stopped
environment:
USER_UID: "1000"
USER_GID: "1000"
FORGEJO__database__DB_TYPE: postgres
FORGEJO__database__HOST: postgres:5432
FORGEJO__database__NAME: ${POSTGRES_DB}
FORGEJO__database__USER: ${POSTGRES_USER}
FORGEJO__database__PASSWD: ${POSTGRES_PASSWORD}
FORGEJO__server__DOMAIN: ${FORGEJO_DOMAIN}
FORGEJO__server__ROOT_URL: ${FORGEJO_ROOT_URL}
FORGEJO__security__SECRET_KEY: ${FORGEJO_SECRET_KEY}
FORGEJO__security__INTERNAL_TOKEN: ${FORGEJO_INTERNAL_TOKEN}
FORGEJO__oauth2__JWT_SECRET: ${FORGEJO_OAUTH_JWT_SECRET}
# --- Storage backend: Sia via silentmode.st's s3d (public endpoint on port 8600) ---
# Cert is a real LE cert issued to navigate.st (with SAN for s3.silentmode.st);
# Go's default TLS chain trusts it fine. No skip-verify needed.
# The 'hephaestus' bucket was pre-created on the 'sync' account.
# Path prefixes keep repos/LFS/attachments/packages/archives separated within the bucket.
FORGEJO__storage__MINIO_ENDPOINT: ${SIA_STORAGE_ENDPOINT}
FORGEJO__storage__MINIO_ACCESS_KEY_ID: ${SIA_STORAGE_ACCESS_KEY}
FORGEJO__storage__MINIO_SECRET_ACCESS_KEY: ${SIA_STORAGE_SECRET_KEY}
FORGEJO__storage__MINIO_BUCKET: ${SIA_STORAGE_BUCKET}
FORGEJO__storage__MINIO_LOCATION: us-east-1
FORGEJO__storage__MINIO_USE_SSL: "true"
FORGEJO__storage.lfs__STORAGE_TYPE: minio
FORGEJO__storage.lfs__MINIO_BASE_PATH: lfs/
FORGEJO__storage.attachments__STORAGE_TYPE: minio
FORGEJO__storage.attachments__MINIO_BASE_PATH: attachments/
FORGEJO__storage.packages__STORAGE_TYPE: minio
FORGEJO__storage.packages__MINIO_BASE_PATH: packages/
FORGEJO__storage.repo-archive__STORAGE_TYPE: minio
FORGEJO__storage.repo-archive__MINIO_BASE_PATH: archives/
# Live git repos still live on local disk under /data/git — S3 is only for LFS
# and other cold blobs. Never point [repository] itself at S3.
# --- CORS (so hephaestus.x and other BCNR-served pages can list public repos) ---
FORGEJO__cors__ENABLED: "true"
FORGEJO__cors__ALLOW_DOMAIN: "*"
FORGEJO__cors__ALLOW_CREDENTIALS: "false"
FORGEJO__cors__METHODS: "GET,HEAD"
# --- Quota (free tier: 500 MB per user) ---
FORGEJO__quota__ENABLED: "true"
FORGEJO__quota__DEFAULT_GROUPS: free
# --- Registration + signin ---
# Local form is disabled via SHOW_REGISTRATION_BUTTON=false + ALLOW_ONLY_EXTERNAL_REGISTRATION=true.
# DISABLE_REGISTRATION must stay FALSE — it blocks OIDC auto-provisioning too, not just the form.
FORGEJO__service__DISABLE_REGISTRATION: "false"
FORGEJO__service__SHOW_REGISTRATION_BUTTON: "false"
FORGEJO__service__ALLOW_ONLY_EXTERNAL_REGISTRATION: "true"
# OIDC callback creates users automatically using the preferred_username claim (= cashaddr).
FORGEJO__oauth2_client__ENABLE_AUTO_REGISTRATION: "true"
FORGEJO__oauth2_client__ACCOUNT_LINKING: "auto"
FORGEJO__oauth2_client__USERNAME: "preferred_username"
FORGEJO__oauth2_client__UPDATE_AVATAR: "false"
# Skip the web installer wizard — everything is already configured
FORGEJO__server__INSTALL_LOCK: "true"
# hephaestus.x isn't in ICANN DNS, so the Forgejo container can't resolve
# it via its default resolver. Map it to the host gateway so OIDC-discovery
# calls (Forgejo → https://hephaestus.x/auth/…) reach Caddy on the host.
extra_hosts:
- "hephaestus.x:host-gateway"
# Caddy proxies / → forgejo:3000 over the internal network. No public HTTP port.
# 22 stays on 2222 for git-over-SSH (no TLS involved).
expose:
- "3000"
ports:
- "2222:22"
volumes:
- forgejo-data:/data
depends_on:
postgres:
condition: service_healthy
auth-proxy:
condition: service_started
volumes:
postgres-data:
forgejo-data:
auth-proxy-keys:
caddy-data:
caddy-config: