Minimal Btrfs-Subvol Install with Disko and Flakes
Disko allows you to declaratively partition and format your disks, and then mount them to your system. I recommend checking out the README as it is a disk destroyer if used incorrectly.
We will mainly be following the disko quickstart guide
If you have a ton of RAM you could most likely skip the minimal install and just set your system up as needed or just use tmpfs as root
-
Get the Nixos Minimal ISO Get it on a usb stick, I use Ventoy with Ventoy2Disk.sh. The following is the link to the Ventoy TarBall download, untar it with
tar -xzf ventoy-1.1.05-linux.tar.gz
, and make it executable withchmod +x Ventoy2Disk.sh
, and finally execute it withsudo bash Ventoy2Disk.sh
Follow the prompts to finish the install. -
The minimal installer uses
wpa_supplicant
instead of NetworkManager, to enable networking run the following:
sudo systemctl start wpa_supplicant
wpa_cli
> add_network
0
> set_network 0 ssid "myhomenetwork"
OK
> set_network 0 psk "mypassword"
OK
> enable_network 0
OK
To exit type quit
, then check your connection with ping google.com
.
Another option is to do the following, so either the above method or the below
method after starting wpa_supplicant
:
# Alternative for quick setup (less interactive, but often faster)
sudo wpa_passphrase "myhomenetwork" "mypassword" >> /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
sudo systemctl restart wpa_supplicant@wlan0.service
- Get your Disk Name with
lsblk
The output should be something like:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme0n1 259:0 0 1,8T 0 disk
- Copy the disk configuration to your machine. You can choose one from the examples directory. I chose the btrfs-subvolumes layout so I ran the following:
cd /tmp
curl https://raw.githubusercontent.com/nix-community/disko/refs/heads/master/example/btrfs-subvolumes.nix -o /tmp/disk-config.nix
- Make Necessary changes, I set mine up for impermanence with the following:
nano /tmp/disk-config.nix
{
disko.devices = {
disk = {
main = {
type = "disk";
device = "/dev/nvme0n1";
content = {
type = "gpt";
partitions = {
ESP = {
priority = 1;
name = "ESP";
start = "1M";
end = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = ["umask=0077"];
};
};
root = {
size = "100%";
content = {
type = "btrfs";
extraArgs = ["-f"]; # Override existing partition
# Subvolumes must set a mountpoint in order to be mounted,
# unless their parent is mounted
subvolumes = {
# Subvolume name is different from mountpoint
"/root" = {
mountpoint = "/";
mountOptions = ["subvol=root" "compress=zstd" "noatime"];
};
# Subvolume name is the same as the mountpoint
"/home" = {
mountOptions = ["subvol=home" "compress=zstd" "noatime"];
mountpoint = "/home";
};
# Sub(sub)volume doesn't need a mountpoint as its parent is mounted
"/home/user" = {};
# Parent is not mounted so the mountpoint must be set
"/nix" = {
mountOptions = [
"subvol=nix"
"compress=zstd"
"noatime"
];
mountpoint = "/nix";
};
"/persist" = {
mountpoint = "/persist";
mountOptions = ["subvol=nix" "compress=zstd" "noatime"];
};
"/log" = {
mountpoint = "/var/log";
mountOptions = ["subvol=log" "compress=zstd" "noatime"];
};
"/lib" = {
mountpoint = "/var/lib";
mountOptions = ["subvol=lib" "compress=zstd" "noatime"];
};
# This subvolume will be created but not mounted
"/test" = {};
};
};
};
};
};
};
};
};
fileSystems."/persist".neededForBoot = true;
fileSystems."/var/log".neededForBoot = true;
fileSystems."/var/lib".neededForBoot = true;
}
- You may choose to add a swapfile to the above
disk-config.nix
, I haven't included it here because I manage it with the impermanence module. If you were to add it here you could just add under say the"/lib"
section add:
# Persistent subvolume for swapfile
"/persist/swap" = {
mountpoint = "/persist/swap";
mountOptions = ["subvol=persist/swap" "noatime"]; # No compression for swap
};
fileSystems."/persist/swap".neededForBoot = true;
- Run disko to partition, format and mount your disks. Warning this will wipe EVERYTHING on your disk. Disko doesn't work with dual boot.
sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko/latest -- --mode destroy,format,mount /tmp/disk-config.nix
Check it with the following:
mount | grep /mnt
The output for an nvme0n1
disk would be similar to the following:
/dev/nvme0n1p1 on /mnt type ext4 (rw,relatime,stripe=2)
/dev/nvme0n1p2 on /mnt/boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)
# ... snip ...
- Generate necessary files, here we use
--no-filesystems
because disko handles thefileSystems
attribute for us.
nixos-generate-config --no-filesystems --root /mnt
sudo mv /tmp/disk-config.nix /mnt/etc/nixos
- Create the flake in your home directory, then move it to
/mnt/etc/nixos
mkdir flake && cd flake
nix-shell -p git yazi helix
export NIX_CONFIG='experimental-features = nix-command flakes'
export EDITOR='hx'
hx flake.nix
# flake.nix
{
description = "NixOS configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
inputs.disko.url = "github:nix-community/disko/latest";
inputs.disko.inputs.nixpkgs.follows = "nixpkgs";
# impermanence.url = "github:nix-community/impermanence";
};
outputs = inputs@{ nixpkgs, ... }: {
nixosConfigurations = {
hostname = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./configuration.nix
inputs.disko.nixosModules.disko
# inputs.impermanence.nixosModules.impermanence
];
};
};
};
}
Move all the files into your flake:
cd /mnt/etc/nixos/
sudo mv disk-config.nix hardware-configuration.nix configuration.nix ~/flake
- Edit
configuration.nix
with what is required, the following is required, I clone my original flake repo and move the pieces into place but it's fairly easy to just type it all out:
-
Bootloader
-
User
-
Networking
-
hardware-configuration.nix
&disk-config.nix
for this setup -
initialHashedPassword
: Runmkpasswd -m SHA-512 -s
, then enter your desired password. Example output,
Password: your_secret_password
Retype password: your_secret_password
$6$random_salt$your_hashed_password_string_here_this_is_very_long_and_complex
copy the hashed password and use it for the value of your initialHashedPassword
# configuration.nix
{
config,
lib,
pkgs,
inputs,
...
}: {
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
./disk-config.nix
];
networking.hostName = "magic"; # Define your hostname.
networking.networkmanager.enable = true;
boot.loader.systemd-boot.enable = true; # (for UEFI systems only)
# List packages installed in system profile.
# You can use https://search.nixos.org/ to find more packages (and options).
environment.systemPackages = with pkgs; [
vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
# wget
git
];
time.timeZone = "America/New_York";
users.users.nixos = {
isNormalUser = true;
extraGroups = [ "wheel" "networkmanager" ]; # Add "wheel" for sudo access
initialHashedPassword = "COPY_YOUR_MKPASSWD_OUTPUT_HERE"; # <-- This is where it goes!
# home = "/home/nixos"; # Optional: Disko typically handles home subvolumes
};
console.keyMap = "us";
nixpkgs.config.allowUnfree = true;
system.stateVersion = "25.05"; # Did you read the comment?
}
- Move the flake to
/mnt/etc/nixos
and runnixos-install
:
sudo mv ~/flake /mnt/etc/nixos/
sudo nixos-install --flake /mnt/etc/nixos/flake .#hostname
-
You will be prompted to enter a new password if everything succeeds.
-
If everything checks out, reboot the system and you should be prompted to enter your user and password to login to a shell to get started.
-
The flake will be placed at
/etc/nixos/flake
, I choose to move it to my home directory. Since the file was first in/etc
you'll need to adjust the permissions with something likesudo chmod username:users ~/flake
and then you can work on it without privilege esculation. -
To continue following allong and set up impermanence Click Here