Skip to content

samunemeth/System

Repository files navigation

NixOS logo

My main flake and documentation for it.

Goal

I am trying to achieve a minimal NixOS installation for productivity. I use Qtile as my window manager, Neovim for text and code editing, Firefox for browsing and Lf for file management. I am mainly using these systems for internet browsing, text editing, coding, and LaTeX compilation.

To-Do

Bugs

  • Zathura bottom status bar is not transparent.
  • Look Into: The mini greeter seems to act up on first boot. Maybe just ditch the mini greeter?
  • Sometimes there is a significant slowdown after the machine is powered on for a long time and/or had been suspended for a long/multiple times.
  • In some cases missing optional applications are not handled with care. This is manly an issue on minimal configurations.

Features

  • Impermanence, for some parts at least.
  • Locking, password prompt after suspend.
  • Clean up python parts.
  • Handle missing low priority packages.
  • Finish installation documentation.
  • Proper Tmux setup for Kmscon, with some status bar.
  • Try the Wayland backed for Qtile.

There are also items marked with TODO inside comments. There are also NOTE, WARN and BUG labels used.

Qtile Keybindings

The images below are generated from the Qtile configuration with this script. There is a GitHub action set up that regenerates the images if needed.

Keybindings with Meta Keybindings with Meta and Shift Keybindings with Meta and Control

Language Support

The table below summarizes the support for programming languages. Syntax highlighting is handled by tree-sitter, and is enabled automatically. The language server and formatter is primarily designed and set up to be used with Neovim.

Language Installed Formatter LSP Server
Bash S X
Haskell
Java
Julia X X
LaTeX
Lua
Nix S
Python
Rust

A letter 'S' means that the feature is part of the root system. A tick means the feature is available but needs to be enabled with the configuration option of the language. Rows can only be enabled or disabled at once at the moment. A cross means that the feature is not present at the moment but may be implemented later. If there is no mark it means that the feature is not applicable.

Setup

For the installation it is recommended to use the ISO image generated from this configuration with using the command below. An ISO image will be generated into./result/iso/. The size should be about ~1.5 GiB.

nix build github:samunemeth/System#iso

Alternatively, you can also get the official minimal ISO image. In this case you might need to install some packages during the setup process.

I recommend using Ventoy for booting either of the ISO images. It makes it so you only have to copy the ISO onto a partition on a pen drive without the need to erase the drive and burn the image.

Warning

