NixOS Root on ZFS: use Nix-config for multi-disk
NixOS has enjoyed popularity among ZFS users thanks to its declarative configuration and native ZFS support. However, the installation guide used hardcoded disk names in configuration files, which is unnecessary and is the source of difficulties in multidisk setups. The guide is now rewritten to leverage expressions in the Nix language to manage multidisk setups. Also adds instruction on replacing failed disk. Closes #385. Signed-off-by: Maurice Zhou <ja@apvc.uk>
This commit is contained in:
committed by
George Melikov
parent
d8713058b3
commit
cc6d72c02d
@@ -8,7 +8,7 @@ Preparation
|
|||||||
|
|
||||||
#. Disable Secure Boot. ZFS modules can not be loaded if Secure Boot is enabled.
|
#. Disable Secure Boot. ZFS modules can not be loaded if Secure Boot is enabled.
|
||||||
#. Download `NixOS Live Image
|
#. Download `NixOS Live Image
|
||||||
<https://channels.nixos.org/nixos-22.05/latest-nixos-gnome-x86_64-linux.iso>`__ and boot from it.
|
<https://nixos.org/download.html#download-nixos>`__ and boot from it.
|
||||||
#. Connect to the Internet.
|
#. Connect to the Internet.
|
||||||
#. Set root password or ``/root/.ssh/authorized_keys``.
|
#. Set root password or ``/root/.ssh/authorized_keys``.
|
||||||
#. Start SSH server::
|
#. Start SSH server::
|
||||||
@@ -17,15 +17,15 @@ Preparation
|
|||||||
|
|
||||||
#. Connect from another computer::
|
#. Connect from another computer::
|
||||||
|
|
||||||
ssh root@192.168.1.19
|
ssh root@192.168.1.91
|
||||||
|
|
||||||
#. Target disk
|
#. Target disk
|
||||||
|
|
||||||
List available disks with::
|
List available disks with::
|
||||||
|
|
||||||
ls /dev/disk/by-id/*
|
find /dev/disk/by-id/
|
||||||
|
|
||||||
If using virtio as disk bus, use ``/dev/disk/by-path/*``.
|
If using virtio as disk bus, use ``/dev/disk/by-path/``.
|
||||||
|
|
||||||
Declare disk array::
|
Declare disk array::
|
||||||
|
|
||||||
@@ -37,11 +37,10 @@ Preparation
|
|||||||
|
|
||||||
#. Set partition size:
|
#. Set partition size:
|
||||||
|
|
||||||
Set swap size. It's `recommended <https://chrisdown.name/2018/01/02/in-defence-of-swap.html>`__
|
Set swap size, set to 1 if you don't want swap to
|
||||||
to setup a swap partition. If you intend to use hibernation,
|
take up too much space::
|
||||||
the minimum should be no less than RAM size. Skip if swap is not needed::
|
|
||||||
|
|
||||||
INST_PARTSIZE_SWAP=8
|
INST_PARTSIZE_SWAP=4
|
||||||
|
|
||||||
Root pool size, use all remaining disk space if not set::
|
Root pool size, use all remaining disk space if not set::
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ System Installation
|
|||||||
|
|
||||||
sgdisk -n2:0:+4G -t2:BE00 $i
|
sgdisk -n2:0:+4G -t2:BE00 $i
|
||||||
|
|
||||||
test -z $INST_PARTSIZE_SWAP || sgdisk -n4:0:+${INST_PARTSIZE_SWAP}G -t4:8200 $i
|
sgdisk -n4:0:+${INST_PARTSIZE_SWAP}G -t4:8200 $i
|
||||||
|
|
||||||
if test -z $INST_PARTSIZE_RPOOL; then
|
if test -z $INST_PARTSIZE_RPOOL; then
|
||||||
sgdisk -n3:0:0 -t3:BF00 $i
|
sgdisk -n3:0:0 -t3:BF00 $i
|
||||||
@@ -25,6 +25,12 @@ System Installation
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
sgdisk -a1 -n5:24K:+1000K -t5:EF02 $i
|
sgdisk -a1 -n5:24K:+1000K -t5:EF02 $i
|
||||||
|
|
||||||
|
sync && udevadm settle && sleep 3
|
||||||
|
|
||||||
|
cryptsetup open --type plain --key-file /dev/random $i-part4 ${i##*/}-part4
|
||||||
|
mkswap /dev/mapper/${i##*/}-part4
|
||||||
|
swapon /dev/mapper/${i##*/}-part4
|
||||||
done
|
done
|
||||||
|
|
||||||
#. Create boot pool::
|
#. Create boot pool::
|
||||||
@@ -84,9 +90,7 @@ System Installation
|
|||||||
|
|
||||||
If not using a multi-disk setup, remove ``mirror``.
|
If not using a multi-disk setup, remove ``mirror``.
|
||||||
|
|
||||||
#. This section implements dataset layout as described in `overview <1-preparation.html>`__.
|
#. Create root system container:
|
||||||
|
|
||||||
Create root system container:
|
|
||||||
|
|
||||||
- Unencrypted::
|
- Unencrypted::
|
||||||
|
|
||||||
@@ -108,18 +112,25 @@ System Installation
|
|||||||
-o keyformat=passphrase \
|
-o keyformat=passphrase \
|
||||||
rpool/nixos
|
rpool/nixos
|
||||||
|
|
||||||
Create system datasets::
|
You can automate this step (insecure) with: ``echo POOLPASS | zfs create ...``.
|
||||||
|
|
||||||
zfs create -o canmount=on -o mountpoint=/ rpool/nixos/root
|
Create system datasets, let NixOS declaratively
|
||||||
zfs create -o canmount=on -o mountpoint=/home rpool/nixos/home
|
manage mountpoints with ``mountpoint=legacy``::
|
||||||
zfs create -o canmount=off -o mountpoint=/var rpool/nixos/var
|
|
||||||
zfs create -o canmount=on rpool/nixos/var/lib
|
|
||||||
zfs create -o canmount=on rpool/nixos/var/log
|
|
||||||
|
|
||||||
Create boot dataset::
|
zfs create -o mountpoint=legacy rpool/nixos/root
|
||||||
|
mount -t zfs rpool/nixos/root /mnt/
|
||||||
zfs create -o canmount=off -o mountpoint=none bpool/nixos
|
zfs create -o mountpoint=legacy rpool/nixos/home
|
||||||
zfs create -o canmount=on -o mountpoint=/boot bpool/nixos/root
|
mkdir /mnt/home
|
||||||
|
mount -t zfs rpool/nixos/home /mnt/home
|
||||||
|
zfs create -o mountpoint=legacy rpool/nixos/var
|
||||||
|
zfs create -o mountpoint=legacy rpool/nixos/var/lib
|
||||||
|
zfs create -o mountpoint=legacy rpool/nixos/var/log
|
||||||
|
zfs create -o mountpoint=none bpool/nixos
|
||||||
|
zfs create -o mountpoint=legacy bpool/nixos/root
|
||||||
|
mkdir /mnt/boot
|
||||||
|
mount -t zfs bpool/nixos/root /mnt/boot
|
||||||
|
zfs create -o mountpoint=legacy rpool/nixos/empty
|
||||||
|
zfs snapshot rpool/nixos/empty@start
|
||||||
|
|
||||||
#. Format and mount ESP::
|
#. Format and mount ESP::
|
||||||
|
|
||||||
|
|||||||
@@ -6,83 +6,48 @@ System Configuration
|
|||||||
.. contents:: Table of Contents
|
.. contents:: Table of Contents
|
||||||
:local:
|
:local:
|
||||||
|
|
||||||
#. Generate initial system configuration::
|
#. Download system configuration from this repo::
|
||||||
|
|
||||||
nixos-generate-config --root /mnt
|
mkdir -p /mnt/etc/nixos/
|
||||||
|
curl -o /mnt/etc/nixos/configuration.nix -L \
|
||||||
|
https://github.com/openzfs/openzfs-docs/raw/master/docs/Getting%20Started/NixOS/Root%20on%20ZFS/configuration.nix
|
||||||
|
|
||||||
#. Import ZFS-specific configuration::
|
#. Customize configuration to your hardware::
|
||||||
|
|
||||||
sed -i "s|./hardware-configuration.nix|./hardware-configuration.nix ./zfs.nix|g" /mnt/etc/nixos/configuration.nix
|
for i in $DISK; do
|
||||||
|
sed -i \
|
||||||
|
"s|PLACEHOLDER_FOR_DEV_NODE_PATH|\"${i%/*}/\"|" \
|
||||||
|
/mnt/etc/nixos/configuration.nix
|
||||||
|
break
|
||||||
|
done
|
||||||
|
|
||||||
#. Configure hostid::
|
diskNames=""
|
||||||
|
for i in $DISK; do
|
||||||
tee -a /mnt/etc/nixos/zfs.nix <<EOF
|
diskNames="$diskNames \"${i##*/}\""
|
||||||
{ config, pkgs, ... }:
|
done
|
||||||
|
tee -a /mnt/etc/nixos/machine.nix <<EOF
|
||||||
{ boot.supportedFilesystems = [ "zfs" ];
|
{
|
||||||
networking.hostId = "$(head -c 8 /etc/machine-id)";
|
bootDevices = [ $diskNames ];
|
||||||
boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages;
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
#. Configure bootloader for both legacy boot and UEFI boot and mirror bootloader::
|
|
||||||
|
|
||||||
sed -i '/boot.loader/d' /mnt/etc/nixos/configuration.nix
|
|
||||||
sed -i '/services.xserver/d' /mnt/etc/nixos/configuration.nix
|
|
||||||
tee -a /mnt/etc/nixos/zfs.nix <<EOF
|
|
||||||
boot.loader.efi.efiSysMountPoint = "/boot/efis/$(echo $DISK | cut -f1 -d\ | sed 's|/dev/disk/by-id/||')-part1";
|
|
||||||
EOF
|
|
||||||
tee -a /mnt/etc/nixos/zfs.nix <<-'EOF'
|
|
||||||
boot.loader.efi.canTouchEfiVariables = false;
|
|
||||||
boot.loader.generationsDir.copyKernels = true;
|
|
||||||
boot.loader.grub.efiInstallAsRemovable = true;
|
|
||||||
boot.loader.grub.enable = true;
|
|
||||||
boot.loader.grub.version = 2;
|
|
||||||
boot.loader.grub.copyKernels = true;
|
|
||||||
boot.loader.grub.efiSupport = true;
|
|
||||||
boot.loader.grub.zfsSupport = true;
|
|
||||||
boot.loader.grub.extraInstallCommands = ''
|
|
||||||
ESP_MIRROR=$(mktemp -d)
|
|
||||||
cp -r ${config.boot.loader.efi.efiSysMountPoint}/EFI $ESP_MIRROR
|
|
||||||
for i in /boot/efis/*; do
|
|
||||||
cp -r $ESP_MIRROR/EFI $i
|
|
||||||
done
|
|
||||||
rm -rf $ESP_MIRROR
|
|
||||||
'';
|
|
||||||
boot.loader.grub.devices = [
|
|
||||||
EOF
|
|
||||||
|
|
||||||
for i in $DISK; do
|
|
||||||
printf " \"$i\"\n" >>/mnt/etc/nixos/zfs.nix
|
|
||||||
done
|
|
||||||
|
|
||||||
tee -a /mnt/etc/nixos/zfs.nix <<EOF
|
|
||||||
];
|
|
||||||
EOF
|
|
||||||
|
|
||||||
#. Mount datasets with zfsutil option::
|
|
||||||
|
|
||||||
sed -i 's|fsType = "zfs";|fsType = "zfs"; options = [ "zfsutil" "X-mount.mkdir" ];|g' \
|
|
||||||
/mnt/etc/nixos/hardware-configuration.nix
|
|
||||||
|
|
||||||
#. Mount EFI partitions on demand::
|
|
||||||
|
|
||||||
sed -i 's|fsType = "vfat";|fsType = "vfat"; options = [ "x-systemd.idle-timeout=1min" "x-systemd.automount" "noauto" "nofail" ];|g' \
|
|
||||||
/mnt/etc/nixos/hardware-configuration.nix
|
|
||||||
|
|
||||||
#. Set root password::
|
#. Set root password::
|
||||||
|
|
||||||
rootPwd=$(mkpasswd -m SHA-512 -s)
|
rootPwd=$(mkpasswd -m SHA-512 -s)
|
||||||
|
|
||||||
Declare password in configuration::
|
Declare password in configuration::
|
||||||
|
|
||||||
tee -a /mnt/etc/nixos/zfs.nix <<EOF
|
sed -i \
|
||||||
users.users.root.initialHashedPassword = "${rootPwd}";
|
"s|PLACEHOLDER_FOR_ROOT_PWD_HASH|\""${rootPwd}"\"|" \
|
||||||
}
|
/mnt/etc/nixos/configuration.nix
|
||||||
EOF
|
|
||||||
|
#. Optional: enable NetworkManager for easier wireless configuration and enable desktop
|
||||||
|
environments. See ``man configuration.nix`` for details. By default, the system is
|
||||||
|
installed without any other software.
|
||||||
|
|
||||||
#. Install system and apply configuration::
|
#. Install system and apply configuration::
|
||||||
|
|
||||||
nixos-install -v --show-trace --no-root-passwd --root /mnt
|
nixos-install --no-root-passwd --root /mnt
|
||||||
|
|
||||||
#. Unmount filesystems::
|
#. Unmount filesystems::
|
||||||
|
|
||||||
@@ -92,3 +57,116 @@ System Configuration
|
|||||||
#. Reboot::
|
#. Reboot::
|
||||||
|
|
||||||
reboot
|
reboot
|
||||||
|
|
||||||
|
#. Optional: manage system configuration with git.
|
||||||
|
|
||||||
|
#. Optional: immutable root filesystem can be enabled by
|
||||||
|
using this `configuration file
|
||||||
|
<https://github.com/openzfs/openzfs-docs/raw/master/docs/Getting%20Started/NixOS/Root%20on%20ZFS/configuration-immutable.nix>`__.
|
||||||
|
Apply your own hardware configuration in this file,
|
||||||
|
then execute::
|
||||||
|
|
||||||
|
nixos-rebuild boot
|
||||||
|
|
||||||
|
Then reboot. You may need to make certain
|
||||||
|
adjustments to where configuration files are stored,
|
||||||
|
see `NixOS wiki <https://nixos.wiki/wiki/ZFS>`__ for
|
||||||
|
details.
|
||||||
|
|
||||||
|
Replace a failed disk
|
||||||
|
=====================
|
||||||
|
|
||||||
|
When a disk fails in a mirrored setup, the disk can be
|
||||||
|
replaced with the following procedure.
|
||||||
|
|
||||||
|
#. Shutdown the computer.
|
||||||
|
|
||||||
|
#. Replace the failed disk with another disk. The
|
||||||
|
replacement should be at least the same size or
|
||||||
|
larger than the failed disk.
|
||||||
|
|
||||||
|
#. Boot the computer. When a disk fails, the system will boot, albeit
|
||||||
|
several minutes slower than normal. This is due to
|
||||||
|
the initrd and systemd designed to only import a pool
|
||||||
|
in degraded state after a 90s timeout. Swap
|
||||||
|
partition on that disk will also fail.
|
||||||
|
|
||||||
|
#. Launch a ephemeral nix shell with gptfdisk::
|
||||||
|
|
||||||
|
nix-shell -p gptfdisk
|
||||||
|
|
||||||
|
#. Identify the bad disk and a working old disk::
|
||||||
|
|
||||||
|
ZPOOL_VDEV_NAME_PATH=1 zpool status
|
||||||
|
|
||||||
|
pool: bpool
|
||||||
|
status: DEGRADED
|
||||||
|
action: Replace the device using 'zpool replace'.
|
||||||
|
...
|
||||||
|
config: bpool
|
||||||
|
mirror-0
|
||||||
|
2387489723748 UNAVAIL 0 0 0 was /dev/disk/by-id/ata-BAD-part2
|
||||||
|
/dev/disk/by-id/ata-OLD-part2 ONLINE 0 0 0
|
||||||
|
|
||||||
|
#. Store the bad disk and a working old disk in a variable, omit the partition number ``-partN``::
|
||||||
|
|
||||||
|
BAD=/dev/disk/by-id/ata-BAD
|
||||||
|
OLD=/dev/disk/by-id/ata-OLD
|
||||||
|
|
||||||
|
#. Identify the new disk::
|
||||||
|
|
||||||
|
find /dev/disk/by-id/
|
||||||
|
|
||||||
|
/dev/disk/by-id/ata-OLD-part1
|
||||||
|
/dev/disk/by-id/ata-OLD-part2
|
||||||
|
...
|
||||||
|
/dev/disk/by-id/ata-OLD-part5
|
||||||
|
/dev/disk/by-id/ata-NEW <-- new disk w/o partition table
|
||||||
|
|
||||||
|
#. Store the new disk in a variable::
|
||||||
|
|
||||||
|
NEW=/dev/disk/by-id/ata-NEW
|
||||||
|
|
||||||
|
#. Replicate partition table on the new disk::
|
||||||
|
|
||||||
|
sgdisk -Z $NEW
|
||||||
|
sgdisk --backup=backup $OLD
|
||||||
|
sgdisk --load-backup=backup $NEW
|
||||||
|
sgdisk --randomize-guids $NEW
|
||||||
|
|
||||||
|
#. If the new disk is larger than the old disk, expand root pool partition size::
|
||||||
|
|
||||||
|
sgdisk --delete=3 $NEW
|
||||||
|
|
||||||
|
# expand to all remaining disk space
|
||||||
|
sgdisk -n3:0:0 -t3:BF00 $NEW
|
||||||
|
|
||||||
|
Note that this space will only become available once all disks in the mirrored pool are
|
||||||
|
replaced with larger disks.
|
||||||
|
|
||||||
|
#. Format and mount EFI system partition::
|
||||||
|
|
||||||
|
mkfs.vfat -n EFI ${NEW}-part1
|
||||||
|
mkdir -p /boot/efis/${NEW##*/}-part1
|
||||||
|
mount -t vfat ${NEW}-part1 /boot/efis/${NEW##*/}-part1
|
||||||
|
|
||||||
|
#. Replace failed disk in pool::
|
||||||
|
|
||||||
|
zpool offline bpool ${BAD}-part2
|
||||||
|
zpool offline rpool ${BAD}-part3
|
||||||
|
zpool replace bpool ${BAD}-part2 ${NEW}-part2
|
||||||
|
zpool replace rpool ${BAD}-part3 ${NEW}-part3
|
||||||
|
zpool online bpool ${NEW}-part2
|
||||||
|
zpool online rpool ${NEW}-part3
|
||||||
|
|
||||||
|
Let the new disk resilver. Check status with ``zpool status``.
|
||||||
|
|
||||||
|
#. Update NixOS system configuration::
|
||||||
|
|
||||||
|
sed -i "s|${BAD##*/}|${NEW##*/}|" /etc/nixos/machine.nix
|
||||||
|
|
||||||
|
#. Apply the updated NixOS system configuration, reinstall bootloader, then reboot::
|
||||||
|
|
||||||
|
nixos-rebuild boot --install-bootloader
|
||||||
|
|
||||||
|
reboot
|
||||||
|
|||||||
@@ -0,0 +1,252 @@
|
|||||||
|
# Edit this configuration file to define what should be installed on
|
||||||
|
# your system. Help is available in the configuration.nix(5) man page
|
||||||
|
# and in the NixOS manual (accessible by running ‘nixos-help’).
|
||||||
|
{ config, lib, pkgs, modulesPath, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
zfsRoot.partitionScheme = {
|
||||||
|
biosBoot = "-part5";
|
||||||
|
efiBoot = "-part1";
|
||||||
|
swap = "-part4";
|
||||||
|
bootPool = "-part2";
|
||||||
|
rootPool = "-part3";
|
||||||
|
};
|
||||||
|
zfsRoot.devNodes = PLACEHOLDER_FOR_DEV_NODE_PATH; # MUST have trailing slash! /dev/disk/by-id/
|
||||||
|
zfsRoot.bootDevices = (import ./machine.nix).bootDevices;
|
||||||
|
zfsRoot.mirroredEfi = "/boot/efis/";
|
||||||
|
|
||||||
|
in {
|
||||||
|
# adjust according to your platform, such as
|
||||||
|
imports = [
|
||||||
|
# (modulesPath + "/profiles/qemu-guest.nix")
|
||||||
|
# (modulesPath + "/profiles/all-hardware.nix")
|
||||||
|
(modulesPath + "/installer/scan/not-detected.nix")
|
||||||
|
];
|
||||||
|
systemd.services.zfs-mount.enable = false;
|
||||||
|
|
||||||
|
# networking.hostName = "nixos"; # Define your hostname.
|
||||||
|
# Pick only one of the below networking options.
|
||||||
|
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
|
||||||
|
# networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
|
||||||
|
|
||||||
|
# Set your time zone.
|
||||||
|
# time.timeZone = "Europe/Amsterdam";
|
||||||
|
|
||||||
|
# Configure network proxy if necessary
|
||||||
|
# networking.proxy.default = "http://user:password@proxy:port/";
|
||||||
|
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
|
||||||
|
|
||||||
|
# Select internationalisation properties.
|
||||||
|
# i18n.defaultLocale = "en_US.UTF-8";
|
||||||
|
# console = {
|
||||||
|
# font = "Lat2-Terminus16";
|
||||||
|
# keyMap = "us";
|
||||||
|
# useXkbConfig = true; # use xkbOptions in tty.
|
||||||
|
# };
|
||||||
|
|
||||||
|
# Enable the X11 windowing system.
|
||||||
|
|
||||||
|
# Configure keymap in X11
|
||||||
|
# "eurosign:e";
|
||||||
|
# "caps:escape" # map caps to escape.
|
||||||
|
# };
|
||||||
|
|
||||||
|
# Enable CUPS to print documents.
|
||||||
|
# services.printing.enable = true;
|
||||||
|
|
||||||
|
# Enable sound.
|
||||||
|
# sound.enable = true;
|
||||||
|
# hardware.pulseaudio.enable = true;
|
||||||
|
|
||||||
|
# Enable touchpad support (enabled default in most desktopManager).
|
||||||
|
|
||||||
|
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||||
|
# users.users.alice = {
|
||||||
|
# isNormalUser = true;
|
||||||
|
# extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
||||||
|
# packages = with pkgs; [
|
||||||
|
# firefox
|
||||||
|
# thunderbird
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
# List packages installed in system profile. To search, run:
|
||||||
|
# $ nix search wget
|
||||||
|
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
|
||||||
|
mg
|
||||||
|
];
|
||||||
|
|
||||||
|
# Some programs need SUID wrappers, can be configured further or are
|
||||||
|
# started in user sessions.
|
||||||
|
# programs.mtr.enable = true;
|
||||||
|
# programs.gnupg.agent = {
|
||||||
|
# enable = true;
|
||||||
|
# enableSSHSupport = true;
|
||||||
|
# };
|
||||||
|
|
||||||
|
# List services that you want to enable:
|
||||||
|
|
||||||
|
# Enable the OpenSSH daemon.
|
||||||
|
services.openssh.enable = false;
|
||||||
|
users.users.root = {
|
||||||
|
##hash: mkpasswd -m SHA-512 -s
|
||||||
|
initialHashedPassword = PLACEHOLDER_FOR_ROOT_PWD_HASH;
|
||||||
|
openssh.authorizedKeys.keys = [
|
||||||
|
];
|
||||||
|
};
|
||||||
|
programs.git.enable = true;
|
||||||
|
# Open ports in the firewall.
|
||||||
|
# networking.firewall.allowedTCPPorts = [ ... ];
|
||||||
|
# networking.firewall.allowedUDPPorts = [ ... ];
|
||||||
|
# Or disable the firewall altogether.
|
||||||
|
# networking.firewall.enable = false;
|
||||||
|
|
||||||
|
# Copy the NixOS configuration file and link it from the resulting system
|
||||||
|
# (/run/current-system/configuration.nix). This is useful in case you
|
||||||
|
# accidentally delete configuration.nix.
|
||||||
|
system.copySystemConfiguration = true;
|
||||||
|
|
||||||
|
# This value determines the NixOS release from which the default
|
||||||
|
# settings for stateful data, like file locations and database versions
|
||||||
|
# on your system were taken. It‘s perfectly fine and recommended to leave
|
||||||
|
# this value at the release version of the first install of this system.
|
||||||
|
# Before changing this value read the documentation for this option
|
||||||
|
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
||||||
|
system.stateVersion = "22.11"; # Did you read the comment?
|
||||||
|
|
||||||
|
boot.initrd.availableKernelModules = [
|
||||||
|
"ahci"
|
||||||
|
"xhci_pci"
|
||||||
|
"virtio_pci"
|
||||||
|
"virtio_blk"
|
||||||
|
"ehci_pci"
|
||||||
|
"nvme"
|
||||||
|
"uas"
|
||||||
|
"sd_mod"
|
||||||
|
"sr_mod"
|
||||||
|
"sdhci_pci"
|
||||||
|
];
|
||||||
|
boot.initrd.kernelModules = [ ];
|
||||||
|
boot.kernelModules = [ "kvm-intel" "kvm-amd" ];
|
||||||
|
boot.extraModulePackages = [ ];
|
||||||
|
|
||||||
|
fileSystems = {
|
||||||
|
"/" = {
|
||||||
|
device = "rpool/nixos/empty";
|
||||||
|
fsType = "zfs";
|
||||||
|
options = [ "X-mount.mkdir" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
"/oldroot" = {
|
||||||
|
device = "rpool/nixos/root";
|
||||||
|
fsType = "zfs";
|
||||||
|
options = [ "X-mount.mkdir" ];
|
||||||
|
neededForBoot = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
"/nix" = {
|
||||||
|
device = "/oldroot/nix";
|
||||||
|
fsType = "none";
|
||||||
|
options = [ "bind" "X-mount.mkdir" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
"/etc/nixos" = {
|
||||||
|
device = "/oldroot/etc/nixos";
|
||||||
|
fsType = "none";
|
||||||
|
options = [ "bind" "X-mount.mkdir" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
"/home" = {
|
||||||
|
device = "rpool/nixos/home";
|
||||||
|
fsType = "zfs";
|
||||||
|
options = [ "X-mount.mkdir" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
"/var/lib" = {
|
||||||
|
device = "rpool/nixos/var/lib";
|
||||||
|
fsType = "zfs";
|
||||||
|
options = [ "X-mount.mkdir" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
"/var/log" = {
|
||||||
|
device = "rpool/nixos/var/log";
|
||||||
|
fsType = "zfs";
|
||||||
|
options = [ "X-mount.mkdir" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
"/boot" = {
|
||||||
|
device = "bpool/nixos/root";
|
||||||
|
fsType = "zfs";
|
||||||
|
options = [ "X-mount.mkdir" ];
|
||||||
|
};
|
||||||
|
} // (builtins.listToAttrs (map (diskName: {
|
||||||
|
name = zfsRoot.mirroredEfi + diskName + zfsRoot.partitionScheme.efiBoot;
|
||||||
|
value = {
|
||||||
|
device = zfsRoot.devNodes + diskName + zfsRoot.partitionScheme.efiBoot;
|
||||||
|
fsType = "vfat";
|
||||||
|
options = [
|
||||||
|
"x-systemd.idle-timeout=1min"
|
||||||
|
"x-systemd.automount"
|
||||||
|
"noauto"
|
||||||
|
"nofail"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}) zfsRoot.bootDevices));
|
||||||
|
|
||||||
|
swapDevices = (map (diskName: {
|
||||||
|
device = zfsRoot.devNodes + diskName + zfsRoot.partitionScheme.swap;
|
||||||
|
discardPolicy = "both";
|
||||||
|
randomEncryption = {
|
||||||
|
enable = true;
|
||||||
|
allowDiscards = true;
|
||||||
|
};
|
||||||
|
}) zfsRoot.bootDevices);
|
||||||
|
|
||||||
|
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||||
|
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||||
|
# still possible to use this option, but it's recommended to use it in conjunction
|
||||||
|
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
|
||||||
|
networking.useDHCP = lib.mkDefault true;
|
||||||
|
# networking.networkmanager.enable = true;
|
||||||
|
# networking.interfaces.enp1s0.useDHCP = lib.mkDefault true;
|
||||||
|
|
||||||
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
|
hardware.cpu.intel.updateMicrocode =
|
||||||
|
lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
hardware.cpu.amd.updateMicrocode =
|
||||||
|
lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
|
||||||
|
|
||||||
|
boot.supportedFilesystems = [ "zfs" ];
|
||||||
|
networking.hostId = "abcd1234";
|
||||||
|
boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages;
|
||||||
|
boot.loader.efi.efiSysMountPoint = with builtins;
|
||||||
|
(zfsRoot.mirroredEfi + (head zfsRoot.bootDevices) + zfsRoot.partitionScheme.efiBoot);
|
||||||
|
boot.zfs.devNodes = zfsRoot.devNodes;
|
||||||
|
boot.loader.efi.canTouchEfiVariables = false;
|
||||||
|
boot.loader.generationsDir.copyKernels = true;
|
||||||
|
boot.loader.grub.efiInstallAsRemovable = true;
|
||||||
|
boot.loader.grub.enable = true;
|
||||||
|
boot.loader.grub.version = 2;
|
||||||
|
boot.loader.grub.copyKernels = true;
|
||||||
|
boot.loader.grub.efiSupport = true;
|
||||||
|
boot.loader.grub.zfsSupport = true;
|
||||||
|
boot.loader.grub.extraInstallCommands = with builtins;
|
||||||
|
(toString (map (diskName:
|
||||||
|
"cp -r " + config.boot.loader.efi.efiSysMountPoint + "/EFI" + " "
|
||||||
|
+ zfsRoot.mirroredEfi + diskName + zfsRoot.partitionScheme.efiBoot + "\n")
|
||||||
|
(tail zfsRoot.bootDevices)));
|
||||||
|
boot.loader.grub.devices =
|
||||||
|
(map (diskName: zfsRoot.devNodes + diskName) zfsRoot.bootDevices);
|
||||||
|
boot.initrd.postDeviceCommands = ''
|
||||||
|
zpool import -Nf rpool
|
||||||
|
zfs rollback -r rpool/nixos/empty@start
|
||||||
|
zpool export -a
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
|
||||||
227
docs/Getting Started/NixOS/Root on ZFS/configuration.nix
Normal file
227
docs/Getting Started/NixOS/Root on ZFS/configuration.nix
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
# Edit this configuration file to define what should be installed on
|
||||||
|
# your system. Help is available in the configuration.nix(5) man page
|
||||||
|
# and in the NixOS manual (accessible by running ‘nixos-help’).
|
||||||
|
{ config, lib, pkgs, modulesPath, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
zfsRoot.partitionScheme = {
|
||||||
|
biosBoot = "-part5";
|
||||||
|
efiBoot = "-part1";
|
||||||
|
swap = "-part4";
|
||||||
|
bootPool = "-part2";
|
||||||
|
rootPool = "-part3";
|
||||||
|
};
|
||||||
|
zfsRoot.devNodes = PLACEHOLDER_FOR_DEV_NODE_PATH; # MUST have trailing slash! /dev/disk/by-id/
|
||||||
|
zfsRoot.bootDevices = (import ./machine.nix).bootDevices;
|
||||||
|
zfsRoot.mirroredEfi = "/boot/efis/";
|
||||||
|
|
||||||
|
in {
|
||||||
|
# adjust according to your platform, such as
|
||||||
|
imports = [
|
||||||
|
# (modulesPath + "/profiles/qemu-guest.nix")
|
||||||
|
# (modulesPath + "/profiles/all-hardware.nix")
|
||||||
|
(modulesPath + "/installer/scan/not-detected.nix")
|
||||||
|
];
|
||||||
|
systemd.services.zfs-mount.enable = false;
|
||||||
|
|
||||||
|
# networking.hostName = "nixos"; # Define your hostname.
|
||||||
|
# Pick only one of the below networking options.
|
||||||
|
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
|
||||||
|
# networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
|
||||||
|
|
||||||
|
# Set your time zone.
|
||||||
|
# time.timeZone = "Europe/Amsterdam";
|
||||||
|
|
||||||
|
# Configure network proxy if necessary
|
||||||
|
# networking.proxy.default = "http://user:password@proxy:port/";
|
||||||
|
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
|
||||||
|
|
||||||
|
# Select internationalisation properties.
|
||||||
|
# i18n.defaultLocale = "en_US.UTF-8";
|
||||||
|
# console = {
|
||||||
|
# font = "Lat2-Terminus16";
|
||||||
|
# keyMap = "us";
|
||||||
|
# useXkbConfig = true; # use xkbOptions in tty.
|
||||||
|
# };
|
||||||
|
|
||||||
|
# Enable the X11 windowing system.
|
||||||
|
|
||||||
|
# Configure keymap in X11
|
||||||
|
# "eurosign:e";
|
||||||
|
# "caps:escape" # map caps to escape.
|
||||||
|
# };
|
||||||
|
|
||||||
|
# Enable CUPS to print documents.
|
||||||
|
# services.printing.enable = true;
|
||||||
|
|
||||||
|
# Enable sound.
|
||||||
|
# sound.enable = true;
|
||||||
|
# hardware.pulseaudio.enable = true;
|
||||||
|
|
||||||
|
# Enable touchpad support (enabled default in most desktopManager).
|
||||||
|
|
||||||
|
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||||
|
# users.users.alice = {
|
||||||
|
# isNormalUser = true;
|
||||||
|
# extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
||||||
|
# packages = with pkgs; [
|
||||||
|
# firefox
|
||||||
|
# thunderbird
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
|
|
||||||
|
# List packages installed in system profile. To search, run:
|
||||||
|
# $ nix search wget
|
||||||
|
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
|
||||||
|
mg
|
||||||
|
];
|
||||||
|
|
||||||
|
# Some programs need SUID wrappers, can be configured further or are
|
||||||
|
# started in user sessions.
|
||||||
|
# programs.mtr.enable = true;
|
||||||
|
# programs.gnupg.agent = {
|
||||||
|
# enable = true;
|
||||||
|
# enableSSHSupport = true;
|
||||||
|
# };
|
||||||
|
|
||||||
|
# List services that you want to enable:
|
||||||
|
|
||||||
|
# Enable the OpenSSH daemon.
|
||||||
|
services.openssh.enable = false;
|
||||||
|
users.users.root = {
|
||||||
|
##hash: mkpasswd -m SHA-512 -s
|
||||||
|
initialHashedPassword = PLACEHOLDER_FOR_ROOT_PWD_HASH;
|
||||||
|
openssh.authorizedKeys.keys = [
|
||||||
|
];
|
||||||
|
};
|
||||||
|
programs.git.enable = true;
|
||||||
|
# Open ports in the firewall.
|
||||||
|
# networking.firewall.allowedTCPPorts = [ ... ];
|
||||||
|
# networking.firewall.allowedUDPPorts = [ ... ];
|
||||||
|
# Or disable the firewall altogether.
|
||||||
|
# networking.firewall.enable = false;
|
||||||
|
|
||||||
|
# Copy the NixOS configuration file and link it from the resulting system
|
||||||
|
# (/run/current-system/configuration.nix). This is useful in case you
|
||||||
|
# accidentally delete configuration.nix.
|
||||||
|
system.copySystemConfiguration = true;
|
||||||
|
|
||||||
|
# This value determines the NixOS release from which the default
|
||||||
|
# settings for stateful data, like file locations and database versions
|
||||||
|
# on your system were taken. It‘s perfectly fine and recommended to leave
|
||||||
|
# this value at the release version of the first install of this system.
|
||||||
|
# Before changing this value read the documentation for this option
|
||||||
|
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
|
||||||
|
system.stateVersion = "22.11"; # Did you read the comment?
|
||||||
|
|
||||||
|
boot.initrd.availableKernelModules = [
|
||||||
|
"ahci"
|
||||||
|
"xhci_pci"
|
||||||
|
"virtio_pci"
|
||||||
|
"virtio_blk"
|
||||||
|
"ehci_pci"
|
||||||
|
"nvme"
|
||||||
|
"uas"
|
||||||
|
"sd_mod"
|
||||||
|
"sr_mod"
|
||||||
|
"sdhci_pci"
|
||||||
|
];
|
||||||
|
boot.initrd.kernelModules = [ ];
|
||||||
|
boot.kernelModules = [ "kvm-intel" "kvm-amd" ];
|
||||||
|
boot.extraModulePackages = [ ];
|
||||||
|
|
||||||
|
fileSystems = {
|
||||||
|
"/" = {
|
||||||
|
device = "rpool/nixos/root";
|
||||||
|
fsType = "zfs";
|
||||||
|
options = [ "X-mount.mkdir" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
"/home" = {
|
||||||
|
device = "rpool/nixos/home";
|
||||||
|
fsType = "zfs";
|
||||||
|
options = [ "X-mount.mkdir" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
"/var/lib" = {
|
||||||
|
device = "rpool/nixos/var/lib";
|
||||||
|
fsType = "zfs";
|
||||||
|
options = [ "X-mount.mkdir" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
"/var/log" = {
|
||||||
|
device = "rpool/nixos/var/log";
|
||||||
|
fsType = "zfs";
|
||||||
|
options = [ "X-mount.mkdir" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
"/boot" = {
|
||||||
|
device = "bpool/nixos/root";
|
||||||
|
fsType = "zfs";
|
||||||
|
options = [ "X-mount.mkdir" ];
|
||||||
|
};
|
||||||
|
} // (builtins.listToAttrs (map (diskName: {
|
||||||
|
name = zfsRoot.mirroredEfi + diskName + zfsRoot.partitionScheme.efiBoot;
|
||||||
|
value = {
|
||||||
|
device = zfsRoot.devNodes + diskName + zfsRoot.partitionScheme.efiBoot;
|
||||||
|
fsType = "vfat";
|
||||||
|
options = [
|
||||||
|
"x-systemd.idle-timeout=1min"
|
||||||
|
"x-systemd.automount"
|
||||||
|
"noauto"
|
||||||
|
"nofail"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}) zfsRoot.bootDevices));
|
||||||
|
|
||||||
|
swapDevices = (map (diskName: {
|
||||||
|
device = zfsRoot.devNodes + diskName + zfsRoot.partitionScheme.swap;
|
||||||
|
discardPolicy = "both";
|
||||||
|
randomEncryption = {
|
||||||
|
enable = true;
|
||||||
|
allowDiscards = true;
|
||||||
|
};
|
||||||
|
}) zfsRoot.bootDevices);
|
||||||
|
|
||||||
|
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||||
|
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||||
|
# still possible to use this option, but it's recommended to use it in conjunction
|
||||||
|
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
|
||||||
|
networking.useDHCP = lib.mkDefault true;
|
||||||
|
# networking.networkmanager.enable = true;
|
||||||
|
# networking.interfaces.enp1s0.useDHCP = lib.mkDefault true;
|
||||||
|
|
||||||
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
|
hardware.cpu.intel.updateMicrocode =
|
||||||
|
lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
hardware.cpu.amd.updateMicrocode =
|
||||||
|
lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||||
|
|
||||||
|
boot.supportedFilesystems = [ "zfs" ];
|
||||||
|
networking.hostId = "abcd1234";
|
||||||
|
boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages;
|
||||||
|
boot.loader.efi.efiSysMountPoint = with builtins;
|
||||||
|
(zfsRoot.mirroredEfi + (head zfsRoot.bootDevices) + zfsRoot.partitionScheme.efiBoot);
|
||||||
|
boot.zfs.devNodes = zfsRoot.devNodes;
|
||||||
|
boot.loader.efi.canTouchEfiVariables = false;
|
||||||
|
boot.loader.generationsDir.copyKernels = true;
|
||||||
|
boot.loader.grub.efiInstallAsRemovable = true;
|
||||||
|
boot.loader.grub.enable = true;
|
||||||
|
boot.loader.grub.version = 2;
|
||||||
|
boot.loader.grub.copyKernels = true;
|
||||||
|
boot.loader.grub.efiSupport = true;
|
||||||
|
boot.loader.grub.zfsSupport = true;
|
||||||
|
boot.loader.grub.extraInstallCommands = with builtins;
|
||||||
|
(toString (map (diskName:
|
||||||
|
"cp -r " + config.boot.loader.efi.efiSysMountPoint + "/EFI" + " "
|
||||||
|
+ zfsRoot.mirroredEfi + diskName + zfsRoot.partitionScheme.efiBoot + "\n")
|
||||||
|
(tail zfsRoot.bootDevices)));
|
||||||
|
boot.loader.grub.devices =
|
||||||
|
(map (diskName: zfsRoot.devNodes + diskName) zfsRoot.bootDevices);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user