Build A Dns Server On Nixos
06 Nov 2022You might remember my blog posts from 2016 where I documented my dnsmasq setup. I run a primary setup on NetBSD and a secondary on Debian. (Checkout the linked blog posts if you are interested)
The reasons and use-cases are still the same but this time I gave NixOS a chance since it was time to upgrade the Debian installation.
It was surprisingly easy after a few start hurdles, where I struggled to get any output on my 4k display. Using a older 1080p monitor solved that for me.
Getting started
Since I used a Raspberry Pi 3 I could use the latest AArch64 image from Hydra (source: https://wiki.nixos.org/wiki/NixOS_on_ARM#Installation). In my case that was the release-22.05 https://hydra.nixos.org/job/nixos/release-22.05/nixos.sd_image.aarch64-linux.
Unpacking and flashing this image to the SD Card works the same as with all other Raspberry Pi images. Make sure you flash it to the correct device!
wget https://hydra.nixos.org/build/197683332/download/1/nixos-sd-image-22.05.3977.f09ad462c5a-aarch64-linux.img.zst
unzstd nixos-sd-image-22.05.3977.f09ad462c5a-aarch64-linux.img.zst
cat unzstd nixos-sd-image-22.05.3977.f09ad462c5a-aarch64-linux.img > /dev/sdX
After doing this it should be possible to boot up NixOS for the first time.
Basics
Start with generating a basic configuration with:
sudo nixos-generate-config
Lets add a user and some packages (vim
and ping
) which I want to have on my new system.
# Define a user account. Don't forget to set a password with ‘passwd’.
users.users.l33tname = {
isNormalUser = true;
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
};
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
vim
inetutils # ping
];
Network
The networking is a bit more involved. I need a static IPv4 and IPv6. Default routes and DNS server.
Very straight forward after I understood the concept.
networking.useDHCP = false;
networking.interfaces.eth0 = {
useDHCP = false;
ipv4.addresses = [
{ address = "192.168.17.7"; prefixLength = 24; }
];
ipv6.addresses = [
{ address = "2001:XXXX:XXXX::7"; prefixLength = 64; }
];
};
networking.defaultGateway = { address = "192.168.17.1"; interface = "eth0"; };
networking.defaultGateway6 = { address = "2001:XXXX:XXXX::1"; interface = "eth0"; };
networking.nameservers = [ "127.0.0.1" "8.8.8.8.8" ];
Dnsmasq
UPDATE: take a look at the update configuration for NixOS 23.05 where i fetch the hosts file from a url.
Last the main event to configure my dnsmasq server the same way I did on my Debian.
And as you can see from the config I just created a hosts.txt
file which will be merged with /etc/hosts
.
(I am thinking about fetching this file from a local webserver or git repo)
# List services that you want to enable:
networking.hostFiles = [ /etc/nixos/hosts.txt ];
services.dnsmasq.enable = true;
services.dnsmasq.alwaysKeepRunning = true;
services.dnsmasq.servers = [ "85.214.73.63" "208.67.222.222" "62.141.58.13" ];
services.dnsmasq.extraConfig = "cache-size=500";
Putting it all together
This gives me a config which looks something like this:
{ config, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
# Use the extlinux boot loader. (NixOS wants to enable GRUB by default)
boot.loader.grub.enable = false;
# Enables the generation of /boot/extlinux/extlinux.conf
boot.loader.generic-extlinux-compatible.enable = true;
networking.hostName = "nixos"; # Define your hostname.
# Pick only one of the below networking options.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
# networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
# Set your time zone.
time.timeZone = "Europe/Zurich";
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
# Define a user account. Don't forget to set a password with ‘passwd’.
users.users.l33tname = {
isNormalUser = true;
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
};
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
vim
inetutils # ping
];
networking.useDHCP = false;
networking.interfaces.eth0 = {
useDHCP = false;
ipv4.addresses = [
{ address = "192.168.17.7"; prefixLength = 24; }
];
ipv6.addresses = [
{ address = "2001:XXXX:XXXX::7"; prefixLength = 64; }
];
};
networking.defaultGateway = { address = "192.168.17.1"; interface = "eth0"; };
networking.defaultGateway6 = { address = "2001:XXXX:XXXX::1"; interface = "eth0"; };
networking.nameservers = [ "127.0.0.1" "8.8.8.8" ];
# List services that you want to enable:
networking.hostFiles = [ /etc/nixos/hosts.txt ];
services.dnsmasq.enable = true;
services.dnsmasq.alwaysKeepRunning = true;
services.dnsmasq.servers = [ "85.214.73.63" "208.67.222.222" "62.141.58.13" ];
services.dnsmasq.extraConfig = "cache-size=500";
# Enable the OpenSSH daemon.
services.openssh.enable = true;
}
After that we can build and install this config. It helps to set a password for the newly created account.
sudo nixos-rebuild switch
passwd l33tname
After a reboot lets see if everything booted correctly and you can login over ssh with the new user.
Misc
Over all it was a pleasant experience to setup NixOS.
I think to keep it up to date I will run nixos-rebuild switch --upgrade
from time to time.
A thing I used a bunch is the options search from NixOS at: https://search.nixos.org/options to read the docs for config keys or finding the correct config key.
Last but not least I want to point to these four resources which helped me to understand how to configure my system.