There are missing steps in this guide at the moment, marked with 'MISSING STEPS'.

  • Boot the installation media, then switch to the root user with:
    sudo -i
    
  • If you only have a wireless connection do one of the following:
    • If you are using the custom ISO image use network manager's TUI:
      nmtui
      
    • If you are using the official ISO image, connect to a Wi-Fi network with the following commands:
      sudo systemctl start wpa_supplicant
      wpa_cli
      
      add_network
      set_network 0 ssid "<SSID>"
      set_network 0 psk "<PASSWORD>"
      enable_network 0
      
      quit
      
  • Do a network sanity check with ping:
    ping google.com
    
  • If you are using the official ISO, get some packages for the installation by generating a dev shell from this flake. A message should confirm that you are in a dev shell.
    nix develop github:samunemeth/System#setup
    
  • Check disk and partition names, mount points, labels, and file system types with the following command any time during the installation:
    lsblk -o +LABEL,FSTYPE,FSVER
    
  • Create the needed partitions:
    cfdisk /dev/<OS-DISK>
    
    If asked, select GPT partition table. I recommend a boot partition between 512 MiB and 1 GiB, a main partition of at least 16 GiB, and a swap partition the same size as the RAM.
  • Create a Luks encrypted Btrfs main partition:
    cryptsetup luksFormat /dev/<NIXOS-PART> --label lb_luks_nixos -v --verify-passphrase
    cryptsetup open /dev/disk/by-label/lb_luks_nixos
    mkfs.btrfs /dev/mapper/enc --label lb_nixos
    
  • Create the needed sub volumes on the Btrfs partition:
    mount -t btrfs /dev/mapper/enc /mnt
    btrfs subvolume create /mnt/root /mnt/home /mnt/nix
    umount /mnt
    
  • Mount the Btrfs sub volumes to the appropriate places, with compression:
    mount -o subvol=root,compress=zstd /dev/mapper/enc /mnt 
    mkdir -p /mnt/{home,nix}
    mount -o subvol=home,compress=zstd /dev/mapper/enc /mnt/home
    mount -o subvol=nix,compress=zstd,noatime /dev/mapper/enc /mnt/nix
    
  • If you just created a boot partition, format it now:
    mkfs.fat -F 32 -n lb_boot /dev/<BOOT-PART>
    
    If you already have a boot partition, make sure it is labelled:
    fatlabel /dev/<BOOT-PART> lb_boot
    
    It should work after this as long as it has enough space. (Windows usually creates a small boot partition, and resizing it is not the easiest or safest thing to do, so I recommend installing Linux before Windows for dual booting setups.)
  • Mount the boot partition:
    mkdir -p /mnt/boot
    mount /dev/disk/by-label/lb_boot /mnt/boot
    
  • If you created a swap partition, format it with Luks encryption:
    cryptsetup luksFormat /dev/<SWAP-PART> --label lb_luks_swap
    cryptsetup luksOpen /dev/disk/by-label/lb_luks_swap swap
    mkswap /dev/mapper/swap -L lb_swap
    
    (If you use the same passphrase for the swap as the main partition, you will only have to enter it once during boot.)
  • MISSING STEPS What do we do with the swap now? Do we just leave it?
  • Check mount points, and file systems now for good measure.
  • Clone this repository into the installer's home directory, and change into it:
    cd ~
    git clone https://github.com/samunemeth/System.git
    cd System
    
    The following commands are all run from the working directory.
  • If you are creating a new host, it is most easily done by coping an existing host's directory and adapting it:
    cp -r ~/System/hosts/<SOURCE-HOST> ~/System/hosts/<HOST>
    
    Otherwise, you can override an existing one if reinstalling.
  • Generate the hardware configuration for the system directly to the new host's directory:
    mv ~/System/hosts/<HOST>/hardware-configuration.nix hardware-configuration.nix.old
    nixos-generate-config --root /mnt --dir ~/System/hosts/<HOST>/
    
  • MISSING STEPS Generating a new hardware configuration might not be necessary if only file system labels are used.
  • MISSING STEPS You need to add all the extra mount options, and file system support.
  • You will have to add these changes in git:
    git add .
    
  • After all the changes are made and committed, you can finally install the system from the flake:
    nixos-install --flake ~/System#<HOST>
    
  • Get some host ssh keys for your machine. This can be done in two different ways:
    • Generate some new host ssh keys for your new machine:
      ssh-keygen -A -f /mnt
      
      In this case, the new keys need to be added to the .sops.yaml file, and the keys need to be updated.
    • MISSING STEPS
    • Copy some existing keys from an external drive.
    • MISSING STEPS
  • Make sure that the keys have the correct permissions:
    chmod 0400 /etc/ssh/ssh_host_*
    
  • As the changes are still not pushed to GitHub, you will need to move the current git repository to the new users home. Give the user ownership of the repository, and change remote URL:
    cp -r ~/System /mnt/home/<USER>/
    
    nixos-enter
    
    cd /home/<USER>
    chown -R <USER>:users System
    
    su <USER>
    cd ~/System
    git remote set-url origin git@github.com:samunemeth/System.git
    
  • Everything should be ready to use, you can boot into the installation.
    reboot
    
  • If the login screen does not work, you can switch to a virtual terminal by pressing ctrl+alt+f2, logging in and disabling the mini greeter with the following in your host's configuration.nix:
    services.xserver.displayManager.lightdm.greeters.mini.enable = lib.mkForce false;
  • If you have a fingerprint reader, enroll a fingerprint to your user:
    sudo fprintd-enroll $USER
    
  • Everything should be set! Rebuild with nrs and reboot to see if everything works as expected.

