In the last post, I admitted to dropping the ball on my home server upkeep and explained how I was going to remedy that with NixOS instead of Ubuntu Server. It's been (over) an entire month and there are some things I need to say out loud about my experience so far.
First of all, I am going to spoil this entire post up front by saying that I am absolutely thrilled with how this decision turned out. After a month of getting my server where it needs to be and having everything declared in a few NIX files, I can confidently say that I know exactly what's on my server and how it works. It's all self documented . . . maybe more like 99% but more on that later. I did take the route to not having the entire configuration inside of my Configuration.nix file, as I thought it would be better to break things out into modular pieces. All Nix files are backed up on a private Github repo and I make a commit each time there is a significant, yet successful change.
There have been many times that I've misspelled something or forgot to add a semi-colon at the end of a line in an Nix file, but NixOS is really good at telling me that I screwed up, thus not building the new generation of my configuration. It's been rare that an error message was confusing and not straight forward when trying to rebuild, but even so, I can always go back one generation in a matter of minutes and be exactly where I was at the last rebuild point.
Here are a few examples of how easy it was to convert everything over to "the Nix way":
- My server has a total of 5 hard drives (2 SSD, 3 HDD), so getting 4 of them (not including the OS drive) to auto mount took about 2-3 lines per drive. You could add 1 more line per drive to verify and make sure that the custom mount point folders exist before the mount occurs. This is very similiar to setting it up manually in /etc/fstab, but not as complicated.
- Samba shares took the same amount of lines as you would in a typical Samba config file.
- Setting up a static IP is just a few lines.
- I went with KDE as a Desktop Manager, but I can just as easily go with anything else if I want. It's a simple change of a few lines in my Nix config file, rebuild and reboot.
- Adding in Public SSH keys for SSH access is a simple copy and paste.
- Custom settings for SSH, ZSH, OhMyZsh, and Neovim are guaranteed. Now SSH is even more a joy to use as it is my primary way of server access. Since I keep these things simple, I don't have to keep up with them in a 'dotfile' folder.
- If you install a Nix Package for an application, most of them have an option to "Open Firewall", so the hassle and guess work is done for you. All other ports are closed, however you can manually open up specific ports just as easily if you need to.
So, what's the downside? I went into this transition trying to learn how I can declare everything possible, trying to get 1:1 with the Nix universe. One of these things was to declare all Docker containers using OCI Containers in a single NIX file. It took me a little while to understand the formatting, but I made most of it work . . . except a few containers just wouldn't work for some reason. It was like some of the options like "restart" or "network" wasn't being read by Docker and I could not build with this version of the file. I know that I need to spend some more time with it but this is honestly a back burner item for now.
To add on to this issue, I did run into a few Nix packages that, honestly, the Docker containers were just easier to deal with or were more up to date. A good example is Borgmatic, an app that makes Borg backups a little easier to deal with and has some great options. My goal with my Borg backups is to get a notification if the backup is successful or failure via my private Discord channel. This meant that I would have to use version 1.8.13 or greater of Borgmatic to get Apprise and Uptime Kuma support, however the Nix package (as of 7/8/2024) was stuck on 1.8.11. This is probably the biggest struggle that I've had in the last month but the answer was in front of me the whole time: just build a Docker container until the Nix package is updated (or not). I was able to find a Docker container with the latest version, get it setup with a Compose file, and notifications are now working like I want them to.
I'm still learning about a few things, especially how to properly maintain the server and keep it updated. Funny enough, Nix has built in options to do automatic updates and garbage collection. It's rare that you will ever need to go back to a generation from 3+ months ago, so why keep it around? NixOS can automatically delete generations older than a specified date. Very simple.
It's just such a great feeling to know that everything is documented, easy to restore, and even if I had to reinstall the entire OS and rebuild with my custom configuration file. It's a one time setup for forever.
If you haven't tried NixOS, I highly recommend spinning it up in a VM and just giving it a shot. You will be surprised.