milestone 13 discrepancies: redact credentials from urls in logs, metrics and cli output
This commit is contained in:
+105
-42
@@ -23,21 +23,24 @@ Serves DNS until SIGINT or SIGTERM.
|
||||
| `--config FILE` | Seed configuration file (default `/etc/nxdns/config.zon`). Read only when the database has never been configured. |
|
||||
| `--web-dev DIR` | Serve the web interface from DIR instead of the embedded assets, with no cache headers. Development only. |
|
||||
|
||||
Seeding failures are not treated as configuration faults here: a seed file that
|
||||
is unparseable, oversized or invalid prints its diagnostics and exits 1, not 2.
|
||||
See [exit codes](#exit-codes).
|
||||
A seed file that is unparseable, oversized or invalid prints its diagnostics and
|
||||
exits 2 — the same code `check` and `import` give for the same file. See
|
||||
[exit codes](#exit-codes).
|
||||
|
||||
## `check`
|
||||
|
||||
Validates the configuration and probes the upstreams. Exit 0 when clean, 2 when
|
||||
it found problems. It always reports every problem, not just the first. What it
|
||||
checks, in order:
|
||||
Validates the configuration and probes the upstreams. Exit 0 when it found no
|
||||
failures, 2 when it found one. It always reports every problem, not just the
|
||||
first. What it checks, in order:
|
||||
|
||||
1. Which source to check (see [source selection](#source-selection)).
|
||||
2. Full validation — the same rules `import` enforces.
|
||||
3. For each enabled DoH/DoT listener: certificate and key are readable (FAIL if
|
||||
not), and the key's permissions are owner-only (WARN if any group or other
|
||||
bit is set; the WARN does not change the exit code).
|
||||
3. For each enabled DoH/DoT listener: both PEM files are read and the key is
|
||||
tested against the certificate, through the same `CertStore.init` the
|
||||
listeners boot with. A file that is missing, unreadable, too large or
|
||||
unparseable, and a key that does not belong to the certificate, are all FAIL.
|
||||
The key's permissions are a separate finding: WARN when any group or other
|
||||
bit is set, which does not change the exit code.
|
||||
4. A live probe: one real A query for `example.com` through every enabled
|
||||
upstream, driving the same pool and failover machinery the server uses, with
|
||||
`upstream.total_timeout_ms` as the per-attempt deadline. A FAIL line names
|
||||
@@ -50,13 +53,28 @@ checks, in order:
|
||||
| `--data-dir DIR` | Data directory to look for `config.db` in. |
|
||||
| `--config FILE` | Check this file instead of the database. |
|
||||
|
||||
### Failures and warnings
|
||||
|
||||
Every finding carries a severity. `FAIL` is a problem that sets exit 2. `WARN`
|
||||
is legal configuration that is almost certainly not what was meant — a blocklist
|
||||
source no group links to, a TLS key readable beyond its owner — and never
|
||||
changes an exit code, because the service starts either way.
|
||||
|
||||
The last line is a summary, and it never contradicts the lines above it:
|
||||
|
||||
| What was found | Last line | Exit |
|
||||
| --- | --- | --- |
|
||||
| Nothing | `OK: no problems found` | 0 |
|
||||
| Warnings only | `OK: no failures found, 2 warnings` — `1 warning` in the singular | 0 |
|
||||
| At least one failure | No summary line; the FAIL lines are the report | 2 |
|
||||
|
||||
### Source selection
|
||||
|
||||
- `--config FILE` given explicitly: check that file, nothing else.
|
||||
- Otherwise, if `<data-dir>/config.db` exists: check the database — the right
|
||||
default, since the database is the truth on a configured server. Pending
|
||||
schema migrations are applied first, so a `check` immediately after an upgrade
|
||||
works.
|
||||
default, since the database is the truth on a configured server. It is opened
|
||||
immutable, so `check` writes nothing to it; see
|
||||
[what `check` does not do](#what-check-does-not-do).
|
||||
- Otherwise, if the default config file path exists: check it.
|
||||
- Otherwise: "nothing to check", exit 2.
|
||||
|
||||
@@ -64,10 +82,42 @@ The first line of output always names which source was checked. A file larger
|
||||
than 4 MiB fails with `larger than 4194304 bytes`; a ZON syntax error is
|
||||
reported with its line and column.
|
||||
|
||||
A missing file is treated differently depending on how the path was reached. An
|
||||
explicit `--config FILE` that does not exist is an I/O failure: `check failed:
|
||||
FileNotFound` on stderr, exit 1. A default path that does not exist is one of
|
||||
the cases above and produces "nothing to check", exit 2.
|
||||
A named file that is missing or unreadable is a finding like any other, not an
|
||||
I/O failure that escapes the run: `FAIL <path>: no such file` or
|
||||
`FAIL <path>: not readable`, exit 2. That is the same code the implicit path
|
||||
gives when there is nothing to check, so naming the file does not change what a
|
||||
missing file costs.
|
||||
|
||||
### What `check` does not do
|
||||
|
||||
`check` never writes to `config.db`. It opens the file immutable, which means
|
||||
SQLite refuses every statement that would write and builds no write-ahead log,
|
||||
so no `config.db-wal` and no `config.db-shm` appear beside it. It does not chmod
|
||||
the file and it does not migrate the schema.
|
||||
|
||||
Two consequences are worth knowing before you read a FAIL line as damage:
|
||||
|
||||
- A database behind this binary's schema is reported, not upgraded. Start the
|
||||
service to migrate it.
|
||||
|
||||
```
|
||||
FAIL <db>: schema version <n>, this nxdns expects <m>; `nxdns run` migrates it, `check` will not
|
||||
```
|
||||
|
||||
- A database with an unapplied write-ahead log cannot be graded without writing,
|
||||
because the newest settings are in the log and the main file holds older ones.
|
||||
`check` says so rather than reading the stale values:
|
||||
|
||||
```
|
||||
FAIL <db>: uncheckpointed changes are waiting in <db>-wal, and reading without writing would answer from the older settings in the main file; `nxdns run` applies them. A running nxdns normally holds this log, which is the usual reason to see this line.
|
||||
```
|
||||
|
||||
A running nxdns is the usual holder of that log, so this is a common answer
|
||||
when checking a live server rather than a sign of damage. It depends on what
|
||||
is in the log, not on whether a server is up: a configuration write that has
|
||||
not been checkpointed puts bytes there, and a server that has only been
|
||||
answering queries leaves `config.db-wal` empty and reads normally. Check an
|
||||
`export` with `--config`, or stop the service first.
|
||||
|
||||
## `export`
|
||||
|
||||
@@ -92,17 +142,24 @@ See [back up and restore](../how-to/back-up-and-restore.md).
|
||||
## `import FILE`
|
||||
|
||||
Validates FILE and replaces the whole configuration with it in one transaction.
|
||||
Prints every validation problem on failure; a failed import leaves the database
|
||||
untouched. Refuses a database that already has content unless `--force` is
|
||||
given (`DatabaseNotEmpty`, exit 2). Creates the data directory at mode 0700 if
|
||||
it is missing.
|
||||
Prints every validation problem; a failed import leaves the database untouched.
|
||||
Refuses a database that already holds configuration unless `--force` is given
|
||||
(`DatabaseNotEmpty`, exit 2). The check measures what an operator set, not what
|
||||
the network did: client rows the DNS path materialised from traffic never
|
||||
trigger the refusal on their own. Creates the data directory at mode 0700 if it
|
||||
is missing.
|
||||
|
||||
Client history survives the replacement. An address the database already knew
|
||||
keeps its first-seen and last-seen even when FILE names it; only an address it
|
||||
has never seen takes the import's clock. A client FILE leaves out is removed,
|
||||
history included.
|
||||
|
||||
`FILE` is positional and may appear before or after the flags.
|
||||
|
||||
| Flag | Meaning |
|
||||
| --- | --- |
|
||||
| `--data-dir DIR` | Data directory holding `config.db` (created if missing). |
|
||||
| `--force` | Replace a database that already has content. |
|
||||
| `--force` | Replace a database that already holds configuration. |
|
||||
|
||||
## `version`
|
||||
|
||||
@@ -120,31 +177,37 @@ the same. A usage error prints the same text to stderr and exits 64.
|
||||
| --- | --- |
|
||||
| 0 | Success. |
|
||||
| 1 | Runtime failure — I/O, database, out of memory. A partial diagnostic report caused by an allocation failure is a runtime failure, not a verdict on the configuration. |
|
||||
| 2 | A configuration problem the operator can fix, or a `check` that found one. Which faults qualify differs per subcommand; see below. |
|
||||
| 2 | A configuration problem the operator can fix, or a `check` that found one. |
|
||||
| 64 | Usage error — unknown command or flag, a flag without its value, a missing or extra argument. |
|
||||
|
||||
Code 2 is not a single rule shared by every subcommand. `check` and `import`
|
||||
classify configuration faults; `run` maps only four errors to it and lets
|
||||
everything else out as a runtime failure.
|
||||
Code 2 means the same thing from every subcommand. `src/config/faults.zig`
|
||||
holds the one list of errors that mean "the configuration the operator supplied
|
||||
is wrong", and `run`, `check` and `import` all ask it, so a rejected file exits
|
||||
2 whichever command read it. The list is every error the validator raises, plus
|
||||
`ParseZon`, `ConfigTooLarge`, `NoUsableUpstreams` and `BadCertificate`. In
|
||||
practice that covers a seed file with a syntax error, one larger than 4 MiB, one
|
||||
with no `default` group (`MissingDefaultGroup`), one with no enabled upstream
|
||||
(`NoUpstreams`), a bad bind address, a bad rate limit, an unusable certificate,
|
||||
and `password` and `password_hash` set together.
|
||||
|
||||
`check` exits 2 when validation reported at least one problem, when a
|
||||
certificate or key named by an enabled listener is unreadable, when a probed
|
||||
upstream failed, when the file is larger than 4 MiB, when the file has a ZON
|
||||
syntax error, and when there was nothing to check. Any other error escaping the
|
||||
run — a missing explicit `--config` file, an unreadable database — prints
|
||||
`check failed: <Error>` and exits 1.
|
||||
When `run` exits 2 it points at the diagnosis on stderr, whether the fault came
|
||||
from the seed file or from the database it loaded:
|
||||
|
||||
`import` exits 2 when validation recorded at least one problem, and for
|
||||
`DatabaseNotEmpty`, `ConfigTooLarge`, `ParseZon` and `PasswordAndHashBothSet`.
|
||||
`OutOfMemory` is 1 even when problems were recorded, because the report is then
|
||||
incomplete. Every other error is 1.
|
||||
```
|
||||
run `nxdns check` to see the configuration in full
|
||||
```
|
||||
|
||||
`run` exits 2 for `NoUsableUpstreams`, `BadBindAddress`, `BadRateLimit` and
|
||||
`BadCertificate`, and points the operator at `nxdns check` on stderr when it
|
||||
does. Nothing else is remapped. In particular, seeding the database from
|
||||
`--config` on first start happens before that classification applies to it: a
|
||||
seed file that is unparseable (`ParseZon`), larger than 4 MiB
|
||||
(`ConfigTooLarge`), or rejected by validation prints its diagnostics to stderr
|
||||
and exits 1. The same file given to `check` or `import` exits 2.
|
||||
`check` exits 2 for those faults and also when a probed upstream failed, when a
|
||||
named configuration file is missing or unreadable, when the database cannot be
|
||||
read or is not at this binary's schema version, and when there was nothing to
|
||||
check. Warnings never contribute.
|
||||
|
||||
`import` exits 2 for those faults and for `DatabaseNotEmpty`. That last one is
|
||||
deliberately not a configuration fault — it reports the state of the database
|
||||
rather than the content of a file — and `import` decides it for itself; the
|
||||
answer to it is `--force`, not an edit.
|
||||
|
||||
`OutOfMemory` is exit 1 even when problems were recorded, because the report is
|
||||
then incomplete. Every other error is 1.
|
||||
|
||||
Where an exit code sends you next: [troubleshoot](../how-to/troubleshoot.md).
|
||||
|
||||
Reference in New Issue
Block a user