NixOs native flake deployment with LUKS drive encryption and LVM

Ion Mudreac
13 min readJul 22, 2021

In this series of tutorials, I will not cover nix or NixOs. You can probably find many tutorials with detailed descriptions of the advantages of using nix declarative, functional configuration management language.

I will tackle a specific problem I was trying to solve, and as a result, I can share and expand on potential options available.

Some time back, I was looking to reinstall my nixos “that I was running for the past four years” with a new nix feature like a flake and make it more flexible from a storage management standpoint “using LVM” and to secure with full disk encryption “using LUKS.”

Flake

Flakes are a new feature in the Nix ecosystem. Flakes replace stateful channels and introduce a more intuitive and consistent CLI interface.

LVM

A Linux, Logical Volume Manager (LVM) is a device mapper framework that provides logical volume management for the Linux kernel. The main advantage is using LVM multiple Disk management becomes very easy, and adding new disk storage is a breeze. A good description for LVM you can find in Chris Titus Blog Post

LUKS

LUKS stands for ”Linux Unified Key Setup.” I will use cryptsetup to use to encrypt the entire disk using LUKS2. For more information on specification for LUKS2

Before you start a good recommendation, use hypervisor VirtualBox or QEMU/KVM to get familiarised with the setup and available options. In the below example, I am using QEMU/KVM.

Installation

Prerequisites

Download latest nixos iso image Download min Minimal ISO image.

Make sure you have a git repository with all configuration files. In the below example, I will use my Github systst repository.

Setup virtualization with QEMU/KVM

1st step is to create a Virtual Machine that will install NixOS using nix flakes.
Download min Minimal ISO image.

~> virt-install \
--name nixos \
--boot uefi \
--ram 8196 \
--vcpus 4 \
--network bridge:virbr0 \
--os-type linux \
--os-variant nixos-unstable \
--disk path=/var/lib/libvirt/images/nixos.qcow2,size=30 \
--console pty,target_type=serial \
--cdrom ~/Downloads/iso/nixos-minimal-21.05.1555.6b940846e99-x86_64-linux.iso

Note: Adjust --cdrom and -disk path locations. Feel free to adjust --ram and --vcpus accommodate underlying hardware.

Hard Drive preparation

Once VM is up and running, we will need to identify the drive nixos will be installed by running;

[nixos@nixos:~]$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 614.2M 1 loop /nix/.ro-store
sr0 11:0 1 661M 0 rom /iso
vda 253:0 0 30G 0 disk

Note: we will use vda disk that was provisioned with 30 G of free storage.
Note: Good proactive to have a minimum of 20 G of storage due to the nature of NixOs to create derivation for recovery.

Drive partitioning

Once we know on what drive we will use, install nixos is time to create the necessary partitions. Will become root for easier access to the resources requiring root access.

[nixos@nixos:~]$ sudo -i[root@nixos:~]# export ROOT_DISK=/dev/vda[root@nixos:~]# parted -a opt --script "${ROOT_DISK}" \
mklabel gpt \
mkpart primary fat32 0% 512MiB \
mkpart primary 512MiB 100% \
set 1 esp on \
name 1 boot \
set 2 lvm on \
name 2 root
[root@nixos:~]# fdisk /dev/vda -l
Disk /dev/vda: 30 GiB, 32212254720 bytes, 62914560 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 4E4E582E-8CC3-4901-93B4-3D8DD429FA7E
Device Start End Sectors Size Type
/dev/vda1 2048 1048575 1046528 511M EFI System
/dev/vda2 1048576 62912511 61863936 29.5G Linux LVM

Note: I am installing the nixos on UEFI partition type fat32 with 512 Mib of the allocated storage. The rest of the storage is allocated for the root partition.
Note: except partitioning the disk I labeled the partition /dev/vda1 as boot and /dev/vda1 as root that will help us later in the system setup.

Partition encryption

The next step is to encrypt root partition. I will use cryptsetup with luksFormat.

[root@nixos:~]# cryptsetup luksFormat /dev/disk/by-partlabel/root
WARNING!
========
This will overwrite data on /dev/disk/by-partlabel/root irrevocably.
Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/disk/by-partlabel/root:
Verify passphrase:

Note: Make sure you use a secure password

Open encrypted partition

[root@nixos:~]# cryptsetup luksOpen /dev/disk/by-partlabel/root rootEnter passphrase for /dev/disk/by-partlabel/root:

Setting up LVM

