---
title: NixOS
visible: true
---

[toc]

## Change to Root user

```sh
sudo su
```

## Keyboard Layout

```sh
loadkeys de_CH-latin1
```

## Check UEFI mode

If the following command works, the system is booted in EFI.

```sh
ls /sys/firmware/efi/efivars
```

## Verify internet connection

```sh
ping wiki.exu.li
```

## Creating partitions

```sh
cfdisk
```

Use `EFI System` for EFI partition  
Use `Linux filesystem` for other partitions

## (LUKS) Create encrypted partition

_Note: Do not put your /efi or /boot partition on an encrypted partition!_

Create encrypted Partition  
`cryptsetup luksFormat /dev/(partition)`

To view if this worked correctly  
`cryptsetup luksDump /dev/(partition)`

Open the partition  
Give it a fitting name  
`cryptsetup open /dev/(partition) (name)`

Check if this worked with `ls /dev/mapper/`  
The name should show up there

## Format partitions

_For EFI or BOOT partition_
Fat 32:  
`mkfs.fat -F32 /dev/(partition)`

_All other partitions_
btrfs:  
`mkfs.btrfs /dev/(partition)`

## Mounting partitions

Generally partitions have to be mounted where you will later use them in your system.  
BTRFS with its subvolumes is a special case

```
Root: /mnt
EFI: /mnt/boot
Home: /mnt/home
etc...
```

### Boot partition

```sh
mkdir /mnt/boot
mount /dev/(partition) /mnt/boot
```

### [BTRFS] Btrfs preparation of subvolumes and mounting

Mount root partition

```sh
mount /dev/(partition) /mnt
```

```sh
btrfs subvolume create /mnt/root
btrfs subvolume create /mnt/home
btrfs subvolume create /mnt/nix
btrfs subvolume create /mnt/swap
```

```sh
umount /mnt
```

```sh
mount -o compress=zstd,subvol=root /dev/(partition) /mnt
mkdir /mnt/{boot,home,nix,swap}
mount -o compress=zstd,subvol=home /dev/(partition) /mnt/home
mount -o compress=zstd,noatime,subvol=nix /dev/(partition) /mnt/nix
mount -o noatime,subvol=swap /dev/(partition) /mnt/swap
```

**Don't forget mounting other partitions!!**

## Swap

### Swapfile

#### [BTRFS] Swapfile on btrfs

```sh
truncate -s 0 /mnt/swap/swapfile
chattr +C /mnt/swap/swapfile
btrfs property set /mnt/swap/swapfile compression none
fallocate -l (size)M /mnt/swap/swapfile
```

#### Initialising swapfile

```sh
chmod 600 /mnt/swap/swapfile
mkswap /mnt/swap/swapfile
swapon /mnt/swap/swapfile
```

## Generate initial config

```sh
nixos-generate-config --root /mnt
```

## Modify config file

```nix
{ config, pkgs, ... }:

let
  user = "exu";
  hostname = "nixos";
in
{

  # systemd-boot configuration limit
  boot.loader.systemd-boot.configurationLimit = 5;

  # Define hostname
  networking.hostName = "${hostname}";

  # time zone
  time.timeZone = "Europe/Zurich";

  # default locale
  i18n.defaultLocale = "de_CH.UTF-8";

  # TTY keymap
  console = {
    keyMap = "de_CH-latin1";
  };

  # Enable X11
  services.xserver = {
    enable = true;
    #displayManager.defaultSession = "none+hyprland";
    displayManager.lightdm = {
      enable = true;
      greeters.gtk.enable = true;
    };
    windowManager.openbox = {
      enable = true;
    };
  };

  # TODO figure out how to get this working in the ISO
  # Hyprland
  #programs.hyprland = {
  #  enable = true;
  #};

  # X11 keymap
  services.xserver.layout = "ch";

  # CUPS
  services.printing.enable = true;

  # Pipewire
  security.rtkit.enable = true;
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
    # If you want to use JACK applications, uncomment this
    #jack.enable = true;
  };

  # Enable touchpad support
  services.xserver.libinput.enable = true;

  # Enable fish shell for nix
  programs.fish.enable = true;

  # Create user with initial password
  users.users.${user} = {
    isNormalUser = true;
    extraGroups = [ "wheel" "video" "audio" "networkmanager" "lp" "scanner" ];
    initialPassword = "pass";
    shell = pkgs.fish;
  };

  # System installed packages
  environment.systemPackages = with pkgs; [
    vim
    wget
  ];

  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;

  # Enable SSH server
  services.openssh.enable = true;
```

