docs(operator-guide): PIN hashing is unified (issue #2)

Describes the canonical [security] pin_hash key, the PBKDF2 format
emitted by 'vigilar config set-pin', and the deprecation warning for
the legacy [system] arm_pin_hash. Drops the three-way mismatch
known-limitation.
This commit is contained in:
adlee-was-taken
2026-04-05 12:11:32 -04:00
parent 385bafc73f
commit eb281ad058

View File

@@ -113,8 +113,9 @@ omitted sections behave sensibly.
`.vge` files. `.vge` files.
- `hls_dir` (default `/var/vigilar/hls`): HLS segment output. - `hls_dir` (default `/var/vigilar/hls`): HLS segment output.
- `log_level` (default `"INFO"`): one of DEBUG, INFO, WARNING, ERROR. - `log_level` (default `"INFO"`): one of DEBUG, INFO, WARNING, ERROR.
- `arm_pin_hash` (default `""`): commented out in the sample; set via - `arm_pin_hash` (default `""`): **deprecated.** Still parsed but
`vigilar config set-pin`. ignored at runtime. Use `[security] pin_hash` instead; run
`vigilar config set-pin` to generate the canonical hash.
### `[mqtt]` ### `[mqtt]`
@@ -291,11 +292,10 @@ enabled = false`, `[visitors] enabled = false`, `[highlights] enabled
- `[location] latitude`, `longitude` (default `0.0`): used for sunrise - `[location] latitude`, `longitude` (default `0.0`): used for sunrise
and sunset lookups. and sunset lookups.
- `[security] pin_hash` and `recovery_passphrase_hash`: populated by - `[security] pin_hash` (canonical arm/disarm PIN store) and
`vigilar config set-pin` (the same hash is also stored under `recovery_passphrase_hash`: both populated by
`[system] arm_pin_hash` on the `system` model; both fields exist `vigilar config set-pin`. The `[system] arm_pin_hash` field is
because the web UI uses `[security]` while the CLI helper prints a deprecated; see the `[system]` section above.
`[system]` line — pick one location and stick with it).
## CLI reference ## CLI reference
@@ -344,9 +344,9 @@ sudo -u vigilar /opt/vigilar/venv/bin/vigilar config show \
``` ```
Dumps the parsed config as JSON with `web.password_hash`, Dumps the parsed config as JSON with `web.password_hash`,
`system.arm_pin_hash`, and `alerts.webhook.secret` redacted. Useful `security.pin_hash`, `security.recovery_passphrase_hash`, and
for confirming which defaults Pydantic applied for keys you did not `alerts.webhook.secret` redacted. Useful for confirming which
set. defaults Pydantic applied for keys you did not set.
### `vigilar config set-password` ### `vigilar config set-password`
@@ -365,10 +365,12 @@ prints a `password_hash = "salt_hex:key_hex"` line to paste into
sudo -u vigilar /opt/vigilar/venv/bin/vigilar config set-pin sudo -u vigilar /opt/vigilar/venv/bin/vigilar config set-pin
``` ```
Prompts for an arm/disarm PIN, generates a random 32-byte HMAC key, Prompts for an arm/disarm PIN, derives a salted PBKDF2-SHA256 hash
computes `HMAC-SHA256(key, pin)`, and prints an `arm_pin_hash = (600,000 iterations) via `vigilar.alerts.pin.hash_pin`, and prints a
"secret_hex:mac_hex"` line to paste into `[system]`. Again, no file `pin_hash = "pbkdf2_sha256$salt$dk"` line to paste into `[security]`.
write. Again, no file write. The same hash format is verified identically by
the web arm/disarm endpoint and by `ArmStateFSM` in the event
processor — there is one canonical PIN store.
## Secrets and security ## Secrets and security
@@ -388,9 +390,13 @@ write.
volume on integrity-verified storage (dm-integrity, ZFS with volume on integrity-verified storage (dm-integrity, ZFS with
checksums) or mirror to write-once media. checksums) or mirror to write-once media.
- The web UI password is a scrypt hash set by `vigilar config - The web UI password is a scrypt hash set by `vigilar config
set-password` and stored at `[web] password_hash`. The arm PIN is set-password` and stored at `[web] password_hash`. The arm/disarm
an HMAC stored at `[system] arm_pin_hash` (and/or `[security] PIN is a PBKDF2-SHA256 hash (600k iterations, salted) set by
pin_hash`). `vigilar config set-pin` and stored at `[security] pin_hash`.
A legacy `[system] arm_pin_hash` field is still parsed but ignored
at runtime; if it's set and `[security] pin_hash` is empty, the
service logs a deprecation warning at startup and arm/disarm will
behave as if no PIN were configured until you re-run `set-pin`.
- TLS: `gen_cert.sh` uses `mkcert` if present, otherwise an `openssl` - TLS: `gen_cert.sh` uses `mkcert` if present, otherwise an `openssl`
ECDSA P-256 self-signed certificate valid for 3650 days with SANs ECDSA P-256 self-signed certificate valid for 3650 days with SANs
for `vigilar.local`, `localhost`, `127.0.0.1`, and the detected LAN for `vigilar.local`, `localhost`, `127.0.0.1`, and the detected LAN
@@ -602,10 +608,6 @@ Do not expose port `49735` directly on the WAN; require the tunnel.
`[health]` for real disk policy. `[health]` for real disk policy.
- **No schema migrations.** There is no Alembic (or equivalent) in - **No schema migrations.** There is no Alembic (or equivalent) in
the tree. Rollbacks rely on your backup discipline. the tree. Rollbacks rely on your backup discipline.
- **Duplicate PIN fields.** `vigilar config set-pin` writes to
`[system] arm_pin_hash`, while the web arm/disarm flow reads from
`[security] pin_hash`. Both models exist. If you set one and the
other side does not behave as expected, mirror the value manually.
## Troubleshooting ## Troubleshooting