System readout of volumes and partitions

[root@nixos:~]# lvmdiskscan
/dev/loop0 [ <614.18 MiB]
/dev/gpt-auto-root [ 29.48 GiB]
/dev/vda1 [ 511.00 MiB]
/dev/vda2 [ <29.50 GiB]
1 disk
3 partitions
0 LVM physical volume whole disks
0 LVM physical volumes

Create a physical volume from /dev/mapper/root that is mapped to /dev/vda2

[root@nixos:~]# pvcreate /dev/mapper/root
Physical volume "/dev/mapper/root" successfully created.

Create a volume group from /dev/mapper/root

[root@nixos:~]# vgcreate vg /dev/mapper/root
Volume group "vg" successfully created

Create a 4 GB logical volume on volume group vg that will be used for swap partition

[root@nixos:~]# lvcreate -L 4G -n swap vg
Logical volume "swap" created.

Create a logical volume on volume group vg using all the rest of the storage space that will be used for root partition.

[root@nixos:~]# lvcreate -l '100%FREE' -n root vg
Logical volume "root" created.

View volumes and partitions created

[root@nixos:~]# lvdisplay
--- Logical volume ---
LV Path /dev/vg/swap
LV Name swap
VG Name vg
LV UUID BEZroA-bKry-jAz2-dW2v-jQDY-uqUB-bIdJQa
LV Write Access read/write
LV Creation host, time nixos, 2021-07-20 14:44:52 +0000
LV Status available
# open 0
LV Size 4.00 GiB
Current LE 1024
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 254:1

--- Logical volume ---
LV Path /dev/vg/root
LV Name root
VG Name vg
LV UUID KJHdcu-CLvf-saWV-Kp3r-qSTw-HcMg-7SePkt
LV Write Access read/write
LV Creation host, time nixos, 2021-07-20 14:46:11 +0000
LV Status available
# open 0
LV Size 25.48 GiB
Current LE 6523
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 254:2

Partition formatting

Formatting the boot partition with FAT32

[root@nixos:~]# mkfs.fat -F 32 -n boot /dev/disk/by-partlabel/boot
mkfs.fat 4.1 (2017-01-24)
mkfs.fat: warning - lowercase labels might not work properly with DOS or Windows

Formatting the root partition with EXT4 file system

[root@nixos:~]# mkfs.ext4 -L root /dev/vg/root
mke2fs 1.46.2 (28-Feb-2021)
Creating filesystem with 6679552 4k blocks and 1671168 inodes
Filesystem UUID: e78f4a6b-5d85-458a-9757-f722d657c091
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

Formatting the swap partition

[root@nixos:~]# mkswap -L swap /dev/vg/swap
Setting up swapspace version 1, size = 4 GiB (4294963200 bytes)
LABEL=swap, UUID=3feeb8e9-9843-401b-93dc-128047b8c08b

Mounting newly created partitions and swap activation

[root@nixos:~]# mount /dev/disk/by-label/root /mnt[root@nixos:~]# mkdir -p /mnt/boot[root@nixos:~]# mount /dev/disk/by-label/boot /mnt/boot[root@nixos:~]# swapon /dev/vg/swap[root@nixos:~]# swapon -s
Filename Type Size Used Priority
/dev/dm-1 partition 4194300 0 -2

NixOS Installation

Installation options

We have a few available options to use nix flake.

Base example

Bellow, you can find the most basic example where you can use flake and ingest configuration.nix as a module.

{
description = "NixOS configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-21.05";
};
outputs = { nixpkgs, ... }: {
nixosConfigurations = {
nixtst = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./configuration.nix
];
};
};
};
}

Home Manager integration

If you are a single user for underlying hardware and want to have a single management workspace, you can integrate the system config with the home manager config under the same nix flake.

{
description = "NixOS configuration and Home Manager configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-21.05";
home-manager.url = "github:nix-community/home-manager";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { home-manager, nixpkgs, ... }: {
nixosConfigurations = {
nixtst = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./configuration.nix
home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.users.mudrii = import ./users/$USER/home.nix;
}
];
};
};
};
}

Full flake integration

Another option is to get rid of configuration.nix and add all entries into flake.nix.

