docs: unwrap hand-wrapped prose repo-wide
Gates / frontend (push) Successful in 1m2s
Gates / test (push) Successful in 1m38s
Gates / package (push) Successful in 5m5s
Gates / test-aarch64 (push) Successful in 6m30s
Gates / container (push) Successful in 15s
CI / gates (push) Successful in 13m30s
Gates / frontend (push) Successful in 1m2s
Gates / test (push) Successful in 1m38s
Gates / package (push) Successful in 5m5s
Gates / test-aarch64 (push) Successful in 6m30s
Gates / container (push) Successful in 15s
CI / gates (push) Successful in 13m30s
This commit is contained in:
@@ -1,16 +1,10 @@
|
||||
# Install nxdns with systemd
|
||||
|
||||
Installs nxdns as a system service on a Linux host with systemd, including a
|
||||
Raspberry Pi 5. At the end the service answers DNS on port 53 and starts on
|
||||
boot.
|
||||
Installs nxdns as a system service on a Linux host with systemd, including a Raspberry Pi 5. At the end the service answers DNS on port 53 and starts on boot.
|
||||
|
||||
The normal path is to download a released tarball, verify it, and install what
|
||||
is inside it. Building from source is still supported and is the last section
|
||||
of this page.
|
||||
The normal path is to download a released tarball, verify it, and install what is inside it. Building from source is still supported and is the last section of this page.
|
||||
|
||||
For what each flag does, see [the CLI reference](../reference/cli.md); for what
|
||||
each configuration field means, see
|
||||
[the configuration reference](../reference/configuration.md).
|
||||
For what each flag does, see [the CLI reference](../reference/cli.md); for what each configuration field means, see [the configuration reference](../reference/configuration.md).
|
||||
|
||||
> Verification: `systemd-analyze verify` was run on the machine that wrote this
|
||||
> page. `nxdns check`, `nxdns import`, `nxdns export` and `nxdns run` were run
|
||||
@@ -33,9 +27,7 @@ each configuration field means, see
|
||||
|
||||
## 1. Download and verify
|
||||
|
||||
Two static musl tarballs are published per release, one per architecture. Pick
|
||||
`x86_64-linux-musl` for a normal PC or server and `aarch64-linux-musl` for a
|
||||
Raspberry Pi 5.
|
||||
Two static musl tarballs are published per release, one per architecture. Pick `x86_64-linux-musl` for a normal PC or server and `aarch64-linux-musl` for a Raspberry Pi 5.
|
||||
|
||||
```sh
|
||||
BASE=https://git.mial.net/mokhtar/nxdns
|
||||
@@ -47,15 +39,9 @@ curl -fLO "$BASE/releases/download/v$VERSION/SHA256SUMS.txt"
|
||||
curl -fLO "$BASE/releases/download/v$VERSION/SHA256SUMS.txt.asc"
|
||||
```
|
||||
|
||||
The first line asks the server which release is current instead of hardcoding a
|
||||
number that goes stale one release later — Gitea redirects `releases/latest` to
|
||||
the newest published release's tag page. To install a particular version
|
||||
instead, set `VERSION=<version>` yourself with the one you want; the tarball
|
||||
filenames carry the version either way, so there is no version-free download
|
||||
URL for them.
|
||||
The first line asks the server which release is current instead of hardcoding a number that goes stale one release later — Gitea redirects `releases/latest` to the newest published release's tag page. To install a particular version instead, set `VERSION=<version>` yourself with the one you want; the tarball filenames carry the version either way, so there is no version-free download URL for them.
|
||||
|
||||
Verify before you extract. The signature is over `SHA256SUMS.txt`, and
|
||||
`SHA256SUMS.txt` is over the tarballs:
|
||||
Verify before you extract. The signature is over `SHA256SUMS.txt`, and `SHA256SUMS.txt` is over the tarballs:
|
||||
|
||||
```sh
|
||||
gpg --verify SHA256SUMS.txt.asc SHA256SUMS.txt
|
||||
@@ -63,13 +49,9 @@ sha256sum -c --ignore-missing SHA256SUMS.txt
|
||||
tar -xzf "nxdns-$VERSION-x86_64-linux-musl.tar.gz"
|
||||
```
|
||||
|
||||
[Verify a release](verify-a-release.md) has the whole procedure: where the
|
||||
public key comes from, what fingerprint to expect, what each failure means, and
|
||||
what the signature does and does not prove. Read it once before your first
|
||||
install.
|
||||
[Verify a release](verify-a-release.md) has the whole procedure: where the public key comes from, what fingerprint to expect, what each failure means, and what the signature does and does not prove. Read it once before your first install.
|
||||
|
||||
The extracted directory `nxdns-$VERSION-x86_64-linux-musl/` holds everything
|
||||
this page installs:
|
||||
The extracted directory `nxdns-$VERSION-x86_64-linux-musl/` holds everything this page installs:
|
||||
|
||||
| File | What it is |
|
||||
| --- | --- |
|
||||
@@ -92,8 +74,7 @@ cd "nxdns-$VERSION-x86_64-linux-musl"
|
||||
scp nxdns nxdns.service nxdns.conf target:/tmp/
|
||||
```
|
||||
|
||||
For a Raspberry Pi 5, extract the `aarch64-linux-musl` tarball instead — see
|
||||
[Raspberry Pi 5](#raspberry-pi-5) below.
|
||||
For a Raspberry Pi 5, extract the `aarch64-linux-musl` tarball instead — see [Raspberry Pi 5](#raspberry-pi-5) below.
|
||||
|
||||
> Not verified on this host: `target` is a placeholder for your server's
|
||||
> hostname, and the machine that wrote this page has no second host to copy
|
||||
@@ -111,9 +92,7 @@ Off the target host this prints one complaint and exits 1:
|
||||
nxdns.service: Command /usr/local/bin/nxdns is not executable: No such file or directory
|
||||
```
|
||||
|
||||
That is the ExecStart path check finding no binary yet. Any other message is a
|
||||
real problem with the unit. On the target, after step 3, the same command
|
||||
should print nothing.
|
||||
That is the ExecStart path check finding no binary yet. Any other message is a real problem with the unit. On the target, after step 3, the same command should print nothing.
|
||||
|
||||
> Verified on this host against `deploy/systemd/nxdns.service` in a checkout,
|
||||
> which is the same file the tarball ships — the path is the only difference.
|
||||
@@ -134,31 +113,21 @@ systemctl daemon-reload
|
||||
mkdir -p -m 0755 /etc/nxdns
|
||||
```
|
||||
|
||||
The sysusers fragment ships under the name it is installed as, so there is no
|
||||
rename to get wrong.
|
||||
The sysusers fragment ships under the name it is installed as, so there is no rename to get wrong.
|
||||
|
||||
> Not verified on this host: these commands need root on a target machine. The
|
||||
> files they install were read at HEAD and the unit was checked with
|
||||
> `systemd-analyze verify`.
|
||||
|
||||
The service user is a static one, not `DynamicUser`: a TLS key for the DoH or
|
||||
DoT listener has to be chown-able to a uid that survives a restart.
|
||||
The service user is a static one, not `DynamicUser`: a TLS key for the DoH or DoT listener has to be chown-able to a uid that survives a restart.
|
||||
|
||||
Do not create `/var/lib/nxdns` or `/var/log/nxdns` by hand. The unit's
|
||||
`StateDirectory` and `LogsDirectory` settings make systemd create them on first
|
||||
start, `/var/lib/nxdns` at mode 0700 owned by `nxdns`.
|
||||
Do not create `/var/lib/nxdns` or `/var/log/nxdns` by hand. The unit's `StateDirectory` and `LogsDirectory` settings make systemd create them on first start, `/var/lib/nxdns` at mode 0700 owned by `nxdns`.
|
||||
|
||||
`/etc/nxdns` is the one directory the `mkdir` above is for. The unit's
|
||||
`ConfigurationDirectory=nxdns` also creates it, but not until the first start
|
||||
in step 5, and step 4 has to write a file into it before then. systemd does not
|
||||
mind finding the directory already there; it adjusts the mode and ownership to
|
||||
what the unit asks for.
|
||||
`/etc/nxdns` is the one directory the `mkdir` above is for. The unit's `ConfigurationDirectory=nxdns` also creates it, but not until the first start in step 5, and step 4 has to write a file into it before then. systemd does not mind finding the directory already there; it adjusts the mode and ownership to what the unit asks for.
|
||||
|
||||
## 4. Write the configuration
|
||||
|
||||
nxdns will not start with nothing to forward to. Write `/etc/nxdns/config.zon`.
|
||||
The smallest file that starts is one group named `default` and one enabled
|
||||
upstream:
|
||||
nxdns will not start with nothing to forward to. Write `/etc/nxdns/config.zon`. The smallest file that starts is one group named `default` and one enabled upstream:
|
||||
|
||||
```zon
|
||||
.{
|
||||
@@ -168,36 +137,20 @@ upstream:
|
||||
}
|
||||
```
|
||||
|
||||
That file holds a password in plain text, so restrict it as soon as you have
|
||||
written it:
|
||||
That file holds a password in plain text, so restrict it as soon as you have written it:
|
||||
|
||||
```sh
|
||||
chown root:nxdns /etc/nxdns/config.zon
|
||||
chmod 0640 /etc/nxdns/config.zon
|
||||
```
|
||||
|
||||
Root's umask is 022 on most distributions, so a freshly written
|
||||
`/etc/nxdns/config.zon` is mode 0644 and every account on the host can read the
|
||||
password out of it. The unit's `UMask=0077` does not help here: it applies to
|
||||
files the service creates once it is running, and never re-chmods a file that
|
||||
was written before the first start.
|
||||
Root's umask is 022 on most distributions, so a freshly written `/etc/nxdns/config.zon` is mode 0644 and every account on the host can read the password out of it. The unit's `UMask=0077` does not help here: it applies to files the service creates once it is running, and never re-chmods a file that was written before the first start.
|
||||
|
||||
0640 with group `nxdns` rather than 0600: `/etc/nxdns` is a
|
||||
`ConfigurationDirectory`, which systemd leaves owned by root, and the service
|
||||
runs as `nxdns`. A root-owned 0600 file would be unreadable to it.
|
||||
0640 with group `nxdns` rather than 0600: `/etc/nxdns` is a `ConfigurationDirectory`, which systemd leaves owned by root, and the service runs as `nxdns`. A root-owned 0600 file would be unreadable to it.
|
||||
|
||||
Keep that group read bit for good, not just for the first boot. Under
|
||||
`run --config` the service reads this file on **every** start, so tightening
|
||||
the mode later breaks the next restart. Under database authority it is
|
||||
`nxdns import` that reads the file, as whoever runs that command, and a bare
|
||||
`nxdns run` never reads it at all.
|
||||
Keep that group read bit for good, not just for the first boot. Under `run --config` the service reads this file on **every** start, so tightening the mode later breaks the next restart. Under database authority it is `nxdns import` that reads the file, as whoever runs that command, and a bare `nxdns run` never reads it at all.
|
||||
|
||||
Do not expect `nxdns check` to catch a permissive mode here. Its only
|
||||
permission warning is for a TLS private key
|
||||
(`WARN doh_server.key_path: ... is mode 644; a TLS key must be readable by its
|
||||
owner only`, from `checkTlsFiles` in `src/cli.zig`); it never stats the
|
||||
configuration file. A mode 0644 `config.zon` passes `check` in silence, so the
|
||||
`chmod` above is yours to remember.
|
||||
Do not expect `nxdns check` to catch a permissive mode here. Its only permission warning is for a TLS private key (`WARN doh_server.key_path: ... is mode 644; a TLS key must be readable by its owner only`, from `checkTlsFiles` in `src/cli.zig`); it never stats the configuration file. A mode 0644 `config.zon` passes `check` in silence, so the `chmod` above is yours to remember.
|
||||
|
||||
Check it before you start the service:
|
||||
|
||||
@@ -205,8 +158,7 @@ Check it before you start the service:
|
||||
nxdns check --config /etc/nxdns/config.zon
|
||||
```
|
||||
|
||||
A good file prints the source it checked, one `OK` line per upstream, and
|
||||
`OK: no problems found`:
|
||||
A good file prints the source it checked, one `OK` line per upstream, and `OK: no problems found`:
|
||||
|
||||
```
|
||||
checking configuration file /etc/nxdns/config.zon
|
||||
@@ -214,9 +166,7 @@ OK upstreams[0] https://cloudflare-dns.com
|
||||
OK: no problems found
|
||||
```
|
||||
|
||||
The upstream probe sends a real query, so this needs working DNS on the host at
|
||||
the time you run it. Exit 2 means `check` found something to fix and printed
|
||||
every problem it found, not only the first.
|
||||
The upstream probe sends a real query, so this needs working DNS on the host at the time you run it. Exit 2 means `check` found something to fix and printed every problem it found, not only the first.
|
||||
|
||||
Now load it into the database:
|
||||
|
||||
@@ -229,28 +179,17 @@ info(migrations): config.db migrated from schema version 0 to 1
|
||||
imported /etc/nxdns/config.zon
|
||||
```
|
||||
|
||||
The plaintext password is hashed into `web.password_hash` and never stored as
|
||||
plaintext; `nxdns export` writes `.password = null` beside the hash. Nothing
|
||||
downstream reads the plaintext again, so once step 6 confirms you can log in you
|
||||
can delete the file:
|
||||
The plaintext password is hashed into `web.password_hash` and never stored as plaintext; `nxdns export` writes `.password = null` beside the hash. Nothing downstream reads the plaintext again, so once step 6 confirms you can log in you can delete the file:
|
||||
|
||||
```sh
|
||||
rm /etc/nxdns/config.zon
|
||||
```
|
||||
|
||||
A kept file is not a backup — `nxdns export` is (see
|
||||
[Back up and restore](back-up-and-restore.md)), and the export carries the
|
||||
password hash rather than the password. If you keep it, leave it at 0640
|
||||
root:nxdns.
|
||||
A kept file is not a backup — `nxdns export` is (see [Back up and restore](back-up-and-restore.md)), and the export carries the password hash rather than the password. If you keep it, leave it at 0640 root:nxdns.
|
||||
|
||||
That is the **database mode** install, which is what the packaged unit runs:
|
||||
`ExecStart=/usr/local/bin/nxdns run`, no `--config`, so nothing reads a file
|
||||
after this step. Change settings afterwards through the admin interface, the
|
||||
API, or an export–edit–import cycle.
|
||||
That is the **database mode** install, which is what the packaged unit runs: `ExecStart=/usr/local/bin/nxdns run`, no `--config`, so nothing reads a file after this step. Change settings afterwards through the admin interface, the API, or an export–edit–import cycle.
|
||||
|
||||
If you would rather keep `/etc/nxdns/config.zon` in git and have every restart
|
||||
converge onto it, do not delete the file — go to
|
||||
[Run in file mode](#run-in-file-mode) instead, and skip the `rm`.
|
||||
If you would rather keep `/etc/nxdns/config.zon` in git and have every restart converge onto it, do not delete the file — go to [Run in file mode](#run-in-file-mode) instead, and skip the `rm`.
|
||||
|
||||
> Verified on this host, with a scratch `--config` and `--data-dir` in place of
|
||||
> `/etc/nxdns` and `/var/lib/nxdns` — those two paths are the only difference
|
||||
@@ -277,20 +216,11 @@ A healthy start logs a line naming every socket it bound:
|
||||
info(nxdns): nxdns <version> serving on udp [::]:53 tcp [::]:53 tcp 0.0.0.0:53; 1 upstream(s); blocklist generation 1
|
||||
```
|
||||
|
||||
nxdns writes to stderr and systemd captures that into the journal; logging
|
||||
needs no further configuration. Port 53 is privileged, and the unit grants
|
||||
`CAP_NET_BIND_SERVICE` through `AmbientCapabilities`.
|
||||
nxdns writes to stderr and systemd captures that into the journal; logging needs no further configuration. Port 53 is privileged, and the unit grants `CAP_NET_BIND_SERVICE` through `AmbientCapabilities`.
|
||||
|
||||
The unit does not restart the service after exit 2 or exit 64
|
||||
(`RestartPreventExitStatus=2 64`). Those are a wrong configuration and a wrong
|
||||
command line, and neither clears on a retry — restarting every two seconds until
|
||||
`StartLimitBurst` gives up would only bury the diagnostics that are already in
|
||||
the journal. `systemctl status nxdns` shows the failed state; fix the cause and
|
||||
start it again.
|
||||
The unit does not restart the service after exit 2 or exit 64 (`RestartPreventExitStatus=2 64`). Those are a wrong configuration and a wrong command line, and neither clears on a retry — restarting every two seconds until `StartLimitBurst` gives up would only bury the diagnostics that are already in the journal. `systemctl status nxdns` shows the failed state; fix the cause and start it again.
|
||||
|
||||
If the start fails, read [Troubleshoot nxdns](troubleshoot.md). The two common
|
||||
first-install failures are a port 53 already held by `systemd-resolved` and a
|
||||
configuration file that does not parse.
|
||||
If the start fails, read [Troubleshoot nxdns](troubleshoot.md). The two common first-install failures are a port 53 already held by `systemd-resolved` and a configuration file that does not parse.
|
||||
|
||||
## 6. Confirm it answers
|
||||
|
||||
@@ -300,9 +230,7 @@ From another machine on the LAN:
|
||||
dig @<server-ip> example.com A +short
|
||||
```
|
||||
|
||||
The admin interface is on port 8080 by default; log in with the password from
|
||||
the configuration file. `http://<server-ip>:8080/api/health` reports upstream
|
||||
availability and disk state without a login.
|
||||
The admin interface is on port 8080 by default; log in with the password from the configuration file. `http://<server-ip>:8080/api/health` reports upstream availability and disk state without a login.
|
||||
|
||||
> Not verified on this host as written: `<server-ip>` is a placeholder, and a
|
||||
> LAN client to run it from is a second machine this host does not have. What
|
||||
@@ -314,25 +242,15 @@ availability and disk state without a login.
|
||||
|
||||
## Run in file mode
|
||||
|
||||
In file mode `/etc/nxdns/config.zon` is the configuration: every start converges
|
||||
the database onto it, and the admin interface refuses configuration edits with a
|
||||
403 naming the file. Use it when you want the file in git and deployed by
|
||||
Ansible. Stay in database mode when you want the UI to be the way things change.
|
||||
In file mode `/etc/nxdns/config.zon` is the configuration: every start converges the database onto it, and the admin interface refuses configuration edits with a 403 naming the file. Use it when you want the file in git and deployed by Ansible. Stay in database mode when you want the UI to be the way things change.
|
||||
|
||||
The packaged unit is flagless on purpose — it is correct as shipped, and a
|
||||
commented-out alternative `ExecStart` in a unit file is documentation
|
||||
masquerading as configuration. File mode is a drop-in.
|
||||
The packaged unit is flagless on purpose — it is correct as shipped, and a commented-out alternative `ExecStart` in a unit file is documentation masquerading as configuration. File mode is a drop-in.
|
||||
|
||||
### Adopt file mode on a box that is already running
|
||||
|
||||
Run these in order. **Stop first**, and do not skip that: any edit made through
|
||||
the UI between an export and the restart would be silently reverted by the first
|
||||
reconcile, and `nxdns check` against a live database refuses to grade it (below).
|
||||
Run these in order. **Stop first**, and do not skip that: any edit made through the UI between an export and the restart would be silently reverted by the first reconcile, and `nxdns check` against a live database refuses to grade it (below).
|
||||
|
||||
If you are arriving here from an upgrade, the binary must already be the new
|
||||
one before you export. An export written by 0.0.1 carries a `.password = ""`
|
||||
line this binary refuses; see
|
||||
[the order trap](upgrade.md#the-order-trap-export-with-the-new-binary-not-the-old-one).
|
||||
If you are arriving here from an upgrade, the binary must already be the new one before you export. An export written by 0.0.1 carries a `.password = ""` line this binary refuses; see [the order trap](upgrade.md#the-order-trap-export-with-the-new-binary-not-the-old-one).
|
||||
|
||||
```sh
|
||||
systemctl stop nxdns
|
||||
@@ -360,12 +278,9 @@ systemctl daemon-reload
|
||||
systemctl start nxdns
|
||||
```
|
||||
|
||||
The empty `ExecStart=` is required. Without it systemd appends a second command
|
||||
to the list rather than replacing the first, and the unit tries to run nxdns
|
||||
twice.
|
||||
The empty `ExecStart=` is required. Without it systemd appends a second command to the list rather than replacing the first, and the unit tries to run nxdns twice.
|
||||
|
||||
The first start after adoption changes nothing, because the file was rendered
|
||||
from the database it is now governing:
|
||||
The first start after adoption changes nothing, because the file was rendered from the database it is now governing:
|
||||
|
||||
```
|
||||
reconciled '/etc/nxdns/config.zon': no changes
|
||||
@@ -373,14 +288,9 @@ info(nxdns): authority: file (/etc/nxdns/config.zon)
|
||||
info(nxdns): nxdns <version> serving on udp [::]:53 tcp [::]:53 tcp 0.0.0.0:53; 1 upstream(s); blocklist generation 1
|
||||
```
|
||||
|
||||
`authority: file` is the line that confirms the drop-in took. Blocklists,
|
||||
compiled snapshots and client history all survive, and every later start on an
|
||||
unchanged file writes nothing either.
|
||||
`authority: file` is the line that confirms the drop-in took. Blocklists, compiled snapshots and client history all survive, and every later start on an unchanged file writes nothing either.
|
||||
|
||||
The file now carries `web.password_hash`, so restrict it the same way step 4
|
||||
does — `chown root:nxdns`, `chmod 0640`. The unit's `ReadOnlyPaths=/etc/nxdns`
|
||||
denies the service write access to that directory, so the process that reads the
|
||||
file cannot modify it.
|
||||
The file now carries `web.password_hash`, so restrict it the same way step 4 does — `chown root:nxdns`, `chmod 0640`. The unit's `ReadOnlyPaths=/etc/nxdns` denies the service write access to that directory, so the process that reads the file cannot modify it.
|
||||
|
||||
### Change the configuration from now on
|
||||
|
||||
@@ -392,11 +302,7 @@ nxdns check --config /etc/nxdns/config.zon
|
||||
systemctl restart nxdns
|
||||
```
|
||||
|
||||
Make `nxdns check --config` the precondition of any Ansible handler that
|
||||
restarts nxdns. A file-mode start reads the file on **every** boot, so a bad
|
||||
push that skips its handler does not fail at deploy time — it detonates at the
|
||||
next power cut. Validating before restarting turns that into a failed deploy at
|
||||
noon.
|
||||
Make `nxdns check --config` the precondition of any Ansible handler that restarts nxdns. A file-mode start reads the file on **every** boot, so a bad push that skips its handler does not fail at deploy time — it detonates at the next power cut. Validating before restarting turns that into a failed deploy at noon.
|
||||
|
||||
The restart prints what it changed:
|
||||
|
||||
@@ -407,9 +313,7 @@ settings keys changed: dns.port web.port
|
||||
|
||||
### Leave file mode
|
||||
|
||||
Remove the drop-in and restart. The database already holds the last reconciled
|
||||
state, so nothing else is needed and the server comes back serving the same
|
||||
configuration:
|
||||
Remove the drop-in and restart. The database already holds the last reconciled state, so nothing else is needed and the server comes back serving the same configuration:
|
||||
|
||||
```sh
|
||||
rm /etc/systemd/system/nxdns.service.d/file-mode.conf
|
||||
@@ -448,8 +352,7 @@ info(nxdns): authority: database
|
||||
|
||||
## Raspberry Pi 5
|
||||
|
||||
The Pi 5 is aarch64. Nothing about the procedure changes except which tarball
|
||||
you take:
|
||||
The Pi 5 is aarch64. Nothing about the procedure changes except which tarball you take:
|
||||
|
||||
```sh
|
||||
curl -fLO "$BASE/releases/download/v$VERSION/nxdns-$VERSION-aarch64-linux-musl.tar.gz"
|
||||
@@ -467,12 +370,7 @@ Then follow steps 3 to 6 on the Pi.
|
||||
|
||||
## Build from source instead
|
||||
|
||||
You do not need this to install nxdns, and it gets you a binary nobody has
|
||||
signed. It is here for two cases: you want to run something other than a
|
||||
tagged release, or you want to build the release yourself and compare it
|
||||
against the published one. For the second case, follow
|
||||
[Verify a release](verify-a-release.md) rather than this section — it says what
|
||||
the comparison is and is not worth.
|
||||
You do not need this to install nxdns, and it gets you a binary nobody has signed. It is here for two cases: you want to run something other than a tagged release, or you want to build the release yourself and compare it against the published one. For the second case, follow [Verify a release](verify-a-release.md) rather than this section — it says what the comparison is and is not worth.
|
||||
|
||||
Requires Zig 0.16.0 and Node.js. From the repository root:
|
||||
|
||||
@@ -483,29 +381,18 @@ zig build dist -Dversion-string="$VERSION" -Dgit-commit="$(git rev-parse HEAD)"
|
||||
-Dweb-dist=web/dist -Doptimize=ReleaseSafe
|
||||
```
|
||||
|
||||
The first command builds the admin interface into `web/dist`; the last one
|
||||
embeds that directory in the binary. Build the interface every time, before the
|
||||
binary: a stale `web/dist` ships an admin UI that does not match the API it
|
||||
talks to. `dist` refuses to run against the `web/dist-placeholder` default for
|
||||
exactly that reason, so there is no way to skip it by accident.
|
||||
The first command builds the admin interface into `web/dist`; the last one embeds that directory in the binary. Build the interface every time, before the binary: a stale `web/dist` ships an admin UI that does not match the API it talks to. `dist` refuses to run against the `web/dist-placeholder` default for exactly that reason, so there is no way to skip it by accident.
|
||||
|
||||
`-Dversion-string` is required and has no default. It is what `nxdns version`
|
||||
prints. Take it from `build.zig.zon` rather than inventing one: `verify-dist`
|
||||
asserts that the version under build equals `.version` there, so a made-up
|
||||
string like `0.0.0-local` builds but then fails verification. `-Dgit-commit`
|
||||
is what distinguishes your build from the published one of the same version.
|
||||
`-Dversion-string` is required and has no default. It is what `nxdns version` prints. Take it from `build.zig.zon` rather than inventing one: `verify-dist` asserts that the version under build equals `.version` there, so a made-up string like `0.0.0-local` builds but then fails verification. `-Dgit-commit` is what distinguishes your build from the published one of the same version.
|
||||
|
||||
What comes out under `zig-out/dist/` is the same set a release publishes,
|
||||
minus the signature and the image digest:
|
||||
What comes out under `zig-out/dist/` is the same set a release publishes, minus the signature and the image digest:
|
||||
|
||||
- `bin/<triple>/nxdns` — the stripped static binary, one per target
|
||||
- `stage/nxdns-<version>-<triple>/` — the staged payload, one per target
|
||||
- `nxdns-<version>-<triple>.tar.gz` — one tarball per target
|
||||
- `SHA256SUMS` — the two tarball hashes. The release publishes this as
|
||||
`SHA256SUMS.txt`, with a third line for the image digest appended
|
||||
- `SHA256SUMS` — the two tarball hashes. The release publishes this as `SHA256SUMS.txt`, with a third line for the image digest appended
|
||||
|
||||
The two targets are `x86_64-linux-musl` and `aarch64-linux-musl`. Both binaries
|
||||
are statically linked and need nothing installed on the target host.
|
||||
The two targets are `x86_64-linux-musl` and `aarch64-linux-musl`. Both binaries are statically linked and need nothing installed on the target host.
|
||||
|
||||
Check the result the same way the release pipeline does:
|
||||
|
||||
@@ -514,10 +401,7 @@ zig build verify-dist -Dversion-string="$VERSION" -Dgit-commit="$(git rev-parse
|
||||
-Dweb-dist=web/dist -Doptimize=ReleaseSafe
|
||||
```
|
||||
|
||||
`verify-dist` extracts each archive and asserts the ELF is static and within
|
||||
the size budget, that the layout and file modes are exactly what step 1 lists,
|
||||
and that `nxdns version` prints what was built. It exits non-zero on any
|
||||
failure.
|
||||
`verify-dist` extracts each archive and asserts the ELF is static and within the size budget, that the layout and file modes are exactly what step 1 lists, and that `nxdns version` prints what was built. It exits non-zero on any failure.
|
||||
|
||||
> Verified on this host: `zig build dist` and `zig build verify-dist` were both
|
||||
> run to completion with the version taken from `build.zig.zon`. `dist`
|
||||
@@ -529,13 +413,11 @@ failure.
|
||||
> `FAIL zon-version: build.zig.zon says '0.0.1', the build says '0.0.0-local'`,
|
||||
> which is why this section reads the version out of `build.zig.zon`.
|
||||
|
||||
From here, join the page at step 2 with the staged directory in place of the
|
||||
extracted one:
|
||||
From here, join the page at step 2 with the staged directory in place of the extracted one:
|
||||
|
||||
```sh
|
||||
cd "zig-out/dist/stage/nxdns-$VERSION-x86_64-linux-musl"
|
||||
scp nxdns nxdns.service nxdns.conf target:/tmp/
|
||||
```
|
||||
|
||||
The aarch64 binary is built by the same command and needs no toolchain on the
|
||||
Pi.
|
||||
The aarch64 binary is built by the same command and needs no toolchain on the Pi.
|
||||
|
||||
Reference in New Issue
Block a user