milestone 20: declarative configuration for iac
This commit is contained in:
+105
-30
@@ -37,10 +37,22 @@ checked on its first line.
|
||||
**Fixes by cause.**
|
||||
|
||||
- `NoUsableUpstreams` — the database has no enabled upstream. On a fresh
|
||||
install this means the seed file was missing or in the wrong place; the start
|
||||
log says `no configuration file at '/etc/nxdns/config.zon'; using the
|
||||
database as it is`. Write the seed file and start again against the still
|
||||
empty database, or `nxdns import <file> --force`.
|
||||
install in database mode this is simply an empty database, and the run says
|
||||
what to do about it on the next line:
|
||||
|
||||
```
|
||||
nxdns run failed: NoUsableUpstreams
|
||||
run `nxdns check` to see the configuration in full
|
||||
load one with `nxdns import <file>`, or make a file the source of truth with `nxdns run --config <file>`
|
||||
```
|
||||
|
||||
Write a configuration file and take either exit: `nxdns import <file>` to load
|
||||
it into the database once, or add `--config <file>` to `ExecStart` to make the
|
||||
file the configuration from then on.
|
||||
- `ManagedConfigUnreadable` — the service runs `run --config FILE` and that file
|
||||
is missing or the process may not read it. The path is in the FAIL line above
|
||||
the failure. File mode never falls back to the database, on purpose: a
|
||||
fallback would turn a bad deploy into a silently stale configuration.
|
||||
- `BadCertificate` — a DoH or DoT listener is enabled and its certificate or
|
||||
key is unreadable, too large, unparseable, or the key does not belong to the
|
||||
certificate. `run` names both paths before it exits:
|
||||
@@ -79,10 +91,10 @@ checked on its first line.
|
||||
- `BadBindAddress` — `dns.bind_ipv4` or `dns.bind_ipv6` is not an address of
|
||||
that family.
|
||||
|
||||
## A seed file you just wrote is rejected
|
||||
## A configuration file you just wrote is rejected
|
||||
|
||||
**Symptom.** A first start against an empty database prints the validation
|
||||
problem and stops with exit 2:
|
||||
**Symptom.** `nxdns run --config`, `nxdns check --config` or `nxdns import`
|
||||
prints the validation problem and stops with exit 2:
|
||||
|
||||
```
|
||||
FAIL groups: no group named 'default'; every unknown client is assigned to it
|
||||
@@ -98,7 +110,7 @@ nxdns run failed: ParseZon
|
||||
run `nxdns check` to see the configuration in full
|
||||
```
|
||||
|
||||
So does a seed file whose upstream list is empty or all disabled:
|
||||
So does a file whose upstream list is empty or all disabled:
|
||||
|
||||
```
|
||||
FAIL upstreams: at least one upstream must be enabled
|
||||
@@ -106,9 +118,9 @@ nxdns run failed: NoUpstreams
|
||||
run `nxdns check` to see the configuration in full
|
||||
```
|
||||
|
||||
`NoUpstreams` from a seed file is not the same fault as `NoUsableUpstreams`
|
||||
above: the first is a file `run` refused, the second is a database `run`
|
||||
accepted and found empty. Both are exit 2.
|
||||
`NoUpstreams` from a file is not the same fault as `NoUsableUpstreams` above:
|
||||
the first is a file `run` refused, the second is a database `run` accepted and
|
||||
found empty. Both are exit 2.
|
||||
|
||||
**Diagnosis.** Run the same file through `check`, which reports the same
|
||||
problems and exits 2:
|
||||
@@ -117,11 +129,21 @@ problems and exits 2:
|
||||
nxdns check --config /etc/nxdns/config.zon
|
||||
```
|
||||
|
||||
**Fix.** Correct the file the diagnostics name and start again. The database is
|
||||
still empty after a failed seed, so the next start re-reads the file. The exit
|
||||
code no longer depends on which command read the file: all three of these files
|
||||
were run through `run`, `check` and `import` here, and every one of the nine
|
||||
combinations exited 2 with the same diagnostic.
|
||||
**Fix.** Correct the file the diagnostics name and start again. Nothing was
|
||||
applied — a file-mode reconcile happens in one transaction that rolls back, and
|
||||
a failed `import` leaves the database untouched. The exit code does not depend
|
||||
on which command read the file: all three of these files were run through `run`,
|
||||
`check` and `import` here, and every one of the nine combinations exited 2 with
|
||||
the same diagnostic.
|
||||
|
||||
Under the shipped systemd unit an exit 2 stops the service rather than
|
||||
restarting it (`RestartPreventExitStatus=2 64`), so the journal holds the
|
||||
diagnostics instead of drowning them in a restart loop. `systemctl start nxdns`
|
||||
once the file is fixed.
|
||||
|
||||
Make `nxdns check --config <file>` the precondition in whatever pushes the file.
|
||||
In file mode every boot reads it, so an unvalidated bad push does not fail at
|
||||
deploy time — it fails at the next restart, which may be a power cut at 3am.
|
||||
|
||||
## `nxdns check` fails on a server that is running fine
|
||||
|
||||
@@ -210,10 +232,11 @@ startup cycle, not a fix.
|
||||
## The container restarts in a loop
|
||||
|
||||
**Symptom.** `docker compose ps` shows the container restarting, and the log is
|
||||
one line repeated:
|
||||
the same failure repeated. Docker has no start limit, so this goes on forever.
|
||||
|
||||
```
|
||||
nxdns run failed: AccessDenied
|
||||
FAIL /etc/nxdns/config.zon: not readable
|
||||
nxdns run failed: ManagedConfigUnreadable
|
||||
```
|
||||
|
||||
**Diagnosis.**
|
||||
@@ -223,10 +246,10 @@ docker inspect -f '{{.State.Status}} exit={{.State.ExitCode}} restarts={{.Restar
|
||||
stat -c '%a %u:%g %n' deploy/docker/etc-nxdns/config.zon
|
||||
```
|
||||
|
||||
Exit 1 with `AccessDenied` means the container could not read the seed file.
|
||||
The container runs as uid 65532 and `/etc/nxdns` is mounted read-only, so a
|
||||
file at mode 0600 owned by your own uid is unreadable to it and the container
|
||||
cannot repair it.
|
||||
Exit 2 naming the configuration path means the container could not read the
|
||||
file the shipped `command:` makes its configuration. The container runs as uid
|
||||
65532 and `/etc/nxdns` is mounted read-only, so a file at mode 0600 owned by
|
||||
your own uid is unreadable to it and the container cannot repair it.
|
||||
|
||||
**Fix.** Either make the file world-readable, when it holds no secret:
|
||||
|
||||
@@ -241,14 +264,65 @@ chown 65532:65532 deploy/docker/etc-nxdns/config.zon
|
||||
chmod 0600 deploy/docker/etc-nxdns/config.zon
|
||||
```
|
||||
|
||||
The 0644 path was verified here, including the recovery: after the `chmod` the
|
||||
container started and answered queries. The `chown` needs root and was not run
|
||||
here.
|
||||
The 0644 path was verified against an earlier revision of this page, including
|
||||
the recovery: after the `chmod` the container started and answered queries. The
|
||||
`chown` needs root and was not run here.
|
||||
|
||||
A container that exits 2 instead — `nxdns run failed: NoUsableUpstreams` after
|
||||
`no configuration file at '/etc/nxdns/config.zon'` — has no seed file at all on
|
||||
a fresh volume. Create `deploy/docker/etc-nxdns/config.zon` and bring it up
|
||||
again; see [Install with Docker](install-with-docker.md).
|
||||
`FAIL /etc/nxdns/config.zon: no such file` instead of `not readable` means there
|
||||
is no configuration file at all. Create `deploy/docker/etc-nxdns/config.zon` and
|
||||
bring it up again; see [Install with Docker](install-with-docker.md).
|
||||
|
||||
A container that exits 2 with `NoUsableUpstreams` is in database mode — the
|
||||
`command:` line naming `--config` was removed — on a volume whose database is
|
||||
still empty. Load one and bring it back up:
|
||||
|
||||
```sh
|
||||
docker compose -f deploy/docker/compose.yaml run --rm nxdns import /etc/nxdns/config.zon
|
||||
```
|
||||
|
||||
> Not re-run on this host: staging a release image needs `zig build dist`, which
|
||||
> could not run here while the web bundle was mid-rebuild by other work in the
|
||||
> same checkout. The failure text quoted above is what the same binary prints
|
||||
> outside a container, which was reproduced here, with the container's paths.
|
||||
|
||||
## The admin interface refuses an edit with 403
|
||||
|
||||
**Symptom.** Saving anything in the admin interface fails, and the API answers:
|
||||
|
||||
```json
|
||||
{"error":"configuration is managed by /etc/nxdns/config.zon; edit the file and restart"}
|
||||
```
|
||||
|
||||
This is not a fault. The service runs `nxdns run --config`, which makes that
|
||||
file the configuration, and configuration writes through the API are refused so
|
||||
the file and the running server cannot drift apart.
|
||||
|
||||
**Diagnosis.** The start log names the authority:
|
||||
|
||||
```sh
|
||||
journalctl -u nxdns | grep 'authority:'
|
||||
```
|
||||
|
||||
```
|
||||
info(nxdns): authority: file (/etc/nxdns/config.zon)
|
||||
```
|
||||
|
||||
**Fix.** Edit the file, validate it, restart:
|
||||
|
||||
```sh
|
||||
$EDITOR /etc/nxdns/config.zon
|
||||
nxdns check --config /etc/nxdns/config.zon
|
||||
systemctl restart nxdns
|
||||
```
|
||||
|
||||
Or, if you want the interface to be how this box is configured, leave file mode:
|
||||
drop `--config` from `ExecStart` and restart. The database already holds the
|
||||
last reconciled state, so nothing is lost. See
|
||||
[Run in file mode](install-with-systemd.md#run-in-file-mode).
|
||||
|
||||
Pausing blocking, refreshing blocklists and reloading certificates are not
|
||||
configuration and keep working in file mode. Deleting a client works too, unless
|
||||
the file names that client's address.
|
||||
|
||||
## The container cannot reach its upstreams
|
||||
|
||||
@@ -324,7 +398,8 @@ window of unfiltered answers.
|
||||
A generation number with nothing being blocked is a different problem: the
|
||||
snapshot loaded but has no sources in it. The line
|
||||
`blocklist snapshot generation 1: 0 of 0 sources loaded` says exactly that. Add
|
||||
a source in the admin interface, or in the seed file before the first start.
|
||||
a source in the admin interface, or a `blocklist_sources` entry to the
|
||||
configuration file with a `group_sources` link naming a group.
|
||||
|
||||
## A database stamped by a newer binary
|
||||
|
||||
|
||||
Reference in New Issue
Block a user