{
description = "NixOS configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-21.05";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs = { nixpkgs, nixpkgs-unstable, ... }: {
nixosConfigurations = {
nixtst = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
({ config, pkgs, ... }:
let
overlay-unstable = final: prev: {
unstable = nixpkgs-unstable.legacyPackages.x86_64-linux;
};
in
{
imports =
[ ./hardware-configuration.nix ];
fileSystems."/" = { options = [ "noatime" "nodiratime" ]; }; boot = {
kernelPackages = pkgs.linuxPackages_latest;
loader = {
efi.canTouchEfiVariables = true;
grub = {
enable = true;
version = 2;
efiSupport = true;
enableCryptodisk = true;
device = "nodev";
};
};
initrd.luks.devices = {
crypt = {
device = "/dev/vda2";
preLVM = true;
};
};
};
time.timeZone = "Asia/Singapore"; networking = {
useDHCP = false;
interfaces.enp1s0.useDHCP = true;
hostName = "nixtst"; # Define your hostname.
};
security = {
sudo = {
enable = true;
wheelNeedsPassword = false;
};
};
...
..
.

Note: full example can be found at the Link

Mix and Match

In the below example, I am using a combination of available options.
The reason is to have a structure to allow for multi-user support. Some users may not have root access but should manage the user packages using a separate implementation of the Home Manager that will cover in a separate tutorial.

{
description = "NixOS configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-21.05";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs = { nixpkgs, nixpkgs-unstable, ... }: {
nixosConfigurations = {
nixtst = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
({ config, pkgs, ... }:
let
overlay-unstable = final: prev: {
unstable = nixpkgs-unstable.legacyPackages.x86_64-linux;
};
in
{
nixpkgs.overlays = [ overlay-unstable ];
imports =
[
./hardware-configuration.nix
./configuration.nix
./packages.nix
./users/admin_users.nix
./users/dev_users.nix
];
}
)
];
};
};
};
}

Note: I added nixpkgs.overlays to allow some packages to be installed selected from the unstable branch.

*.nix dissected

hardware-configuration.nix

The only change in hardware-configuration.nix is the device from by-uuid to by-label that adds portability and add swap device to the mix.

{ config, lib, pkgs, modulesPath, ... }:{
imports =
[
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "sr_mod" "virtio_blk" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-label/root";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-label/boot";
fsType = "vfat";
};
swapDevices =
[{ device = "/dev/disk/by-label/swap"; }];
nix.maxJobs = lib.mkDefault 4;}

configuration.nix

fileSystems

fileSystems SSD optimization for EXT4

fileSystems."/" = { options = [ "noatime" "nodiratime" ]; };

boot.loader

Adding latest Linux kernel with kernelPackages = pkgs.linuxPackages_latest;
Allowing groub support for UEFi and Luks encryption

boot = {
kernelPackages = pkgs.linuxPackages_latest;
loader = {
efi.canTouchEfiVariables = true;
grub = {
enable = true;
version = 2;
efiSupport = true;
enableCryptodisk = true;
device = "nodev";
};
};
initrd.luks.devices = {
crypt = {
device = "/dev/vda2";
preLVM = true;
};
};
};

networking

Please change to your desired hostname and correct the interface name.

networking = {
useDHCP = false;
interfaces.enp1s0.useDHCP = true; # Add correct network interface name to find out run "ip a"
hostName = "nixtst"; # Define your hostname.
};

console and fonts

I am adding default system-wide encoding and adding additional fonts, useful for the modern shell.

i18n = {
defaultLocale = "en_US.UTF-8";
supportedLocales = [ "en_US.UTF-8/UTF-8" ];
};
console = {
font = "Lat2-Terminus16";
keyMap = "us";
};
fonts = {
fontDir.enable = true;
enableGhostscriptFonts = true;
fonts = with pkgs; [
powerline-fonts
nerdfonts
];
};

services

We are enabling ssh on port 2022 but disabling root login and password authentication.

services = {
openssh = {
enable = true;
permitRootLogin = "no";
passwordAuthentication = false;
ports = [2022];
};
};

virtualisation

Adding docker as an example

virtualisation = {
docker = {
enable = true;
autoPrune.enable = true;
enableOnBoot = true;
};
};

nix optimisations

Allowing unfree allowUnfree = true; packages like Nvidia drivers etc.
Make nix compatible with flakes pkgs.nixFlakes;
Garbage collection and optimization gc and optimise

nixpkgs = {
config = {
allowBroken = true;
allowUnfree = true;
};
};
nix = {
package = pkgs.nixFlakes;
useSandbox = true;
autoOptimiseStore = true;
readOnlyStore = false;
allowedUsers = [ "@wheel" ];
trustedUsers = [ "@wheel" ];
extraOptions = ''
experimental-features = nix-command flakes
keep-outputs = true
keep-derivations = true
'';
gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 7d --max-freed $((64 * 1024**3))";
};
optimise = {
automatic = true;
dates = [ "weekly" ];
};
};

system

Configure system auto-update compatible with flakes you will need to change Github repo to point to your repo location.

system = {
stateVersion = "21.05"; # Did you read the comment?
autoUpgrade = {
enable = true;
allowReboot = true;
flake = "github:mudrii/systst";
flags = [
"--recreate-lock-file"
"--no-write-lock-file"
"-L" # print build logs
];
dates = "daily";
};
};

Note: Complete content of the configuration.nix file can be found in Github

packages.nix

System wide packages

With environment.systemPackages we specify packages that will be installed for all users.

systemPackages = with pkgs; [
git
gh
kubernetes
kubernetes-helm
kubeseal
helmfile
helmsman
unstable.kind
kube3d
argo
argocd
kustomize
k9s
kubectx
binutils
gnutls
wget
curl
bind
mkpasswd
direnv
nix-direnv
];

shellAliases

We can specify system-wide shell aliases for all users.

shellAliases = {
cp = "cp -i";
diff = "diff --color=auto";
dmesg = "dmesg --color=always | lless";
egrep = "egrep --color=auto";
fgrep = "fgrep --color=auto";
grep = "grep --color=auto";
mv = "mv -i";
ping = "ping -c3";
ps = "ps -ef";
sudo = "sudo -i";
vdir = "vdir --color=auto";
};

programs

We specify native nix application to be installed and/or enable/disable. We can add package-specific configurations for all users like nano editor.

programs = {
ssh.startAgent = false;
vim.defaultEditor = true;
fish.enable = true;
nano.nanorc = ''
unset backup
set nonewlines
set nowrap
set tabstospaces
set tabsize 4
set constantshow
'';
};

users

To manage multiple users, I decided to segregate admin users having root access with non-admin users. The only difference is in the wheel group allocation.
You can specify packages that will install only for the user and add ssh public keys and generate the password.

users = {
mutableUsers = false;
users.mudrii = {
isNormalUser = true;
extraGroups = [ "wheel" "docker" ];
shell = pkgs.fish;
# mkpasswd -m sha-512 password
hashedPassword = "$6$ewXNcoQRNG$czTic9vE8CGH.eo4mabZsHVRdmTjtJF4SdDnIK0O/4STgzB5T2nD3Co.dRpVS3/uDD24YUxWrTDy2KRv7m/3N1";
openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8/tE2+oIwLnCnfzPSTqiZaeW++wUPNW5fOi124eGzWfcnOQGrjuwir3sZDKMS9DLqSTDNtvJ3/EZf6z/MLN/uxUE8lA+aKaSs0yopE7csQ89Aqkvp5fvCpz3BJuZgpxtwebPZyTc7QRGQWE4lM3fix3aJhfj827bdxA+sCiq8OnNiwYSXrIag1cQigafhLy6tYtCKdWcxzJq2ebGJF2wu2LU0zArb1SAOanhEOXxz0dG1I/7yMDBDC92R287nWpL+BwxuQcDv0xh/sWnViKixKv+B9ewJnz98iQPcg3WmYWe9BYAcaqkbgMqbwfUPqOHhFXmiQWUpOjsni2O6VoiN mudrii@nixos" ];
packages = with pkgs; [
python39Full
(
python39.withPackages (
ps: with ps; [
#poetry
pip
powerline
pygments
pygments-markdown-lexer
xstatic-pygments
pylint
numpy
pynvim
]
)
)
];
};
};

Prerequisites

Before starting the installation, we need to use git nf Flakes that we cat use nix-shell that allows us to use binaries that are not installed in the system.

[root@nixos:~]# nix-shell -p git nixFlakes
these paths will be fetched (12.56 MiB download, 75.48 MiB unpacked):
/nix/store/0f92b8kgaki9s5rwdj81pni3wj7ca8k6-git-2.31.1-doc
/nix/store/39j27lcvm8sn17k4589v7kxwic58qgsg-libcpuid-0.5.1
/nix/store/3bk9dhdkzg11qm9g1zkv7vxqkvcaqnp6-lowdown-0.8.4-lib
/nix/store/3ghvl0b0bd0pmrkczciy1i9gzlmi47mp-perl5.32.1-CGI-Fast-2.15
/nix/store/47qr4rksqfi8kgc3kwjvrjy9ym1bj89g-gettext-0.21
/nix/store/54dmlydl9lwvrmjjcgf5xrsydhnvasd0-nix-2.4pre20210601_5985b8b
/nix/store/8sxrh4g1zan8lriwfqzw6iimqcaj4asi-perl5.32.1-CGI-4.51
/nix/store/a95f72avd2r70w1rszb6mvyiabydr2nc-perl5.32.1-FCGI-0.79
/nix/store/b9bisjs01ijfw60g8qjk59v843bkldbx-nlohmann_json-3.9.1
/nix/store/c3vb6fvq802hckzz8xrgc6ja39k51af4-git-2.31.1
/nix/store/ln6mp01fyp2dlxfihrnj64js699yzvvn-boehm-gc-8.0.4-dev
/nix/store/p1m2imc7xbp5lf9298v2yndb3gqcr4la-libarchive-3.5.1-lib
/nix/store/p4qkqk2rxcyxfhyv6gzj7inc388azgli-perl5.32.1-HTML-TagCloud-0.38
/nix/store/ppwys502zs735azzksgs5wdya4rar626-nix-2.4pre20210601_5985b8b-dev
/nix/store/qima3mpp9bb5gnarr5z1dw7zvlaj0r8d-nix-2.4pre20210601_5985b8b-man
/nix/store/wzach25vwapl3sa6f7gylqank3jhhsin-bash-interactive-4.4-p23-dev
/nix/store/x24qskawy3d4mj2vqpl0hr5pdhpa8d6i-perl5.32.1-FCGI-ProcManager-0.28
/nix/store/zqf5dhf2pr6sxfgdpbq7gs1ajzknv2hm-perl5.32.1-TermReadKey-2.38
copying path '/nix/store/0f92b8kgaki9s5rwdj81pni3wj7ca8k6-git-2.31.1-doc' from 'https://cache.nixos.org'...
copying path '/nix/store/x24qskawy3d4mj2vqpl0hr5pdhpa8d6i-perl5.32.1-FCGI-ProcManager-0.28' from 'https://cache.nixos.org'...
copying path '/nix/store/p4qkqk2rxcyxfhyv6gzj7inc388azgli-perl5.32.1-HTML-TagCloud-0.38' from 'https://cache.nixos.org'...
copying path '/nix/store/wzach25vwapl3sa6f7gylqank3jhhsin-bash-interactive-4.4-p23-dev' from 'https://cache.nixos.org'...
copying path '/nix/store/ln6mp01fyp2dlxfihrnj64js699yzvvn-boehm-gc-8.0.4-dev' from 'https://cache.nixos.org'...
copying path '/nix/store/47qr4rksqfi8kgc3kwjvrjy9ym1bj89g-gettext-0.21' from 'https://cache.nixos.org'...
copying path '/nix/store/p1m2imc7xbp5lf9298v2yndb3gqcr4la-libarchive-3.5.1-lib' from 'https://cache.nixos.org'...
copying path '/nix/store/39j27lcvm8sn17k4589v7kxwic58qgsg-libcpuid-0.5.1' from 'https://cache.nixos.org'...
copying path '/nix/store/3bk9dhdkzg11qm9g1zkv7vxqkvcaqnp6-lowdown-0.8.4-lib' from 'https://cache.nixos.org'...
copying path '/nix/store/qima3mpp9bb5gnarr5z1dw7zvlaj0r8d-nix-2.4pre20210601_5985b8b-man' from 'https://cache.nixos.org'...
copying path '/nix/store/b9bisjs01ijfw60g8qjk59v843bkldbx-nlohmann_json-3.9.1' from 'https://cache.nixos.org'...
copying path '/nix/store/8sxrh4g1zan8lriwfqzw6iimqcaj4asi-perl5.32.1-CGI-4.51' from 'https://cache.nixos.org'...
copying path '/nix/store/a95f72avd2r70w1rszb6mvyiabydr2nc-perl5.32.1-FCGI-0.79' from 'https://cache.nixos.org'...
copying path '/nix/store/zqf5dhf2pr6sxfgdpbq7gs1ajzknv2hm-perl5.32.1-TermReadKey-2.38' from 'https://cache.nixos.org'...
copying path '/nix/store/3ghvl0b0bd0pmrkczciy1i9gzlmi47mp-perl5.32.1-CGI-Fast-2.15' from 'https://cache.nixos.org'...
copying path '/nix/store/c3vb6fvq802hckzz8xrgc6ja39k51af4-git-2.31.1' from 'https://cache.nixos.org'...
copying path '/nix/store/54dmlydl9lwvrmjjcgf5xrsydhnvasd0-nix-2.4pre20210601_5985b8b' from 'https://cache.nixos.org'...
copying path '/nix/store/ppwys502zs735azzksgs5wdya4rar626-nix-2.4pre20210601_5985b8b-dev' from 'https://cache.nixos.org'...

Repo clone

Now we can clone the repository where we have out configuration files needed for the nixos flake installation.

[nix-shell:~]# git clone https://github.com/mudrii/systst.git /mnt/etc/nixos
Cloning into '/mnt/etc/nixos'...
remote: Enumerating objects: 229, done.
remote: Counting objects: 100% (229/229), done.
remote: Compressing objects: 100% (160/160), done.
remote: Total 229 (delta 127), reused 149 (delta 57), pack-reused 0
Receiving objects: 100% (229/229), 67.03 KiB | 4.47 MiB/s, done.
Resolving deltas: 100% (127/127), done.

NixOs flake installation

nixos-install script supports native nixos flake installation.

[nix-shell:~]# nixos-install --root /mnt --flake /mnt/etc/nixos#nixtst
building the flake in git+file:///mnt/etc/nixos?ref=master&rev=72a8edfd9d6bea0a314d561cdc15c4d72d8b9fb6...
copying channel...
installing the boot loader...
setting up /etc...
/etc/tmpfiles.d/journal-nocow.conf:26: Failed to resolve specifier: uninitialized /etc detected, skipping
All rules containing unresolvable specifiers will be skipped.
updating GRUB 2 menu...
installing the GRUB 2 EFI boot loader into /boot...
Installing for x86_64-efi platform.
/nix/store/gsf4bnf0pg5k8pyzbprx5l26gnq9w93n-grub-2.06-rc1/sbin/grub-install: warning: cannot open directory `/nix/store/gsf4bnf0pg5k8pyzbprx5l26gnq9w93n-grub-2.06-rc1/share/locale': No such file or directory.
Installation finished. No error reported.
setting up /etc...
/etc/tmpfiles.d/journal-nocow.conf:26: Failed to resolve specifier: uninitialized /etc detected, skipping
All rules containing unresolvable specifiers will be skipped.
setting up /etc...
/etc/tmpfiles.d/journal-nocow.conf:26: Failed to resolve specifier: uninitialized /etc detected, skipping
All rules containing unresolvable specifiers will be skipped.
setting root password...
New password:
Retype new password:
passwd: password updated successfully
installation finished!

Post-installation

Once installation is completed, we can reboot the OS and login as a user we declared in our configuration files.

[nix-shell:~]# reboot

System update and management

Once we have our system up and running is a good practice te keep the system up to date.

System update requires a two-step process

  1. Flake update to lock the flake on latest GitHub commit
  2. nix rebuild switch to update the system

Following the below steps will keep you system up to date

mudrii@nixtst ~> sudo nix flake update /etc/nixos/
warning: updating lock file '/etc/nixos/flake.lock':
* Updated 'nixpkgs': 'github:nixos/nixpkgs/4181644d09b96af0f92c2f025d3463f9d19c7790' -> 'github:nixos/nixpkgs/63ee5cd99a2e193d5e4c879feb9683ddec23fa03'
* Updated 'nixpkgs-unstable': 'github:NixOS/nixpkgs/967d40bec14be87262b21ab901dbace23b7365db' -> 'github:NixOS/nixpkgs/16105403bdd843540cbef9c63fc0f16c1c6eaa70'
warning: Git tree '/etc/nixos' is dirty
mudrii@nixtst ~> sudo nixos-rebuild switch --flake /etc/nixos/#nixtst
warning: Git tree '/etc/nixos' is dirty
building the system configuration...
warning: Git tree '/etc/nixos' is dirty
updating GRUB 2 menu...
NOT restarting the following changed units: systemd-fsck@dev-disk-by\x2dlabel-boot.service
activating the configuration...
setting up /etc...
reloading user units for mudrii...
setting up tmpfiles
reloading the following units: dbus.service

In the follow-up tutorial, we will cover home manager installation and configuration using native flake implementation.

--

--