Files
nxdns/docs/how-to/install-with-nix.md
T

5.0 KiB

Install nxdns with Nix

Adds nxdns to a NixOS machine as a flake input pinned to a release tag. At the end pkgs-style references to inputs.nxdns.packages.${system}.default resolve to the published release binary, and a Renovate custom manager opens a pull request when a new tag appears.

nxdns publishes its own flake.nix. Its packages do not build nxdns from source: each one fetches the release tarball for the target and pins its SHA-256 hash, so a changed byte fails the build. The two supported systems are aarch64-linux and x86_64-linux, both static musl builds that need nothing on the host.

For the signature and checksum checks a human does once, see verify a release. For what each configuration field means, see the configuration reference.

Verification: the commands in step 1 and step 2 were run on the machine that wrote this page, against the flake at nxdns 0.0.16. nix flake check --no-build passed and nix build produced a binary that printed nxdns 0.0.16. The consumer snippets in step 3 and step 4 are copied from the shape rpi.mial.net already uses for another flake input of the same author; they were not evaluated from this checkout, which is not a NixOS configuration.

1. Add the input, pinned to a tag

In the consuming flake:

inputs = {
  nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";

  nxdns = {
    url = "git+https://git.mial.net/mokhtar/nxdns.git?ref=refs/tags/v0.0.16";
    inputs.nixpkgs.follows = "nixpkgs";
  };
};

Pin a tag, not a branch. A branch pin moves the version under you at the next nix flake update, and the hashes in the flake belong to whatever release that branch last cut.

The follows line is not cosmetic. Without it Nix fetches and evaluates nxdns's own nixpkgs as a second nixpkgs, which costs a download and an evaluation for a package that only needs stdenv, fetchurl, and lib.

Write the lock entry:

nix flake lock

2. Check what you pinned

nix flake check --no-build
nix eval .#packages.x86_64-linux.default.outPath

Evaluation does not fetch the tarball. The download happens at build time, and the hash in nxdns's flake is what the build asserts the bytes against.

3. Use the package in a NixOS configuration

Pass the flake inputs to the module system, then reference the package:

{ inputs, pkgs, ... }:
{
  environment.systemPackages = [ inputs.nxdns.packages.${pkgs.stdenv.hostPlatform.system}.default ];
}

The derivation installs bin/nxdns, plus LICENSE and THIRD-PARTY-NOTICES under share/doc/nxdns. It sets meta.mainProgram, so lib.getExe resolves to the binary. Run it as a service with the unit from install with systemd, or write your own module around it.

4. Let Renovate bump the tag

Renovate's built-in nix manager does not do this. It only advances flake.lock along the ref an input already tracks, and a refs/tags/vX.Y.Z ref never moves, so it reports no releases for a tag-pinned input. Verified on 2026-09-09 with Renovate 42.99.0 against a Gitea host: all flake inputs, GitHub-hosted ones included, came back with an empty release list.

What works is a regex custom manager that treats the tag in the input URL as a version string, with the gitea-tags datasource:

{
  "$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"
    }
  ]
}

Verified on 2026-09-09: with this manager, Renovate opened the pull request for v0.0.18 on the day of the tag. That pull request rewrites the tag in flake.nix only. flake.lock still records the old revision, so the same pull request must also refresh the lock, either with a postUpgradeTasks command (nix flake update nxdns, which needs the self-hosted allowedCommands setting) or with a CI job on the Renovate branch that commits the lock. The datasource proposes only tags that already exist, so it never pins a release that has not been cut.

Between the tag push and the asset upload there is a window in which the tag exists and the release tarballs do not. A pin written by hand during that window evaluates, then fails at build time with a 404 from the release download URL. Wait for the release to be published, or re-run the build once it is. Renovate's own pull requests are not affected by the window in practice, because it runs on a schedule rather than on the tag push.

Upgrading

Change the ?ref=refs/tags/vX.Y.Z in the input, run nix flake lock --update-input nxdns, and rebuild. Read the release notes first: nxdns is pre-0.1 and breaks on purpose, and upgrade lists what state a version change touches.