NixOS Home Server Series - Part 1

I have used various setups for my home server, currently I am running with OpenMediaVault . It’s a pretty good solution, but I don’t love the UI and and it can a bit bloated and clunky at times.

Why NixOS?

NixOS is a Linux distribution based on the Nix package manager. It is known for its declarative configuration model, which allows you to define your entire system configuration in a single file.

This is the killer feature for me. If I made a change 2 years ago, it will be self documented in the config file. I can see what I did, and if I need to revert, I can just roll back to a previous version.

The Plan

To start off with I will be setting up a basic NixOS install in a Virtual Machine to see how far I can get, with a simple a setup as possible. And no Nix flakes! At least for now.

Here’s what I want to start off with:

  • booting headless system,
  • Fileserver (Samba)
  • SSH server
  • 2x NVME boot drives in RAID 1
  • 2x SATA SSD drives in RAID 1 (Storage)
  • 2x SATA HDD drives in RAID 1 (Backup)

Thats it.

Enough fluff, let’s get started.

  1. Download the minimal NixOS ISO from the NixOS download page, create a new VM in VMware Fusion, attach the ISO and setup virtual drives as above.

  2. Start the VM, and boot into the console to create partitions and filesystems.

    Open terminal and switch to root user:

    sudo -i
    

    Setup the partitons.

    # OS Disks (RAID1)
    for disk in /dev/nvme0n1 /dev/nvme0n2; do
      parted $disk mklabel gpt
      parted $disk mkpart ESP fat32 1MiB 512MiB
      parted $disk set 1 esp on
      parted $disk mkpart primary btrfs 512MiB 100%
    done
    
    # Storage (RAID1)
    for disk in /dev/sda /dev/sdb; do
      parted $disk mklabel gpt
      parted $disk mkpart primary btrfs 1MiB 100%
    done
    
    # Backup (RAID1)
    for disk in /dev/sdd /dev/sde; do
      parted $disk mklabel gpt
      parted $disk mkpart primary btrfs 1MiB 100%
    done
    

    Format Filesystems

    # EFI System Partition (ESP)
    mkfs.fat -F32 -n BOOT /dev/nvme0n1p1
    
    # OS Disk (RAID1)
    mkfs.btrfs -m raid1 -d raid1 /dev/nvme0n1p2 /dev/nvme0n2p2 -L NIXOS-ROOT
    
    # Create Btrfs subvolumes
    mount /dev/disk/by-label/NIXOS-ROOT /mnt
    btrfs subvolume create /mnt/@root
    btrfs subvolume create /mnt/@nix
    btrfs subvolume create /mnt/@home
    umount /mnt
    
    # Storage Pool (RAID1)
    mkfs.btrfs -m raid1 -d raid1 /dev/sda1 /dev/sdb1 -L STORAGE-POOL
    
    # Backup Pool (RAID1)
    mkfs.btrfs -m raid1 -d raid1 /dev/sdd1 /dev/sde1 -L BACKUP-POOL
    
  3. Mount Filesystems

    # Mount OS subvolumes
    mount -o subvol=@root,compress=zstd,noatime /dev/disk/by-label/NIXOS-ROOT /mnt
    mkdir -p /mnt/{boot,nix,home,storage,backup}
    mount -o subvol=@nix,compress=zstd,noatime /dev/disk/by-label/NIXOS-ROOT /mnt/nix
    mount -o subvol=@home,compress=zstd,noatime /dev/disk/by-label/NIXOS-ROOT /mnt/home
    
    # Mount boot partition
    mount /dev/disk/by-label/BOOT /mnt/boot
    
    # Mount storage and backup pools
    mount -o compress=zstd,noatime /dev/disk/by-label/STORAGE-POOL /mnt/storage
    mount -o compress=zstd,noatime /dev/disk/by-label/BACKUP-POOL /mnt/backup
    
  4. Configure NixOS

    nixos-generate-config --root /mnt
    
  5. Edit Configuration

    vim /mnt/etc/nixos/configuration.nix
    
    { config, pkgs, ... }:
    {
      imports = [ ./hardware-configuration.nix ];
    
      # Boot loader configuration
      boot.loader = {
        efi = {
          canTouchEfiVariables = true;
          efiSysMountPoint = "/boot";
        };
        systemd-boot.enable = true;
      };
    
      # Explicitly configure boot partition
      fileSystems."/boot" = lib.mkForce {
        device = "/dev/disk/by-label/BOOT";
        fsType = "vfat";
      };
    
      # Filesystem RAID configuration for storage and backup pools
      fileSystems."/storage" = lib.mkForce {
        device = "/dev/disk/by-label/STORAGE-POOL";
        fsType = "btrfs";
        options = [ "compress=zstd" "noatime" ];
      };
    
      fileSystems."/backup" = lib.mkForce {
        device = "/dev/disk/by-label/BACKUP-POOL";
        fsType = "btrfs";
        options = [ "compress=zstd" "noatime" ];
      };
    
      # Networking and SSH
      networking.hostName = "nixos";
    
      services.openssh = {
        enable = true;
        settings = {
          PasswordAuthentication = true; # Temporary for initial setup.
          PermitRootLogin = "yes";       # Temporary for initial setup.
        };
        ports = [22];
      };
    
      networking.firewall.allowedTCPPorts = [22];
    
      # Time zone setup.
      time.timeZone = "Europe/London";
    
      # User configuration.
      users.users.root.initialPassword = "temp";
    
      users.users.admin = {
        isNormalUser = true;
        extraGroups = [ "wheel" ];
        initialPassword = "temp";
      };
    
      environment.systemPackages = with pkgs; [
        vim           # Vim text editor.
     ];
    
    }
    
  6. Install NixOS

    nixos-install /mnt
    
  7. Reboot

    ssh admin@<ip>
    
  8. Post-Installation

    # Change root password.
    passwd
    passwd admin
    
    # Harden SSH
    vim /etc/nixos/configuration.nix
    
      services.openssh = {
        enable = true;
        settings = {
          PasswordAuthentication = false; # Disable password authentication.
          PermitRootLogin = "no";         # Disable root login.
        };
      };
    
    # Rebuild NixOS configuration.
    nixos-rebuild switch
    
    # Verify Setup
    
    # Check mounted filesystems
    findmnt | grep storage && findmnt | grep backup && findmnt | grep boot 
    
    # Check RAID status
    btrfs filesystem show 
    btrfs device stats /storage
    btrfs device stats /backup
    btrfs device stats /boot
    btrfs device stats /mnt
    

And that’s a wrap for round 1. 😎

APR 20, 2025

Page 1 of 5

Next page