nixos-config/README.adoc

19 KiB
Raw Blame History

This is my NixOS config as a Nix flake.

I finally have some time trying to grok flakes and redo my NixOS config from scratch after leaving it for some time (because I have work and have to quickly set things up without me trying to debug how NixOS works). Here is the result.

Getting started

Caution

Despite being a NixOS system, it isnt entirely reproducible to the point of installing this config will work out-of-the-box. It has some things needed in the first place to work like my external backup setup where it needs my SSH private keys to work in the first place. Nonetheless, the parts is it isnt reproducible is only about 10% of this config. Everything else is fine and dandy.

Oh right… Dont expect everything is working in each commit but Im doing my best to make them build successfully in each, yeah?

Also, this configuration is expected to use under non-restricted evaluation mode.

Hey there, fellow traveler! Youve fell into the rabbit hole we call Nix where it leads to other rabbit holes such as functional package management, reproducibility, declarative systems, and immutable operating systems.

This is one of the many tickets to that rabbit hole, allow me to be your guide in this mark:[painful] wonderful declarative journey. Hope to see you on the other side!

Installation

Since this uses Nix flakes, you should have Nix v2.8 and above installed.

If youre going to install one of my NixOS configs, be sure to download the unstable versions from their release page. As an additional option, you can also use my personalized NixOS installers which is primarily intended for me configs.

This primarily uses Nix flakes so you can have a preview of whats available in my config.

nix flake show github:foo-dogsquared/nixos-config

It should export my NixOS configurations of my different hosts (of only one so far excluding VMs and VPSs ;p) among other things. To install it, run the nixos-install --flake github:foo-dogsquared/nixos-config#ni. (Please see the respective appropriate host README for more information.)

Channels support

While this primarily uses flakes as its main form of distribution, this project does keep some use cases for traditional channels. Its not guaranteed to be good as using it [using-my-config-with-flakes] but its an option.

The entry point is found at ./default.nix. However, you have to keep some limitations and guidelines in mind.

  • It exports an attribute based from the NUR template.

    Several exports includes…

    • My custom library at lib.

    • Custom NixOS modules at modules.

    • Custom home-manager modules at hmModules.

    • An overlay of my custom packages at overlays.foo-dogsquared-pkgs.

    • My packages as the rest of the top-level attributes from the attrset.

  • Keep in mind it doesnt export the NixOS hosts and home-manager user configurations. It would be pointless as it is duplicating effort plus I really like managing my NixOS config more with the flakes way compared to setting up channels. It has a lot of advantages such as the ease of provisioning and updating your setups along with its dependencies, enforcing certain values in a certain attribute that can be seen in the revised Nix CLI, and nicer interface overall. While possible with channels, this is just better experience overall and I have no interest in maintaining setups in both ways.

Whats in my flake?

