111 lines
5.1 KiB
Markdown
111 lines
5.1 KiB
Markdown
# Install with Nix
|
|
|
|
Add nxdns to a NixOS machine as a flake input pinned to a release, and run it with the flake's `services.nxdns` module. At the end the machine answers DNS on port 53 from a configuration file that was checked when the system was built.
|
|
|
|
The flake does not build nxdns from source. Its package fetches the release tarball for `x86_64-linux` or `aarch64-linux` and pins its SHA-256, so a changed byte fails the build.
|
|
|
|
## 1. Add the input
|
|
|
|
In your flake:
|
|
|
|
```nix
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
|
|
nxdns = {
|
|
url = "git+https://git.mial.net/mokhtar/nxdns.git?ref=refs/tags/v<version>";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
};
|
|
```
|
|
|
|
Pin a tag, not a branch: a tag never moves under you. The `follows` line saves fetching and evaluating a second nixpkgs. Then write the lock entry:
|
|
|
|
```sh
|
|
nix flake lock
|
|
```
|
|
|
|
## 2. Enable the service
|
|
|
|
Write the configuration next to your NixOS configuration, for example as `nxdns-config.zon`. The smallest one that starts is a group named `default` and one upstream resolver:
|
|
|
|
```zon
|
|
.{
|
|
.groups = .{ .{ .name = "default" } },
|
|
.upstreams = .{ .{ .url = "https://cloudflare-dns.com/dns-query" } },
|
|
}
|
|
```
|
|
|
|
Import the module and enable it:
|
|
|
|
```nix
|
|
{ inputs, ... }:
|
|
{
|
|
imports = [ inputs.nxdns.nixosModules.default ];
|
|
|
|
services.nxdns = {
|
|
enable = true;
|
|
configFile = ./nxdns-config.zon;
|
|
openFirewall = true;
|
|
};
|
|
}
|
|
```
|
|
|
|
Then run `nixos-rebuild switch`.
|
|
|
|
| Option | Default | What it does |
|
|
| --- | --- | --- |
|
|
| `enable` | `false` | Runs nxdns as `nxdns.service`, as the `nxdns` system user. |
|
|
| `package` | the release of the pinned tag | The nxdns release to run. |
|
|
| `configFile` | none, required | The configuration, installed as `/etc/nxdns/config.zon`. |
|
|
| `openFirewall` | `false` | Opens port 53 over UDP and TCP. The web interface (8080) and the DoH and DoT ports stay closed; open them yourself if other machines should reach them. |
|
|
|
|
`configFile` is copied into the Nix store, which every local user can read. Do not put a plaintext `web.password` in it. Use the `web.password_hash` from an export instead, as [Set up admin authentication](set-up-admin-authentication.md#put-a-hash-in-the-file-instead) shows.
|
|
|
|
What the module does:
|
|
|
|
- **The build checks the configuration.** The pinned nxdns loads `configFile` into a throwaway database during the build, so a file nxdns would reject fails `nixos-rebuild` with nxdns's own message, for example `FAIL rules[0].pattern: '(' is not a valid regex pattern`, and nothing is deployed. The build has no network, so it cannot check that the upstreams answer or load DoH and DoT certificates; a missing certificate still stops the service when it starts.
|
|
- **nxdns runs in file mode.** Every start applies the file, and the web interface shows the configuration read-only. To change anything, change the file and switch. A switch that changes only the configuration restarts the service.
|
|
- **The unit is the packaged one**, with its sandboxing. The module only replaces its command line; `systemctl cat nxdns.service` shows both.
|
|
|
|
The module does not touch the machine's own resolver. Point your network at nxdns by setting the DNS server your router hands out to this machine's address, and leave `networking.nameservers` on another resolver, so the machine can still resolve names while nxdns is down.
|
|
|
|
The package alone is `inputs.nxdns.packages.${pkgs.stdenv.hostPlatform.system}.default`, for running nxdns some other way. It installs `bin/nxdns` and `lib/systemd/system/nxdns.service`, and sets `meta.mainProgram`.
|
|
|
|
## 3. Upgrade
|
|
|
|
Read the release notes, change the tag in the input URL, then:
|
|
|
|
```sh
|
|
nix flake lock --update-input nxdns
|
|
nixos-rebuild switch
|
|
```
|
|
|
|
Rolling back to an older generation puts an older nxdns in front of a database the newer one may already have upgraded. The older binary then refuses to start; [Upgrade](upgrade.md#going-back-to-an-older-release) explains the way back.
|
|
|
|
## Let Renovate bump the tag
|
|
|
|
Renovate's built-in `nix` manager cannot do this: it only moves `flake.lock` along the ref an input already follows, and a tag ref never moves. A regex custom manager that reads the tag from the input URL, with the `gitea-tags` datasource, does:
|
|
|
|
```json
|
|
{
|
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
"extends": ["config:recommended"],
|
|
"customManagers": [
|
|
{
|
|
"customType": "regex",
|
|
"managerFilePatterns": ["/^flake\\.nix$/"],
|
|
"matchStrings": ["git\\+https://git\\.mial\\.net/mokhtar/nxdns\\.git\\?ref=refs/tags/(?<currentValue>v\\d+\\.\\d+\\.\\d+)"],
|
|
"depNameTemplate": "mokhtar/nxdns",
|
|
"datasourceTemplate": "gitea-tags",
|
|
"registryUrlTemplate": "https://git.mial.net",
|
|
"versioningTemplate": "semver"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
Its pull request changes the tag in `flake.nix` only. The same pull request also needs a refreshed `flake.lock`: run `nix flake update nxdns` as a `postUpgradeTasks` command (self-hosted Renovate, with `allowedCommands`), or have CI commit the lock on the Renovate branch.
|
|
|
|
A tag can exist for a short while before its release files are uploaded. A pin made by hand in that window fails the build with a 404 from the download URL; build again once the release is published.
|