Files
wweir dab041b9f6 docs(sowerd): keep the site-route authority rule in one place
Second half of the review: the rationale for `authority` had been written into
every comment that touched it, which is three copies to keep in sync. Keep the
argument in docs/security.md and leave the config example, the struct comment
and the constants stating only what the value does.

- docs/security.md: record "an upstream trusting X-Forwarded-Host" under
  Rejected Directions, where the document already collects declined designs,
  instead of inside the new rule section; merge the per-route bullet into the
  client-controlled one they overlapped with.
- ARCHITECTURE.md: the sentence added last commit left the fake-site rationale
  dangling after the site-route clause; split it back into one claim per
  sentence.
- docs/plans/site-routing.md: the plan states the unconditional Host rewrite as
  a decision of its time, so it gets a forward note to the authoritative
  document rather than a rewrite of the record.
- config/sowerd.go: clearer validation error ("unknown value", naming both
  accepted values) and a tighter comment; no behavior change beyond the
  message.
2026-10-12 16:09:19 +08:00

54 lines
2.4 KiB
TOML

# Sowerd configuration example (TOML format)
# This is the daemon configuration for the sower server
# Logging configuration
log_level = "info" # Log level: debug, info, warn, error
# Server configuration
serve_ip = "0.0.0.0" # IP address to listen on for ports 80 and 443
password = "change_me" # Client auth password (required; replace the placeholder)
fake_site = "/var/www" # Fallback fake site directory or address (default: /var/www)
# Site routing: map domains to upstream URLs for fallback traffic.
# When a TLS connection does not match sower transport,
# the SNI is looked up here. Unmatched connections fall through to fake_site.
# Custom certificate mode requires the certificate SANs to cover all routed domains.
# Route domains become public once autocert issues their certificates
# (Certificate Transparency), so an upstream that cannot authenticate its own
# visitors needs the optional auth gate below.
#
# [[site_routes]]
# domains = ["a.example.com", "b.example.com"]
# upstream = "http://127.0.0.1:8080"
#
# authority selects the Host header sent upstream: "upstream" (the default)
# sends the route's upstream host, "client" forwards the client's authority,
# for an upstream that validates that authority itself (see docs/security.md).
# authority = "client"
#
# [site_routes.auth]
# username = "admin" # Both fields are required to enable the gate;
# password = "change_me" # an empty block leaves the route open.
# The gate also covers WebSocket upgrades, but browsers cannot set Authorization
# on a WS handshake and reconnecting clients feed the per-IP lockout: verify
# before gating one (see docs/security.md).
#
# [site_routes.routes]
# "/ws" = "http://127.0.0.1:8082"
#
# [[site_routes]]
# domains = ["c.example.com"]
# upstream = "https://backend.example.com"
#
# URL userinfo credentials are sent to the upstream as HTTP Basic auth:
# upstream = "http://user:pass@127.0.0.1:8080"
# SSL/TLS certificate configuration
[cert]
email = "your-email@example.com" # Email for Let's Encrypt certificate
# domains = ["proxy.example.com"] # Issuance whitelist beyond site_routes (autocert mode).
# The FIRST entry answers TLS handshakes for unknown/empty SNI: keep it a concrete
# domain, not a wildcard. See docs/security.md.
cert = "" # Path to custom certificate file (optional)
key = "" # Path to custom private key file (optional)