Despite being a NixOS setup which should be reproducible on paper, it mainly uses the unstable versions of the channels and packages meaning you would have a different installation each time (unless you do something like https://nixos.org/guides/towards-reproducibility-pinning-nixpkgs.html[pinning the nixpkgs repo] or using https://www.tweag.io/blog/2020-05-25-flakes/[the flakes feature]).
footnote:[I'm most likely using the Nix flakes some time in the future.]
* The main user configuration is tightly integrated with the system configuration.
In other words, all upgrades would have to affect the entire system.
If you want separate user profiles (just like how Nix intended to be) with each user having its own pace of upgrading their local system, you're missing out with this config setup.
That said, it is still possible to create user profiles by just declaring the user in `./hosts/$HOST/default.nix` (e.g., `users.users.$USERNAME`), leaving it blank, and configure it at your own pace in `$HOME`.
* The directory paid with the most attention would most likely be the `modules/` folder which contains cluster-wide footnote:[Whenever I say 'cluster-wide', I really mean my laptop (which I have none at the moment) and desktop (which I have only one at the moment).] modules intended to be used in each device.
It is also used on the installation phase (from `make install`) by setting the `HOST` variable (i.e., `HOST=zilch make -C /etc/install`) with the folder name as the argument.
* A little library in link:./lib[`./lib`] based from https://github.com/hlissner/dotfiles[original source] which being used for various uses (e.g., limiting certain modules).
* Though my custom packages are now placed in my https://github.com/foo-dogsquared/nur-packages[NUR repo], the `packages/` folder still exists here intended for "private" packages.
Also contains third-party package repositories and overlays such as the https://github.com/nix-community/NUR[NUR], https://github.com/nix-community/emacs-overlay[unstable branch of Emacs], or the unstable branch of https://github.com/NixOS/nixpkgs/[nixpkgs].
* The `templates/` directory is a bunch of https://github.com/cookiecutter/cookiecutter/[Cookiecutter] templates intended for easy creation/deployment of customized systems (e.g., graphical desktop environments, customized modules).
== Hosts
Each machine is represented with a directory in link:./hosts/[`./hosts`] with the name of the directory as the name of the machine.
footnote:[It is basically using the pets approach (from pets versus cattle thing).]
Each host should have an entrypoint at `./hosts/$HOST/default.nix` which is then used from the entrypoint of this setup at link:./default.nix[`./default.nix`] (i.e., `import /etc/dotfiles "$HOST" "$USER"`).
It may contain machine-specific configurations (e.g., specific systemd units, Recoll index building, GNU Nano configurations), other Nix modules for modularity, and other sorts of knick-knacks (e.g., other wallpapers, machine-specific scripts).
For best practice, you may want to follow the following project structure:
[source, tree]
----
./hosts/$HOST
├── config/
├── modules/
├── default.nix*
└── README.adoc
----
* `config/` contains the specific config files.
* `modules/` stores the other Nix modules to be used in `default.nix`.
* `default.nix` is the entrypoint for our host module.
It contains configuration of our link:./modules[`./modules`], NixOS (i.e., `man configuration.nix`), https://github.com/rycee/home-manager[home-manager] (i.e., `man home-configuration.nix`), and other things you might want to include in the host-specific `$HOST/modules/` folder.
* A README file in whatever format you prefer.
(I just choose https://asciidoctor.org/[Asciidoctor] with the `.adoc` file extension since it's my go-to document format.)
This lets me easily switch my graphical setup with a simple toggle (i.e., `theme.$THEME_NAME.enable = true;`) in my machine configuration (i.e., `./hosts/$HOST/default.nix`).
For safety from conflicting modules and configuration, you should have a bare installation ala-Arch Linux.
A wallpaper can be placed at `config/wallpaper` for convenience.
* `default.nix` is simply the entry point for our theme module.
This is where you can add certain packages, enable certain settings, setup your files to the home directory, and pass the theme metadata.
* For convenience, you should make the NixOS theme module as a https://github.com/cookiecutter/cookiecutter[Cookiecutter template] to easily replace the color schemes, fonts, and what-have-you.
The link:./packages/[`./packages/`] directory contains cluster-wide https://nixos.wiki/wiki/Overlays[overlays], https://nixos.wiki/wiki/Nix_Channels[channels], and custom packages.
The overlays should be put in a separate folder in `./packages/overlays/`.
For any other packages, it should be put on the same level as `./packages/default.nix`.
Even though I have https://github.com/foo-dogsquared/nur-packages[a separate repo] for my packages, the packages defined here is only applicable to the setup.
To make this section longer, here is the workflow summary in creating a package:
- Create a test file (i.e., `./packages/$PACKAGE.nix`).
Either as an initial draft or a final prototype that you'll never check once it successfully built.
- Fetch the to-be package.
In case you want to know the SHA256 hash of the to-be package from fetching (e.g., `fetchTarball`, `fetchFromGitHub`), you can use `lib.fakeSha256` and wait for the error to appear.
It should give you the expected hash.
footnote:[Don't forget to visit the nixpkgs repo and look at the source code for the nth time.]
- Give the build inputs and the instructions for individual phases (e.g., `unpackPhase`, `preInstallPhase`, `buildPhase`).
== Why NixOS?
It'll be a full-time geeky story if I have to explain so I'll put it in a bullet list.
* You can configure your system from the system-wide packages, user-specific packages, boot loader settings, graphical environments, and what-have-you stored in text files.
That fact alone blew my mind ever since I saw @hlissner's NixOS and the temptation just keeps growing ever since I see more NixOS-related posts.
This is where the real power of NixOS (and also https://guix.gnu.org/[GuixSD]) really made it worth the try: declarative system and local configuration.
* A https://github.com/NixOS/nixpkgs/[gigantic package set] featuring \~65000 packages (similar number to AUR) as of 2020-10-29.
While NixOS is technically a source distribution (e.g., Gentoo, KISS Linux), with the reproducibility features of Nix, its https://hydra.nixos.org/[build farm], and its https://cache.nixos.org/[very large cache], you get the binary artifacts for most of its packages for free.
footnote:[If you want NixOS to be "truly a source distro", you can disable it by setting no binary caches in `nix.binaryCaches`.]
** With https://nixos.org/nixpkgs/manual/[overlays], you can change how the package is built from its source to its build instructions.
I was able to get up and running with NixOS in a day (which is impressive for the smoothbrain that I am) thanks to these resources:
* https://nixos.org/manual/nixos/[The NixOS manual] is your starting point.
Personally, I find it a bit confusing but it is still good to get an installation working.
* https://www.youtube.com/watch?v=NYyImy-lqaA&list=PLRGI9KQ3_HP_OFRG6R-p4iFgMSK1t5BHs[The Nixology video series by Burke Libbey] which gives a practical insight on Nix and NixOS, in general.
I give it a wholehearted recommendation to check it out.
* I learn a whole lot from tinkering with https://github.com/hlissner/dotfiles[@hlissner's dotfiles].
It's like the practical application of the things I've learned for the day.
Though, it did cost me to spend a week debugging footnote:[Which mostly compose of trial-and-erroring the hardcore way.] the config from the never-ending tinkering (which is a stupid decision on my part).
It could've been resolved in a day or two if I had joined the https://discord.gg/qvGgnVx[Doom Emacs Discord server].
* Speaking of the Doom Emacs Discord server, the https://discord.gg/qvGgnVx[Doom Emacs Discord server] is pretty cool.
Despite it is a Discord server on Doom Emacs, it is welcoming on non-Doom Emacs stuff and you can find a lot of NixOS (and Guix) geeks over there.
* With the https://stephank.nl/p/2020-06-01-a-nix-primer-by-a-newcomer.html[help of the newcomers documented their learnings], I was able to quickly pick the terminologies surrounding the system.
If you want to look out for some go-to resources, the https://nixos.org/learn.html[official manuals] will never fade in the list.
It may be horrible for a newcomer (in my opinion) but it is great for someone who's already familiar with Nix.
The https://nixos.wiki/[unofficial NixOS wiki] is one of the more reliable sources especially with its practical example.
For more learning on the Nix conventions, ecosystem, and practices, I recommend https://nix.dev/[nix.dev] to look out for.
It provides some information that the official (and unofficial) sources misses.
* The filesystem hierarchy standard is completely thrown out of the window.
This means prebuilt binaries (including https://appimage.org/[AppImages]) will not work since the libraries needed are not in the intended locations.
If you want to use them inside Nix (or NixOS), you have https://nixos.wiki/wiki/Packaging/Binaries[to package them].
Thankfully, `/usr/bin/env` is kept for your user scripts.
* While the Nix language is nice and all, the https://github.com/NixOS/nixpkgs/tree/master/lib[standard library] which is essential if you want to go far with Nix, is pretty hard to navigate for a newcomer.
* Fully going into the "Nix way" is sometimes painful with the effort required to package a certain program compared to.
On the other hand, it is "write once, build everywhere".
* The error messages are horrible (when it's horrible)!
There is a https://opencollective.com/nix-errors-enhancement/updates/revising-our-road-map-phase-3[recent push on improving Nix in that aspect] but it focuses on the formatting.
The interpreter sometimes points at the opposite way (at least to me).