197 lines
7.1 KiB
Markdown
197 lines
7.1 KiB
Markdown
# Install with systemd
|
|
|
|
Install nxdns as a system service on a Linux machine with systemd, including a Raspberry Pi. At the end it answers DNS on port 53 for your network and starts on boot.
|
|
|
|
## 1. Download and verify
|
|
|
|
Each release has two builds: `x86_64-linux-musl` for a PC or server, and `aarch64-linux-musl` for a Raspberry Pi or another 64-bit ARM machine. Both are static binaries that need nothing installed. On the machine that will run nxdns:
|
|
|
|
```sh
|
|
mkdir -p ~/nxdns-release && cd ~/nxdns-release
|
|
curl -fLO https://git.mial.net/mokhtar/nxdns/releases/download/v<version>/nxdns-<version>-x86_64-linux-musl.tar.gz
|
|
curl -fLO https://git.mial.net/mokhtar/nxdns/releases/download/v<version>/SHA256SUMS.txt
|
|
curl -fLO https://git.mial.net/mokhtar/nxdns/releases/download/v<version>/SHA256SUMS.txt.asc
|
|
gpg --verify SHA256SUMS.txt.asc SHA256SUMS.txt
|
|
sha256sum -c --ignore-missing SHA256SUMS.txt
|
|
tar -xzf nxdns-<version>-x86_64-linux-musl.tar.gz
|
|
cd nxdns-<version>-x86_64-linux-musl
|
|
```
|
|
|
|
The signature covers `SHA256SUMS.txt`, and `SHA256SUMS.txt` covers the tarball. [Verify a release](verify-a-release.md) explains where the public key comes from and which fingerprint to expect; read it before your first install.
|
|
|
|
The directory holds the binary `nxdns`, the systemd unit `nxdns.service`, the sysusers file `nxdns.conf` that creates the `nxdns` user, the licences and a short `INSTALL.md`.
|
|
|
|
## 2. Install the binary, the user and the unit
|
|
|
|
As root:
|
|
|
|
```sh
|
|
install -m 0755 nxdns /usr/local/bin/nxdns
|
|
install -m 0644 nxdns.conf /usr/lib/sysusers.d/nxdns.conf
|
|
systemd-sysusers
|
|
install -m 0644 nxdns.service /etc/systemd/system/nxdns.service
|
|
systemctl daemon-reload
|
|
mkdir -p -m 0755 /etc/nxdns
|
|
```
|
|
|
|
Do not create `/var/lib/nxdns` or `/var/log/nxdns`. systemd creates them on the first start, with the right owner and modes.
|
|
|
|
## 3. Write the configuration
|
|
|
|
The smallest configuration that starts is a group named `default` and one upstream resolver. Write `/etc/nxdns/config.zon` and give the web interface a password:
|
|
|
|
```zon
|
|
.{
|
|
.groups = .{ .{ .name = "default" } },
|
|
.upstreams = .{ .{ .url = "https://cloudflare-dns.com/dns-query" } },
|
|
.web = .{ .password = "choose-a-real-password" },
|
|
}
|
|
```
|
|
|
|
The file holds a password in plain text, so restrict it:
|
|
|
|
```sh
|
|
chown root:nxdns /etc/nxdns/config.zon
|
|
chmod 0640 /etc/nxdns/config.zon
|
|
```
|
|
|
|
Check it, then load it into the database:
|
|
|
|
```sh
|
|
nxdns check --config /etc/nxdns/config.zon
|
|
nxdns import /etc/nxdns/config.zon
|
|
```
|
|
|
|
```
|
|
checking configuration file /etc/nxdns/config.zon
|
|
OK upstreams[0] https://cloudflare-dns.com
|
|
OK: no problems found
|
|
info(migrations): config.db migrated from schema version 0 to 1
|
|
imported /etc/nxdns/config.zon
|
|
```
|
|
|
|
`check` sends one real query through each upstream, so the machine needs working DNS when you run it. If it finds a problem it lists every one and exits 2.
|
|
|
|
The password is stored only as a hash, so once you have logged in (step 5) you can delete the file:
|
|
|
|
```sh
|
|
rm /etc/nxdns/config.zon
|
|
```
|
|
|
|
From now on you change settings in the web interface. This is database mode, and it is what the packaged unit runs. To keep `config.zon` in git as the configuration instead, keep the file and see [Run in file mode](#run-in-file-mode).
|
|
|
|
## 4. Start it
|
|
|
|
```sh
|
|
systemctl enable --now nxdns
|
|
journalctl -u nxdns -f
|
|
```
|
|
|
|
A healthy start names every socket it opened:
|
|
|
|
```
|
|
info(nxdns): nxdns <version> serving on udp [::]:53 tcp [::]:53 tcp 0.0.0.0:53; 1 upstream(s); blocklist generation 1
|
|
```
|
|
|
|
The unit grants the capability to bind port 53 and runs nxdns as the `nxdns` user. It does not restart nxdns after exit code 2 (a configuration problem) or 64 (a wrong command line), because a retry cannot fix either; the journal says what is wrong. Fix it and start the service again.
|
|
|
|
### If port 53 is already taken
|
|
|
|
```
|
|
cannot bind udp [::1]:53: AddressInUse
|
|
nxdns run failed: AddressInUse
|
|
```
|
|
|
|
On most systemd distributions `systemd-resolved` holds port 53 with its stub listener. Turn the stub off and keep resolved for the machine's own lookups:
|
|
|
|
```sh
|
|
mkdir -p /etc/systemd/resolved.conf.d
|
|
printf '[Resolve]\nDNSStubListener=no\n' > /etc/systemd/resolved.conf.d/nxdns.conf
|
|
systemctl restart systemd-resolved
|
|
```
|
|
|
|
If `/etc/resolv.conf` is a link to `/run/systemd/resolve/stub-resolv.conf`, point it at `/run/systemd/resolve/resolv.conf` so the machine still resolves names. `ss -lnup 'sport = :53'` shows what else holds the port.
|
|
|
|
## 5. Check it and point your network at it
|
|
|
|
From another machine on your network:
|
|
|
|
```sh
|
|
dig @<server-ip> example.com A +short
|
|
```
|
|
|
|
Open `http://<server-ip>:8080` and log in with the password from step 3. Then add blocklists on the **Protection** page, as [Get started](../tutorial/get-started.md#5-add-a-blocklist) shows.
|
|
|
|
To make every device use nxdns, set the DNS server your router hands out (its DHCP settings) to the nxdns machine's address. Leave the nxdns machine itself on another resolver: nxdns looks up its upstreams' names through it, and that should not depend on nxdns already running.
|
|
|
|
## Run in file mode
|
|
|
|
In file mode `/etc/nxdns/config.zon` is the configuration. Every start applies the file, and the web interface refuses configuration changes and names the file instead. Use it when the file lives in git and a tool deploys it. [The configuration model](../explanation/configuration-model.md) compares the two modes.
|
|
|
|
### Switch to file mode
|
|
|
|
Stop the service first, so no change made in the web interface is lost, then write the current configuration out as the file:
|
|
|
|
```sh
|
|
systemctl stop nxdns
|
|
nxdns export --out /etc/nxdns/config.zon
|
|
chown root:nxdns /etc/nxdns/config.zon
|
|
chmod 0640 /etc/nxdns/config.zon
|
|
nxdns check --config /etc/nxdns/config.zon
|
|
```
|
|
|
|
Add a drop-in that passes the file, and start:
|
|
|
|
```sh
|
|
mkdir -p /etc/systemd/system/nxdns.service.d
|
|
cat > /etc/systemd/system/nxdns.service.d/file-mode.conf <<'EOF'
|
|
[Service]
|
|
ExecStart=
|
|
ExecStart=/usr/local/bin/nxdns run --config=/etc/nxdns/config.zon
|
|
EOF
|
|
systemctl daemon-reload
|
|
systemctl start nxdns
|
|
```
|
|
|
|
The empty `ExecStart=` line is required: it clears the unit's own command instead of adding a second one. The first start changes nothing, because the file was written from the database it now governs:
|
|
|
|
```
|
|
reconciled '/etc/nxdns/config.zon': no changes
|
|
info(nxdns): authority: file (/etc/nxdns/config.zon)
|
|
```
|
|
|
|
Blocklists, their downloads and the query history all carry over.
|
|
|
|
### Change the configuration
|
|
|
|
Edit the file, check it, restart:
|
|
|
|
```sh
|
|
$EDITOR /etc/nxdns/config.zon
|
|
nxdns check --config /etc/nxdns/config.zon
|
|
systemctl restart nxdns
|
|
```
|
|
|
|
The restart logs what it changed:
|
|
|
|
```
|
|
reconciled '/etc/nxdns/config.zon': upstreams +1 ~0 -0; settings +0 ~2 -0;
|
|
settings keys changed: dns.port web.port
|
|
```
|
|
|
|
Because the file is read at every start, a broken file stops the service at its next restart, whenever that is. If a tool deploys the file, run `nxdns check --config` before it restarts nxdns, so a mistake fails the deploy instead.
|
|
|
|
### Go back to database mode
|
|
|
|
Remove the drop-in and restart. The database already holds the last configuration the file set:
|
|
|
|
```sh
|
|
rm /etc/systemd/system/nxdns.service.d/file-mode.conf
|
|
systemctl daemon-reload
|
|
systemctl restart nxdns
|
|
```
|
|
|
|
```
|
|
info(nxdns): authority: database
|
|
```
|