1 Commits
Author SHA1 Message Date
sneak c90afd9e35 Make the HSTS max-age configurable with HSTS_MAX_AGE (closes #271)
check / check (push) Failing after 3m30s
HSTS_MAX_AGE, a Go duration, sets the max-age of the
Strict-Transport-Security header. Unset, it is ten years (87600h);
0 sends no header at all. A negative value, or one that is not a
whole number of seconds, stops startup like an unparseable one.
includeSubDomains and preload stay in the header. The value is shown
on /settings and in the startup log, and the README's HSTS section
now says what each part of the header commits the operator to.

Model: opus-5-5
2026-10-12 22:37:56 +00:00
+7 -15
View File
@@ -895,10 +895,9 @@ Strict-Transport-Security: max-age=315360000; includeSubDomains; preload
``` ```
`HSTS_MAX_AGE` sets `max-age`, in seconds. `includeSubDomains` and `preload` are `HSTS_MAX_AGE` sets `max-age`, in seconds. `includeSubDomains` and `preload` are
always part of the header. A browser that receives the header over HTTPS refuses always part of the header. A browser that sees the header refuses plaintext HTTP
plaintext HTTP to that hostname until `max-age` runs out, whatever else is to that hostname until `max-age` runs out, whatever else is served there, so
served there, so terminate TLS on a hostname you are prepared to keep on HTTPS. terminate TLS on a hostname you are prepared to keep on HTTPS.
Browsers ignore the header when it arrives over plain HTTP.
`includeSubDomains` extends this to every subdomain of the hostname webhooker is `includeSubDomains` extends this to every subdomain of the hostname webhooker is
served at. Served at `hooks.example.com`, it covers every name under served at. Served at `hooks.example.com`, it covers every name under
@@ -912,10 +911,10 @@ every browser that ships the list, even for users who have never visited it, and
removal takes months to reach those browsers, so treat a listing as permanent. removal takes months to reach those browsers, so treat a listing as permanent.
Setting `HSTS_MAX_AGE=0` later stops the header being sent, but a browser that Setting `HSTS_MAX_AGE=0` later stops the header being sent, but a browser that
already received it over HTTPS does not forget it. That browser keeps refusing already saw it does not forget it. That browser keeps refusing plaintext HTTP
plaintext HTTP until the `max-age` it saw runs out. Only a `max-age=0` header until the `max-age` it saw runs out. Only a `max-age=0` header received over
received over HTTPS clears it sooner. webhooker never sends one; a reverse proxy HTTPS clears it sooner. webhooker never sends one; a reverse proxy in front of
in front of it can. it can.
## Backup, Restore, and Upgrades ## Backup, Restore, and Upgrades
@@ -964,13 +963,6 @@ with an error naming it: for `webhooker.db` the server and `webhooker resetpw`
stop, and an event or archive database fails as a damaged one does (see stop, and an event or archive database fails as a damaged one does (see
[Database Architecture](#database-architecture)). [Database Architecture](#database-architecture)).
**`DATA_DIR` must be on a local filesystem.** Under WAL, SQLite maps each
database's `-shm` file into memory, which network filesystems (NFS, SMB/CIFS) do
not support reliably, so they are not supported. webhooker does not check which
filesystem `DATA_DIR` is on. An error reading `disk I/O error (522)`
(`SQLITE_IOERR_SHORT_READ`) points at the storage under `DATA_DIR`, not at
locking; moving `DATA_DIR` to a plain local disk is the first thing to try.
Configuration is **not** in `DATA_DIR` — it comes from the environment and from Configuration is **not** in `DATA_DIR` — it comes from the environment and from
a `.env` file read out of the process working directory. Back that up with your a `.env` file read out of the process working directory. Back that up with your
deployment config, separately. deployment config, separately.