### [BTRFS] Mount options

Mount options are not automatically detected and have to be readded manually to their respective filesystems. As the hardware-config file is automatically generated, we have to add the relevant options in our main config file.

```nix
  # BTRFS options
  fileSystems = {
    "/".options = [ "compress=zstd" ];
    "/home".options = [ "compress=zstd" ];
    "/nix".options = [ "compress=zstd" "noatime" ];
    "/swap".options = [ "noatime" ];
  };
```

> [NixOS Wiki BTRFS](https://nixos.wiki/wiki/Btrfs#Compression)

### Swapfile configuration

The swapfile is not automatically detected either and has to be specified in the configuration file.

```nix
swapDevices = [ { device = "/swap/swapfile"; } ];
```

## Modify hardware config file

```nix
networking.useDHCP = lib.mkDefault false;
networking.interfaces.(interface).useDHCP = lib.mkDefault true;
```

## Installation

**NOTE:** Hyprland is not yet in any stable release of NixOS and needs to be specified later maybe?

```sh
nixos-install
```

You will be prompted to set a password for the root user.

## Upgrade to unstable

From the installed system, run the following commands to change to the unstable channel.  
Note that using `sudo` is required to change the system channel.

```sh
sudo nix-channel --add https://nixos.org/channels/nixos-unstable nixos
```

And rebuild the system  
_Before rebuilding it is possible to reenable the previously commented config for `Hyprland`_

```nix
  # Hyprland
  programs.hyprland = {
    enable = true;
  };
```

Rebuild with upgrading packages

```sh
sudo nixos-rebuild switch --upgrade
```

Rebuild without upgrading packages

```sh
sudo nixos-rebuild switch
```

## Usefull commands

Install single package as user

```sh
nix-env -iA nixos.(package)
```

Uninstall single user package

```sh
nix-env -e (package)
```

Rebuild and upgrade nix config

```sh
nixos-rebuild switch --upgrade
```

Collect and delete old packages

```sh
nix-collect-garbage --delete-old
nix-collect-garbage
nix-collect-garbage -d
```

List generations

```sh
nix-env --list-generations
```

Delete generations

```sh
nix-env --delete-generations (gen1) (gen2) # generation gen1 and gen2
nix-env --delete-generations 7d # older than 7 days
```

### "Fixing?" errors about derivations

While trying to rebuild NixOS in a test VM I made, I ran across the following errors:

```
unpacking channels...
this derivation will be built:
  /nix/store/xzmcf9zqnk3jlkdk7z80y9f1xwjlh89k-nixos-rebuild.drv
error: getting status of '/nix/store/a9ndjg0b1ivi0av9m93vfkrndp7fqbw1-strip.sh': No such file or directory
building Nix...
error: opening file '/nix/store/6igxs6xrl07pfh7l2lcls4z43b61xpn3-patchelf-0.15.0.drv': No such file or directory
```

Nix seemed to still point to some older paths for some reason.  
After some scouring the web, I finally found a post that helped me.

> [File in nix store empty, unable to be repaired](https://discourse.nixos.org/t/file-in-nix-store-empty-unable-to-be-repaired/14497)

From this post I got the following command

```sh
nix-store --verify --check-contents --repair
```

Running the command only once did not resolve all errors, so I just ran it multiple times until it didn't output any errors anymore.

## Automatisms

Automatic upgrades

```nix
  # Enable automatic package upgrades
  system.autoUpgrade = {
    enable = true;
    channel = "https://nixos.org/channels/nixos-unstable";
  };
```

Automatic garbage collection

```nix
  # Enable automatic garbage collection
  nix = {
    settings.auto-optimise-store = true;
    gc = {
      automatic = true;
      dates = "weekly";
      options = "--delete-older-than 7d";
    };
  };
```

## Home-Manager

Add the Home-Manager channel to NixOS

```sh
sudo nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
sudo nix-channel --update
```

Add `<home-manager/nixos>` in the `imports` list of `configuration.nix`

```nix
  imports =
    [
      ./hardware-configuration.nix
      <home-manager/nixos>
    ];
```

```nix

  home-manager.users.${user} = { pkgs, ... }: {
    home.stateVersion = "22.11" # same as the system.stateVersion
    home.packages = [
      pkgs.firefox
    ];
  };
```