Sops

To use sops encrypted secrets while rebuilding your machine, or editing the secrets file, you will need an age key that is authorized in the .sops.yaml file. You can either:

  • Use a standalone age key placed in the location ~/.config/sops/age/keys.txt. This is practical when using a master key for a file, during installation or temporarily. Sops and sops-nix both automatically detect them.
  • Use an age key derived from an SSH host key. This way, your machine only requires its host keys to persist. This is probably better for everyday use, as the host keys are owned by root, and therefore harder to 'peek' at. Sops-nix automatically derives the age keys from the host SSH keys, however sops needs them supplied directly. For this purpose, a nes shell function is provided for convenience.

Get an age public key of your machines host ssh key:

# With ssh-to-age installed:
sudo ssh-to-age -i /etc/ssh/ssh_host_ed25519_key.pub
# With ssh-to-age not installed yet:
nix-shell -p ssh-to-age --run 'sudo ssh-to-age -i /etc/ssh/ssh_host_ed25519_key.pub'

This is useful when adding the key to .sops.yaml for example.

To get a private key, add the -private-key flag to the previous ssh-to-age commands. Sops checks the SOPS_AGE_KEY environment variable for additional or derived age keys to use for editing. The following snippet adds a host ssh key derived age key to sops:

export SOPS_AGE_KEY=$(sudo ssh-to-age -private-key -i /etc/ssh/ssh_host_ed25519_key)

This is the same snippet used in the nes shell function.

Note that you may need to prefix the paths in the snippets above with /mnt if you are running them during the installation. To update the secrets.yaml file with new keys or settings, use the updatekeys option with the sops or nes commands. SSH host keys can also be transferred, if the operating system needs to be reinstalled. This way, there is no need to modify .sops.yaml.

Wi-Fi

