I moved to NixOS
I tried Nix the package manager and home manager so many times on my Archlinux computer, but I never got the hang of it. I saw it as more trouble than it's worth cause I could already get latest packages for everything I need on Arch. I didn't look at NixOS the operating system cause I heard people say that you don't need to be on NixOS to use Nix and see the power of Nix. And, maybe that's true for people whose distro doesn't ship latest packages, but to me it was more trouble than it's worth. I was bored on a random day and decided to boot up NixOS in a VM and that was the real deal. What do you mean I can install steam with programs.steam.enable = true
? Is steam built into this...language?
If I want to my computer to do something the first place I go to is the options search engine. If it's not there, I go to the packages search engine and configure the application traditional way. I have these search engines in my browser just two keystrokes away:
Yes, it's a pain to port your existing config to Nix, but it's nice when you don't have to learn yet another config when you want to try something new. The best part is that you don't need to port your config cause there's always a way to refer to your external config file. You can't mix and match Nix options with the external config file, though. For example, this is what my Caddy service looks like:
services.caddy = {
enable = true;
configFile = ../Caddyfile;
};
Caddyfile
is in the same git repo so it's all declarative for all I care and I don't have to learn the Nix way of configuring it.
The server
I had recently bought a new VPS and had to migrate all my stuff there cause it's cheaper than what I was paying then. So it was the perfect place to experiment with Nix. I wanted to move services out of docker into the host. Not everything cause some applications have better support for docker (immich). But, I have a central PostgreSQL service running on the host that stores data for a bunch of containers. I experimented with moving some services to Nix, but for many it was too much work. As of now, I have Caddy, Anki sync server, Vaultwarden, Ntfy, and a Tor relay which are part of configuration.nix
that used be in compose.yml
. It may not sound like much of any achievement but my sysadmin-fu is not so great and it would be so much more work to keep track of all of them and migrating servers would be nightmare.
My favorite is how easy it is to create services in Nix. No need to worry about what service unit files and timer unit files to write and where to put them cause Nix has OOTB support for many common services that you might need to write manually. For example here's my BorgBackup service:
services.borgbackup.jobs = {
crashRsync = {
paths = [ "/root" "/home" "/var/backup" "/var/lib" "/var/log" "/opt" "/etc" "/vw-data" ];
exclude = [ "**/.cache" "**/node_modules" "**/cache" "**/Cache" "/var/lib/docker" ];
repo = "de3911@de3911.rsync.net:borg/crash";
encryption = {
mode = "repokey-blake2";
passCommand = "cat /run/secrets/borg/crash";
};
environment = {
BORG_RSH = "ssh -i /home/yt/.ssh/id_ed25519";
BORG_REMOTE_PATH = "borg1";
};
compression = "auto,zstd";
startAt = "hourly";
extraCreateArgs = [ "--stats" ];
# warnings are often not that serious
failOnWarnings = false;
postHook = ''
${pkgs.curl}/bin/curl -u $(cat /run/secrets/ntfy) -d "chunk: backup completed with exit code: $exitStatus
$(journalctl -u borgbackup-job-crashRsync.service|tail -n 5)" \
https://ntfy.cything.io/chunk
'';
};
};
See? It's all options. I read the very helpful wiki page and I converted my bash script to this in minutes. I use sops-nix to manage secrets and it integrates well with everything.
The configuration.nix
is here if you're interested.
The PC
I tried to use the graphical installer hoping it'd be faster, but I couldn't do things like Btrfs and LUKS easily. I tried but something would go wrong and I don't think there even was an option for Btrfs. But I'm glad that I had the graphical ISO cause I could have firefox and a terminal side-by-side instead of just a TTY.
I still don't use home-manager for my other config files. I tried once, but it was too much work and reverted back. I use it to configure GTK and Qt themes, but that's it. Maybe I'll use it in the future if I want to configure something new.
# home.nix
qt = {
enable = true;
platformTheme.name = "gtk";
style.name = "adwaita-dark";
style.package = pkgs.adwaita-qt;
};
gtk = {
enable = true;
cursorTheme = {
package = pkgs.bibata-cursors;
name = "Bibata-Modern";
};
theme = {
package = pkgs.adw-gtk3;
name = "adw-gtk3-dark";
};
iconTheme = {
package = pkgs.adwaita-icon-theme;
name = "Adwaita";
};
};
You can find the complete home.nix
here.
It's also fairly easy to compile from master (or a specific commit) for most packages. This is what I did when I wanted to try a recently merged PR for restic:
pkgs.restic.overrideAttrs {
src = pkgs.fetchFromGitHub {
owner = "restic";
repo = "restic";
rev = "1133498ef80762608f959df41d303f7246fff04f";
hash = "sha256-RmCEZ5T99uNNDwrQ3CofXBf4UzNjelVzyZyvx5aZO0A=";
};
vendorHash = "sha256-TstuI6KgAFEQH90PCZMN6s4dUab2GyPKqOtqMfIV8wA=";
};
rev
is the commit hash, hash
is the sha256sum of the source at that specific commit and vendorHash
is the sha256sum of all dependencies of the package. You don't need to worry about the last two, Nix will figure it out.
I have similar services for Borg and Restic backups like with the server. Additionally, I take advantage of btrfs snapshots.
services.btrbk.instances.local = {
onCalendar = "hourly";
settings = {
snapshot_preserve = "8w 12m";
snapshot_preserve_min = "2d";
snapshot_dir = "/snapshots";
subvolume = {
"/home" = {};
"/" = {};
};
};
Other than that, it's not much different than it used to be with Archlinux. It did take a lot of time to configure all of it, but now I have everything I used to with Arch and more. If you want to check it out, the configuration.nix
is here.