You can see the full details with nix flake show. As a helpful summary, heres what my flake should contain sorting from the most interesting and helpful outputs to the most boring and unnecessary.

  • packages contains my custom packages and some of usual images of several hosts which is nice for easily fetching custom images.

  • overlays contains the overlay for extending nixpkgs with my packages. If you want to use my packages alongside the nixpkgs attribute then this is what youre looking for.

  • homeModules are where my custom home-manager modules to be exported. [1]

  • nixosModules are composed from NixOS modules defined in ./modules/nixos. It can be used as additional modules for your own NixOS config in case you want to use mine for whatever reason. There are some niceties in there.

    A few examples include:

    • A NixOS module for Pop launcher plugins and scripts.

    • Several service modules for archiving with yt-dlp, gallery-dl, and ArchiveBox.

    • My themes which contain full desktop environments which is nice for quickly initializing a NixOS configuration.

  • devShells from my custom environments. Similar to homeConfigurations, you can easily use it outside of NixOS.

  • homeConfigurations contains my various home-manager configurations from ./users/home-manager/. The neat thing about it is you can easily install it in a non-NixOS Linux distro.

  • deploy are nodes to be deployed by deploy-rs. Its nice and currently not all of the nodes are publicly committed which is less useful but itll be someday.

  • nixosConfigurations which is where you can install my various NixOS configurations directly (e.g., nixos-install --flake github:foo-dogsquared/nixos-config#HOST). This mainly uses the hosts configuration.

  • templates which contains my templates. Though, these are just templates mostly for my own purposes so it is not as useful as the other outputs.

  • hydraJobs contains Hydra build jobs where it is primarily used for my test Hydra instance.

  • lib is defined from my custom library. It mainly assumes it is to be included in nixpkgs standard library (i.e., import ./lib { lib = inputs.nixpkgs.lib; }). Its another unnecessary export but its there.

  • formatter is the preferred formatter to be used for my Nix files. Nothing special here.

  • checks contains checks for several outputs and are mainly for internal purposes. Theres no use for anyone else, really. :(

What should not be here?

Despite being a NixOS configuration, this is not meant to be fully reproducible by anyone. There are still some things that would need to be privately held as indicated by the following list.

  • Associated private keys: GPG, SSH, age, you name it. They are used with a secret management tool (see Secrets management for more information) to encrypt the more sensitive parts of the system such as credentials and environment files.

  • Disposable hosts configurations. They will typically just make a messier mess than the current situation.

Though the unreproducible part is only like 10% of the whole configuration, it can be successfully deployed by anyone. Keep in mind, it comes with a few restrictions due to the lack of the appropriate credentials.

  • Certain tasks will not start. Most of the project tasks found in this repo requires the associated private key with the task. An example would be the Borg backup task where it needs several files and credentials locked from the secrets management tool.

  • Certain components will be missing. Most notably, the associated SSH key for the hosts. You wont be able to connect to the host if you dont have the private key.

  • Not to mention not all modules listed committed here are up-to-date. Though this only applies to non-critical services like the multimedia archiving service.

The remote repo

For a complete overkill, we use a CI to further the configuration abomination. It uses GitHub workflows to enable things such as…

  • Automatically building my custom packages and sending them to my binary cache to easily distribute it for others.

  • Building my personalized NixOS installers and making a release out of it.

  • Testing the flake outputs (in progress lel).

Project structure

Last and foremost, we have the project directory — the environment youll be living in for the next year, tinkering your Nix configs. . It is required to be familiar with the workspace, after all. My configuration takes a lot of cues from devos (which is unfortunately is a lot to take if youre just beginning to grok Nix as a whole).

My NixOS config should look like the following:

nixos-config
├── hosts/
├── lib/
├── modules/
├── pkgs/
├── scripts/
├── secrets/
├── shells/
├── templates/
├── users/
├── default.nix
├── flake.lock
├── flake.nix
├── images.toml
└── README.adoc

One of the more notable files here when first start looking is the ./images.toml file where it contains a description of the images. For more details, see Declarative host management.

Most of the said folders are related to a flake output attribute, see Whats in my flake? for more details.

  • ./hosts/ contain machine-specific configuration. This usually configures like the hardware setup, timezone, and users. Host configurations are also exported in the flakes in outputs.nixosConfigurations.

  • ./modules/ contain my custom modules including NixOS and home-manager modules. For more information, see the related documentation.

  • ./pkgs/ contains my custom packages. It is exported in the flakes at outputs.packages compiled through various systems.

  • ./scripts/ contains various scripts for various purposes. Should be self-explanatory.

  • ./secrets/ contains my cluster-wide secrets managed with sops and sops-nix. Take note, each component (e.g., hosts, modules, users) could have their own specific secrets.

  • ./shells/ contains my development shells for interacting with the usual type of projects. Setting this up can bring benefits outside of NixOS (unless youre interacting with projects with any OpenGL-related stuff). [2]

  • ./templates/ contains my custom templates handy for quickly initializing for various types of projects.

  • ./users/ contains my home-manager configurations. It is exported in the flakes at outputs.homeConfigurations. For more information, see the related documentation.

Declarative host management

This project uses a custom setup for declarative host management. Specifically, it is done with a simple file at ./images.toml where it expects a table of the hosts' metadata. Each host in the table represents one of the hosts at ./hosts/.

A host metadata has a certain schema which the following example is a complete version of it. The data is then used for certain functions in the flake definition file (i.e., flake.nix).

[plover]
system = "x86_64-linux"
format = "iso"
hostname = "ploverrific"
domain = "foodogsquared.one"
nixpkgs-channel = "nixos-unstable-small"

[plover.deploy]
hostname = "plover.foodogsquared.one"
ssh-user = "admin"
fast-connection = true
auto-rollback = true
magic-rollback = true
remote-build = true

For a complete reference, here are the expected attributes.

  • system contains the platform of the host system. This is mainly used to indicate the platform used for the nixpkgs repository.

  • format is the image output format for the host. It expects an accepted value from nixos-generators project.

  • hostname is the canonical hostname for the host. If unset, the hostname is the name of the table key. In the previous example, if plover.hostname is unset, the value would be plover instead of ploverrific.

  • domain is the domain used for networking configuration. It is set for networking.domain in NixOS configuration.

  • nixpkgs-channel is the nixpkgs channel to be used for the host. The value could be any one of the nixpkgs flake inputs imported into this flake. By default, it uses nixpkgs flake input which points to the nixos-unstable channel.

  • deploy is a table containing arguments from deploy-rs. Only a few arguments are accepted (i.e., hostname, fast-connection, remote-build, magic-rollback, and auto-rollback).

Take note, only certain hosts can be considered as a NixOS configuration (e.g., nixosConfigurations). Specifically, those images with a format of iso and those without (since they fall back to iso anyways). Those NixOS configuration are then included as part of the deploy nodes for deploy-rs. Otherwise, most images are intended to be built. [3]

Declarative user management

Similarly to Declarative host management, this project also provides a way to declare home-manager users.

Similar to images.toml, it expects a table of users with each representing one of the users from ./users/home-manager/. These are then included as part of homeConfigurations for easier installation with the standalone home-manager tool. Of which they are then included as part of deploy nodes for deploy-rs (also for easier deployment).

Heres an example user with complete schema.

[foo-dogsquared]
system = "x86_64-linux"
home-manager-channel = "home-manager-23.05"
home-directory = "/home/foo-dogsquared"
username = "foodogsquared"

[foo-dogsquared.deploy]
hostname = "local.foodogsquared.one"
ssh-user = "admin"
profile = "foodogsquared"
fast-connection = true
auto-rollback = true
magic-rollback = true
remote-build = true
  • system contains the platform of the home-manager user. This is mainly used to indicate the platform used for the nixpkgs repository.

  • home-manager-channel contains the home-manager channel to be used. The value should be one of the home-manager channel that is imported into this flake. By default, it sets the home-manager channel at home-manager which is pointed at the unstable channel.

  • home-directory is the associated home directory of the home-manager. It is set for config.home.directory at the home-manager configuration. By default, it will be set at /home/$USERNAME.

  • username is the username of the home-manager user to be used for config.home.username at the home-manager configuration. If unset, it will use the table key. In the above example, the unset value would be foo-dogsquared.

  • deploy is pretty similar to the previous configuration setting that it sets certain options for deploy-rs.

Secrets management

This repo uses sops as the main secret management tool. For integrating this into NixOS, I use sops-nix.

To get started using sops, I recommend to take a look at .sops.yaml file which secrets belong to whom. Then edit a secrets with sops PATH_TO_SECRET. Take note, you need to respective keys to edit the secret in the first place. If you edit ./secrets/backup-archive.yaml for example, it needs one of the keys (either my age and GPG key or the age key from host ni).

TODO

In order of priority:

  • ✓ Create custom modules.

  • ✓ Create a themes system similar to this NixOS config.

  • ✓ Create a good workflow for creating ISOs.

  • ✓ Create development shells.

  • ✓ Manage secrets with agenix.

  • ❏ Create a good workflow for tests.

  • ✓ Automate backups with NixOS config.

  • ✓ Create custom packages and export it to flakes. (Maybe consider making it to upstream)

  • ✓ Create cluser-wide configs.

  • ✓ Create host-wide configs.

  • ✓ Create user-specific configs with home-manager.

  • Steal Get some ideas from this overengineered template.

  • ✓ Make use of other established utilities such as digga, flake-utils-plus, and home-manager once Im familiar to create my own Nix programs.

Out of scope:

  • Set most program configurations with Nix. This is especially applicable to programs I always use such as my text editor configs.

    • The reason: managing them can be chaotic when applied with Nix. The potential for it is pretty nice especially when seen with similar implementations such as Guix home environment. However, I dont want to rebuild it every time I change it.

    • Plus, most of my applications are now installed using Flatpak anyways. It is a tad easier to manage configurations installed this way (e.g., just copy ~/.var between your systems or make backups with it).

  • Migration of my dotfiles. I still use it on other non-NixOS systems.

  • To be a configuration framework. This is my personal configuration which means experimentation will always be here. Sudden changes can happen at any point.

Inspirations and acknowledgment

I stole got several parts of this configuration from the following projects:

This project is licensed under MIT license. I just chose it to make it easier to upstream parts of this project to nixpkgs and to make it easier to copy it without much problems (just dont forget to add attribution as indicated from the license). Please see ./LICENSE for the full text.


1. This is more useful than my NixOS modules.
2. Since packages brought from Nix shells can only work with the store, a container might be better at some situations.
3. Though, one could create a custom activation and deployment script with deploy-rs.