Some Wi-Fi networks are declared in the Nix configuration and secrets.yaml file. To add a network, create and identifier for it, in this example, let that be `WORK.

If WORK is a regular network:

Then add it to the normal_networks list in the networks.yaml file, then append the following to the wireless-env key in the secrets.yaml file:

    WORK_SSID=<SSID>
    WORK_MGMT=<MGMT-METHOD>
    WORK_PASS=<PASSWORD>

Replace <SSID>, <MGMT-METHOD> and <PASSWORD> accordingly. Where <MGMT-METHOD> is usually either wpa-psk or sae. You can find out the exact value by saving the network imperatively and looking at the generated configuration.

If WORK is an enterprise network:

Then add it to the normal_networks list in the networks.yaml file, then append the following to the wireless-env key in the secrets.yaml file:

    WORK_SSID=<SSID>
    WORK_IDEN=<USERNAME>
    WORK_PASS=<PASSWORD>

Replace <SSID>, <USERNAME> and <PASSWORD> accordingly.

Setting up a WPA enterprise network imperatively does not work with nmtui or networkmanager_dmenu for some reason. Here are some command for setting up such a network:

nmcli connection add type wifi con-name "<SSID>" ssid "<SSID>"
nmcli connection modify "<SSID>" wifi-sec.key-mgmt wpa-eap 802-1x.eap peap 802-1x.phase2-auth mschapv2 802-1x.identity "<IDENTITY>" 802-1x.password "<PASSWORD>"
nmcli connection up "<SSID>"

Replace <SSID>, <IDENTITY> and <PASSWORD> accordingly.

To list all the connections saved, and their configuration file location, use the following command:

sudo nmcli -f NAME,DEVICE,FILENAME connection show

To generate Nix snippets from your saved networks, check out this tool.

Fix for Missing Bootloader

Say that you accidentally deleted your boot partition, or the boot entries for NixOS in your boot partition.

You could also perform other fixes similarly, for example a missing root password. Of course, the disk has to be decrypted for it.

  • Boot a live medium that you would use for installing a new system.
  • Make sure you are running as root:
    sudo -i
  • Do the steps from the setup guide for mounting all the partitions in the correct places.
  • Enter the mounted system:
    nixos-enter
  • Run the command for installing a bootloader for a new system:
    NIXOS_INSTALL_BOOTLOADER=1 /nix/var/nix/profiles/system/bin/switch-to-configuration boot --flake /home/<USER>/System#<HOST>
    The path to the flake is relative to the root of the machine entered, so the /mnt prefix needs to be omitted. Replace the path with the path to your flake.
  • Exit and reboot:
    exit
    reboot

Based on the NixOS wiki's bootloader page.

Nvidia GPU

There are a plethora of versions for Nvidia drivers depending on the GPU type, and they all take up a few GiB of space. When using a laptop that has a dual GPU setup, there are different option for sharing the load, but in the end, using only the integrated graphics might be beneficial for power usage while doing everyday tasks. Power usage improved from 33W to 20W during video playback when disabling the dedicated GPU, without a measurable loss in speed or quality.

If the offloading option was stricter, it would be probably better to use that. (Now the dGPU wakes up sometimes for no apparent reason). In this state, it just increases power usage too much to be worth keeping it on all the time. Using a specialization may be a good idea if the dGPU is sometimes required.

I have tried investigating what is causing the dGPU wakeup, but have found to definite answer. Kmscon definitely runs on the dGPU if available, but without Kmscon wakeup still happen. Investigating this in detail would be a nice side quest for the future.

Removing the Nouveau kernel module seems to increase power usage by about 10W. I assume that without any drivers the dGPU cannot be put into sleep, and therefore consumes more power.

Look at modules/nvidia.template.nix for information on the settings. The template is based on the following sources:

Sticky Derivations

Sometimes stuff gets stuck in /tmp, and prevents packages from being garbage collected. Just clear the /tmp directory and reboot:

sudo rm -rf /tmp/*
sudo reboot

This should be solved later with impermanence.

Secure Boot

Using Lanzaboote, secure boot is possible with this configuration. There are general instructions for installation, that coves almost everything needed for installation. It is important that you cannot have Lanzaboote enabled for the first boot. This means, that you have to enable it later in the setup cycle. This is why it is not included in the above setup instructions.

In addition, some extra information how to get secure boot keys enrolled on machines that I used:

  • On my HP ZBook, secure boot setup mode is enabled while having 'Secure Boot' disabled and after enabling 'Clear Secure Boot keys'. After enrolling, secure boot is enabled automatically.

Miscellaneous

Installing Windows after NixOS can cause the bootloader to become darker, but this usually goes away after a few reboots. No idea what causes it.

On HP laptops the BIOS option 'Verify Boot Block on every boot' causes issues, as NixOS modifies the boot partition a lot.

Resources

Here I have collected some useful resources I have used to create this configuration. For general Linux questions, it is usually a good idea to consult the Arch Wiki.

Options and Packages

For looking for packages or configuration options respectively.

  • Nix Packages for looking up packages.
  • MyNixOS for looking up configuration options.
  • Noogle for looking up pkgs and lib functions.

Nix Language

Wiki's for Nix language basics.

Impermanence

Hibernation

Firefox

Resources for configuring Firefox with Nix.

Other

Guides, threads, wiki's that I have found useful.

Fun

A full IMU

My convertible HP laptop has a full IMU built-in for whatever reason. The following command outputs the monitor orientation in degrees for example.

watch-sensor /sys/bus/iio/devices/iio:device2/in_incli_x_raw 0.00001

Would be fun to create a script that runs a compass or whatever. Note that the compass is not the best, considering the laptop has magnets in it.

NOTE: Some stuff relating to tablet mode on convertibles: libinput # Exposing for other system info. My convertible hp laptop has there messages when folding over and back: -event15 SWITCH_TOGGLE +4.283s switch tablet-mode state 1 event15 SWITCH_TOGGLE +12.837s switch tablet-mode state 0 Maybe add rot8 for automatic rotation? Needs a systemd service, and probably not supported by all laptops.

About

A repository for my NixOS configuration.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors