Environment Variables
None of these need to be set; the defaults work. They matter at deployment time: the port, which sites to watch, and how often to check them.
An environment variable overrides the matching appsettings.json value. Nested keys use a double underscore, so Docs:PageSize becomes Docs__PageSize.
Hosting
| Variable | Default | What it does |
|---|---|---|
ASPNETCORE_URLS |
http://localhost:5000 |
Address and port. The Docker image sets http://+:8080. |
ASPNETCORE_ENVIRONMENT |
Production |
Development logs more. |
| Proxy__Trusted__0 | none | A proxy IP or CIDR network allowed to set X-Forwarded-For. |
| Proxy__TrustAny | false | Honours the forwarded header from any caller. |
Behind a reverse proxy
Rate limits are counted per reader IP. Behind nginx, Caddy, or a container ingress, every request arrives from the proxy instead, so the API budget of thirty per minute ends up shared by everyone, and a single bot can close it out for the whole site.
Listing your proxy fixes it. Loopback is trusted already, so a proxy on the same host needs nothing:
Proxy__Trusted__0=10.0.0.0/8
Proxy__Trusted__1=172.18.0.5Proxy__TrustAny=true skips the list entirely, useful when your ingress has no fixed address. It also means any caller who can reach the port may claim any IP, so it suits a container that only its proxy can talk to, and little else. Warden logs the choice at startup.
Monitoring
What to check, and how often, lives in content/config.json, not here; see the guide for the monitoring block. The database file's location is the one deployment concern:
{
"Monitoring": {
"DatabasePath": "data/warden.db"
}
}| Variable | Default | What it does |
|---|---|---|
Monitoring__DatabasePath |
data/warden.db |
Where the SQLite heartbeat history lives, relative to the app unless rooted. |
DatabasePath |
none | A shorter name for the same setting, simpler to type in a docker-compose.yml environment: block. Takes priority over Monitoring__DatabasePath when both are set. |
Content
| Variable | Default | What it does |
|---|---|---|
Docs__RootPath |
content |
Path to your content folder. |
Docs__EnableHotReload |
true |
Rebuilds when a file changes. |
Docs__DefaultPage |
index |
Filename used as a folder's own page. |
Docs__BasePath |
none | Subdirectory prefix, such as /updates. |
Docs__ContentSecurityPolicy |
built in | Replaces the default policy. |
Docs__Themes__Name |
none | Built-in theme name, overriding config.json. |
Docs__BasePath prefixes every internal link. Give a static export the same value with --base-path so the two agree.
Docs__Themes__Name suits a deployment that wants a different look than the one in version control. It outranks theme in config.json, and --theme <name> on the command line outranks both.
Health checks
GET /health answers 200 with the current build version, page count, and uptime in seconds:
{ "status": "ok", "buildVersion": 17, "pages": 42, "uptimeSeconds": 3600 }It answers 503 with "status": "empty" when no content has been built. That's the signal an external uptime monitor watching this deployment should watch for. The route carries no rate limit, so polling it every few seconds is fine.
Logs
Warnings and errors go to logs/warden-<date>.log beside the binary, rolling daily and keeping a fortnight. Everything at Information stays on the console only, so the file itself stays small.
The Serilog section of appsettings.json holds these settings, so pointing path at a mounted volume or lowering restrictedToMinimumLevel are both single-line changes. Setting Serilog__WriteTo__1__Args__path in the environment works too.
In a container
services:
warden:
image: warden
environment:
- ASPNETCORE_ENVIRONMENT=Production
volumes:
- ./content:/app/content
- ./data:/app/dataMount data/ too. That's where the SQLite database lives, and without a volume the check history resets on every container recreate.
WARNING
If a setting seems ignored, check for a single underscore where a double belongs. Docs_PageSize is nothing at all; Docs__PageSize is the setting you meant.