Moved to NixOS almost 5 years ago now and haven’t looked back, my router config is in Git and I’m able to make changes with confidence.
Best part is making a change/installing an update and being able to rollback if I mess something up. I also use Nixus to push new configs which has a nifty feature where it will autorollback if you e.g make a config change that locks you out of SSH.
I also moved from ESXI to NixOS for a virtualisation host more recently and that has been great as these machines are inherently long lived so you can’t apply the “cattle not pets” mindset here, but I feel like I can make changes and install updates with confidence. It also helped when I migrated to a Threadripper build where there were some strange quirks which needed Linux kernel patches, it’s nice being able to do this declaratively and to store everything in a versioned Git repo.
A couple years ago I was searching for a good way to declaratively manage them, and the best I came up with was libvirt + terraform + nixos-generators for images. It feels like you should just be able to set them up as systemd units, but I couldn’t figure it out.
microvm has caught my eye recently but I haven’t played with it yet: https://github.com/astro/microvm.nix
However, none of my VMs are always-on, so I don’t have to deal with restarts on config change. That said, when libvirt isn’t managing the lifecycle of the VMs as much, writing a systemd unit should be quite a bit easier.
MicroVM looks awesome though, thanks for the pointer!
I've been using OPNSense[0] as my router for the past several months. So far, I am quite happy with it, but I've also thought that NixOS would be the next step.
My OPNSense router has 30+ VLANs and many layered firewall rules (my take on "zEr0 tRuSt") and so the task of converting it all to NixOS seems a little daunting.
I appreciate the utility of OPNSense's web GUI when configuring and troubleshooting my router config. It would be awesome if something like that could be integrated with NixOS. Additionally, something like nsh[1] to provide a traditional router/switch style CLI would be a dream come true.
I haven’t done much with vlans yet so I can’t comment on that.
NixOS still does everything I need it too, but the parent comment sounded like they had a bit more complex of a setup.
{ pkgs, lib, ... }:{
networking = {
useNetworkd = true;
useDHCP = false;
enableIPv6 = true;
};
networking.wireguard.interfaces = {
wireguard = {
ips = [ "172.20.60.1/24" ];
listenPort = 61891;
privateKeyFile = "/etc/nixos/secrets/wireguard-privateKey";
peers = [
{
publicKey = "897mRPejuv9yVnmTvcUL7ckQkIiM0wnSgHmgR15Evyw=";
allowedIPs = [ "172.20.60.10/32" ];
presharedKeyFile = "/etc/nixos/secrets/wireguard-presharedkey";
}
... systemd.network.networks = {
"10-eno1" = {
matchConfig.Name = "eno1";
networkConfig.LinkLocalAddressing = "no";
networkConfig.DHCP = "no";
extraConfig = ''
VLAN=wan
VLAN=vlan99
VLAN=vlan30
VLAN=vlan20
VLAN=vlan1
VLAN=podnet
LLDP=no
EmitLLDP=no
IPv6AcceptRA=no
IPv6SendRA=no
'';
};
"11-vlan1" = {
matchConfig.Name = "vlan1";
linkConfig.RequiredForOnline = false;
networkConfig.DHCP = "no";
networkConfig.Address = "192.168.1.1/24";
networkConfig.Domains = "tanso.net";
networkConfig.ConfigureWithoutCarrier = "yes";
};
"11-podnet" = {
matchConfig.Name = "podnet";
linkConfig.RequiredForOnline = false;
networkConfig.DHCP = "no";
networkConfig.Address = "172.20.2.1/24";
networkConfig.Domains = "tanso.net";
networkConfig.ConfigureWithoutCarrier = "yes";
};
"11-vlan20" = {
matchConfig.Name = "vlan20";
networkConfig.DHCP = "no";
networkConfig.Address = "172.20.20.1/24";
networkConfig.Domains = "tanso.net";
networkConfig.ConfigureWithoutCarrier = "yes";
extraConfig = ''
IPv6SendRA=yes
DHCPv6PrefixDelegation=yes
'';
};
.... systemd.network.netdevs = {
"11-vlan1" = {
netdevConfig = { Name = "vlan1"; Kind = "vlan"; };
vlanConfig.Id = 1;
};
"11-podnet" = {
netdevConfig = { Name = "podnet"; Kind = "vlan"; };
vlanConfig.Id = 2;
};
"11-vlan20" = {
netdevConfig = { Name = "vlan20"; Kind = "vlan"; };
vlanConfig.Id = 20;
};
"11-vlan30" = {
netdevConfig = { Name = "vlan30"; Kind = "vlan"; };
vlanConfig.Id = 30;
};The options under systemd.network almost map 1:1 to systemd-networkd ones.
As other commentators have said, switching to systemd networkd has allowed for more advanced network configurations than I ever managed with pfSense. IPv6 works pretty much out of the box with my ISP which uses DHCP prefix delegation, I can assign /64's to different VLAN networks, and more recently I set up network prefix translation (I think that's what it's called) for my lab kubernetes cluster so each pod gets a unique IPv6 address in the RFC 4193 range which maps to my actual ISP provided IPv6 prefix, so if I change ISP the IPs in the cluster would remain the same. Being able to expose Kubernetes services directly to the internet with unique IPv6 addresses is pretty nice :)