239 lines
7.1 KiB
Nix
239 lines
7.1 KiB
Nix
# Disko configuration for box NAS
|
|
# NVMe boot drive with LUKS + 3x 4TB ZFS RAIDZ1 pool (~8TB usable)
|
|
# Unified encryption: LUKS passphrase unlocks root, ZFS uses keyfile inside encrypted root
|
|
#
|
|
# NOTE: Using RAIDZ1 (3 drives) temporarily due to DOA drive. Can migrate to RAIDZ2
|
|
# with 4 drives later by creating a new pool and copying data.
|
|
#
|
|
# Installation steps:
|
|
#
|
|
# 1. Generate the ZFS keyfile and LUKS password:
|
|
# dd if=/dev/urandom of=/tmp/tank.key bs=32 count=1
|
|
# echo -n "your-luks-password" > /tmp/luks-password
|
|
#
|
|
# 2. Run disko-install:
|
|
# sudo nix run 'github:nix-community/disko/latest#disko-install' -- \
|
|
# --flake ~/helm#box \
|
|
# --disk nvme /dev/disk/by-id/nvme-CT500P310SSD8_2544543B87C2 \
|
|
# --disk zfs1 /dev/disk/by-id/ata-WDC_WD40EFPX-68C6CN0_WD-WX32D954A2J7 \
|
|
# --disk zfs2 /dev/disk/by-id/ata-WDC_WD40EFPX-68C6CN0_WD-WX32D95FVZVL \
|
|
# --disk zfs3 /dev/disk/by-id/ata-WDC_WD40EFPX-68C6CN0_WD-WX42D95M807R
|
|
#
|
|
# 3. Copy the keyfile and update keylocation:
|
|
# sudo mkdir -p /mnt/etc/zfs
|
|
# sudo cp /tmp/tank.key /mnt/etc/zfs/tank.key
|
|
# sudo chmod 000 /mnt/etc/zfs/tank.key
|
|
# sudo zfs set keylocation=file:///etc/zfs/tank.key tank
|
|
{
|
|
disko.devices = {
|
|
disk = {
|
|
# Boot drive - 500GB NVMe with LUKS encryption
|
|
nvme = {
|
|
type = "disk";
|
|
device = "/dev/disk/by-id/nvme-placeholder"; # Override with --disk nvme /dev/disk/by-id/...
|
|
content = {
|
|
type = "gpt";
|
|
partitions = {
|
|
ESP = {
|
|
size = "512M";
|
|
type = "EF00";
|
|
content = {
|
|
type = "filesystem";
|
|
format = "vfat";
|
|
mountpoint = "/boot";
|
|
mountOptions = [ "umask=0077" ];
|
|
};
|
|
};
|
|
luks = {
|
|
size = "100%";
|
|
content = {
|
|
type = "luks";
|
|
name = "cryptroot";
|
|
settings = {
|
|
allowDiscards = true;
|
|
};
|
|
# Passphrase will be prompted during boot
|
|
passwordFile = "/tmp/luks-password"; # Only used during install, set this before running disko
|
|
content = {
|
|
type = "filesystem";
|
|
format = "ext4";
|
|
mountpoint = "/";
|
|
mountOptions = [ "noatime" ];
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
# ZFS pool drives - 3x 4TB in RAIDZ1
|
|
zfs1 = {
|
|
type = "disk";
|
|
device = "/dev/disk/by-id/placeholder-zfs1"; # Override with --disk zfs1 /dev/disk/by-id/...
|
|
content = {
|
|
type = "gpt";
|
|
partitions = {
|
|
zfs = {
|
|
size = "100%";
|
|
content = {
|
|
type = "zfs";
|
|
pool = "tank";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
zfs2 = {
|
|
type = "disk";
|
|
device = "/dev/disk/by-id/placeholder-zfs2";
|
|
content = {
|
|
type = "gpt";
|
|
partitions = {
|
|
zfs = {
|
|
size = "100%";
|
|
content = {
|
|
type = "zfs";
|
|
pool = "tank";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
zfs3 = {
|
|
type = "disk";
|
|
device = "/dev/disk/by-id/placeholder-zfs3";
|
|
content = {
|
|
type = "gpt";
|
|
partitions = {
|
|
zfs = {
|
|
size = "100%";
|
|
content = {
|
|
type = "zfs";
|
|
pool = "tank";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
zpool = {
|
|
tank = {
|
|
type = "zpool";
|
|
mode = "raidz1";
|
|
options = {
|
|
ashift = "12";
|
|
cachefile = "none"; # Needed for disko
|
|
};
|
|
rootFsOptions = {
|
|
compression = "lz4";
|
|
atime = "off";
|
|
xattr = "sa";
|
|
acltype = "posixacl";
|
|
# ZFS native encryption
|
|
# During install: keyfile at /tmp/tank.key
|
|
# After install: install-box.sh copies to /etc/zfs/tank.key and updates keylocation
|
|
encryption = "aes-256-gcm";
|
|
keyformat = "raw";
|
|
keylocation = "file:///tmp/tank.key";
|
|
"com.sun:auto-snapshot" = "false";
|
|
};
|
|
# Don't mount the pool root directly
|
|
mountpoint = null;
|
|
|
|
datasets = {
|
|
# /nix is on the NVMe ext4 root, not on ZFS
|
|
# This simplifies boot dependencies - ZFS is purely for data storage
|
|
|
|
# Parent dataset for all data - inherits encryption
|
|
data = {
|
|
type = "zfs_fs";
|
|
options.mountpoint = "none";
|
|
};
|
|
|
|
# Media datasets
|
|
"data/media" = {
|
|
type = "zfs_fs";
|
|
options.mountpoint = "none";
|
|
};
|
|
"data/media/music" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/media/music";
|
|
options.recordsize = "1M"; # Large files benefit from larger recordsize
|
|
};
|
|
"data/media/photos" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/media/photos";
|
|
options.recordsize = "1M";
|
|
};
|
|
"data/media/movies" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/media/movies";
|
|
options.recordsize = "1M";
|
|
};
|
|
"data/media/tv" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/media/tv";
|
|
options.recordsize = "1M";
|
|
};
|
|
|
|
# Other data
|
|
"data/books" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/books";
|
|
options."com.sun:auto-snapshot" = "true";
|
|
};
|
|
"data/podcasts" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/podcasts";
|
|
};
|
|
"data/postgres" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/postgres";
|
|
options = {
|
|
recordsize = "16K"; # Better for databases
|
|
"com.sun:auto-snapshot" = "true";
|
|
};
|
|
};
|
|
"data/syncthing" = {
|
|
type = "zfs_fs";
|
|
options.mountpoint = "none";
|
|
options."com.sun:auto-snapshot" = "true";
|
|
};
|
|
"data/syncthing/drawing" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/syncthing/drawing";
|
|
};
|
|
"data/backup" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/backup";
|
|
options."com.sun:auto-snapshot" = "true";
|
|
};
|
|
"data/ftp" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/ftp";
|
|
};
|
|
"data/cache" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/cache";
|
|
options."com.sun:auto-snapshot" = "false";
|
|
};
|
|
"data/playlists" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/playlists";
|
|
};
|
|
"data/new-music" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/new-music";
|
|
};
|
|
"data/archive" = {
|
|
type = "zfs_fs";
|
|
mountpoint = "/tank/archive";
|
|
options."com.sun:auto-snapshot" = "true";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|