@@ -0,0 +1,94 @@ |
| 1 | +# Configuration |
| 2 | + |
| 3 | +shithub uses a layered configuration loader. Sources, in increasing-precedence order: |
| 4 | + |
| 5 | +1. **Built-in defaults.** Encoded in `internal/infra/config/Defaults()`. |
| 6 | +2. **TOML file.** Path comes from `SHITHUB_CONFIG` env var, falling back to `/etc/shithub/config.toml`. Absence is fine; bad syntax is a hard error. |
| 7 | +3. **Environment variables.** `SHITHUB_<area>__<key>` (double-underscore separates nested keys). Examples below. |
| 8 | +4. **CLI flag overrides.** Passed in by the caller (mostly `--addr` from `shithubd web`). |
| 9 | + |
| 10 | +After all four merge, `config.Load` applies a small set of named **aliases** (e.g. `SHITHUB_DATABASE_URL` → `db.url`) for backward compatibility, then runs `Validate`. Any validation failure causes `shithubd` to exit non-zero with a one-line error pointing at the offending key. |
| 11 | + |
| 12 | +## Inspecting the active configuration |
| 13 | + |
| 14 | +```sh |
| 15 | +shithubd config print # writes the resolved config as TOML, with secrets redacted |
| 16 | +shithubd config validate # exits non-zero if the resolved config is invalid |
| 17 | +shithubd version # includes a one-line summary of which sinks are configured |
| 18 | +``` |
| 19 | + |
| 20 | +`config print` redacts any field whose name contains `password`, `pass`, `secret`, `key`, `token`, `dsn`, or `url` (URL fields are redacted because they often carry credentials in the userinfo component). |
| 21 | + |
| 22 | +## Reference |
| 23 | + |
| 24 | +| Key | Type | Default | Notes | |
| 25 | +|---|---|---|---| |
| 26 | +| `env` | string | `dev` | One of `dev | staging | prod`. Drives default log format and Sentry environment. | |
| 27 | +| `web.addr` | string | `:8080` | Listen address. | |
| 28 | +| `web.read_timeout` | duration | `30s` | Per-request read timeout. | |
| 29 | +| `web.write_timeout` | duration | `30s` | Per-request write timeout. | |
| 30 | +| `web.shutdown_timeout` | duration | `10s` | Graceful drain on SIGTERM. | |
| 31 | +| `db.url` | string | `""` | Postgres DSN. Aliased by `SHITHUB_DATABASE_URL`. | |
| 32 | +| `db.max_conns` | int | `10` | pgxpool max conns. | |
| 33 | +| `db.min_conns` | int | `0` | pgxpool min conns. | |
| 34 | +| `db.connect_timeout` | duration | `5s` | | |
| 35 | +| `log.level` | string | `info` | One of `debug | info | warn | error`. | |
| 36 | +| `log.format` | string | `text` | One of `text | json`. | |
| 37 | +| `metrics.enabled` | bool | `true` | Mounts `/metrics`. | |
| 38 | +| `metrics.basic_auth_user` | string | `""` | When set together with `pass`, gate `/metrics` behind HTTP Basic. | |
| 39 | +| `metrics.basic_auth_pass` | string | `""` | | |
| 40 | +| `tracing.enabled` | bool | `false` | When true, `tracing.endpoint` is required. | |
| 41 | +| `tracing.endpoint` | string | `""` | OTLP HTTP endpoint, e.g. `http://otel-collector:4318`. | |
| 42 | +| `tracing.sample_rate` | float | `0.05` | Parent-based ratio sampler in [0, 1]. | |
| 43 | +| `tracing.service_name` | string | `shithubd` | OTel resource attribute. | |
| 44 | +| `error_reporting.dsn` | string | `""` | Sentry-protocol DSN (works against GlitchTip). Empty disables. | |
| 45 | +| `error_reporting.environment` | string | `""` | Tag for filtering events. | |
| 46 | +| `error_reporting.release` | string | `""` | Tag for filtering events. | |
| 47 | +| `session.key_b64` | string | `""` | Base64 32-byte AEAD key. Aliased by `SHITHUB_SESSION_KEY`. | |
| 48 | +| `session.max_age` | duration | `720h` | Cookie session lifetime (30 days). | |
| 49 | +| `session.secure` | bool | `false` | Set `Secure` cookie attribute. Enable under TLS (S37 deploy). | |
| 50 | + |
| 51 | +## Env-var examples |
| 52 | + |
| 53 | +```sh |
| 54 | +# Listen elsewhere |
| 55 | +export SHITHUB_WEB__ADDR=:9090 |
| 56 | + |
| 57 | +# Connect to Postgres |
| 58 | +export SHITHUB_DATABASE_URL=postgres://shithub:dev@127.0.0.1:5432/shithub?sslmode=disable |
| 59 | +# (equivalent: export SHITHUB_DB__URL=...) |
| 60 | + |
| 61 | +# JSON logs for prod |
| 62 | +export SHITHUB_LOG__FORMAT=json |
| 63 | +export SHITHUB_LOG__LEVEL=info |
| 64 | + |
| 65 | +# Enable tracing |
| 66 | +export SHITHUB_TRACING__ENABLED=true |
| 67 | +export SHITHUB_TRACING__ENDPOINT=http://otel-collector.bare-metal:4318 |
| 68 | +export SHITHUB_TRACING__SAMPLE_RATE=0.05 |
| 69 | + |
| 70 | +# Error reporting via GlitchTip |
| 71 | +export SHITHUB_ERROR_REPORTING__DSN=https://glitchtip.bare-metal/<project-id> |
| 72 | + |
| 73 | +# Session signing key (deterministic across restarts in prod) |
| 74 | +export SHITHUB_SESSION_KEY=$(openssl rand -base64 32) |
| 75 | + |
| 76 | +# Gate /metrics behind Basic auth |
| 77 | +export SHITHUB_METRICS__BASIC_AUTH_USER=prom |
| 78 | +export SHITHUB_METRICS__BASIC_AUTH_PASS=<long-random> |
| 79 | +``` |
| 80 | + |
| 81 | +## Secrets |
| 82 | + |
| 83 | +- **Never** commit secrets. `.env` is gitignored; production keys live in a systemd `EnvironmentFile=` with mode `0600`. |
| 84 | +- The redaction behavior of `config print` is documented above and tested in `internal/infra/config/config_test.go`. If you add a new secret-bearing field, name it so the redactor matches it (containing `pass`, `secret`, `key`, `token`, `dsn`, `password`, or `url`) — or extend `secretFieldNames` in `internal/infra/config/redact.go`. |
| 85 | +- Log-line redaction is independent (see `docs/internal/observability.md`). Both layers exist on purpose; secrets in env-loaded config and in handler-emitted logs travel different paths. |
| 86 | + |
| 87 | +## Adding a new key |
| 88 | + |
| 89 | +1. Add the field to the appropriate config struct in `internal/infra/config/config.go` with a `toml:` tag. |
| 90 | +2. Set its default in `Defaults()`. |
| 91 | +3. Add validation in `Validate()` if it has invariants. |
| 92 | +4. If it's secret-bearing, confirm its name matches the redactor. |
| 93 | +5. Document it in this file. |
| 94 | +6. Update `.env.example` if the env-var form is the typical usage. |