I recently bought a NAS and I would like to get some review on my disko-ZFS-setup, if someone can spare a few minutes
The setup has not been tested yet, as the device arrived days before a work trip, but I will be able to play starting next weekend.
Hardware
- ugreen
- With 8GB RAM
- Intel N100
- Space for 4 HDDs
- 2x 1TB 990 Samsung Pro SSD
- 2x 22TB Harddrive (one WD, one Toshiba)
The NAS Hardware has 4 slots, my upgrade plan is to add more 22TB (or bigger) drives to the vdev once the 22TB are running out of free space.
Usecase / Software
I will the use the device for:
- Backups (borg)
- Storing Movies, Music, Pictures, Documents (these are all inside different git-annex repositories right now, which I will keep)
- Services:
- Navidrome for music streaming
- Jellyfin for Movie Streaming to kodi
- Kodi for watching movies and connecting also Spotify, Amazon Prime, Youtube, Arte Mediathek, SomaFM, etc
- Immich (not 100% decided on this one yet, but looks good)
- Syncthing âbackupsâ (encrypted remote for syncthing)
The device will be connected to a screen / audio system in my living-room for watching movies and listening to music. Movies will maybe be streamed to devices in the LAN, music will be streamed to devices outside of the LAN as well (tailscale ftw).
ZFS Setup
1 SSD will hold /boot
and the nixos root filesystem, both SSDs will hold a 16GB SWAP (because why notâŚ)
The other SSD is used for databases (immich needs a postgres) and caches (the immich machinelearning service needs some cache space, maybe thereâs other stuff that could use cache). The syncthing I want to set up will also be on there.
The âmediaâ datasets as well as the database dataset are encrypted and will be decrypted by logging in via SSH and doing the decrypt, the relevant services start after the dataset(s) have been mounted (still need to figure out how to do this).
nixos root, backups, syncthing cache do not need encryption (the later two are incrypted client-side already).
The harddrives will be Z1
, not mirror
, as I want to be able to grow the vdev later on to up to 4 drives.
Disko
Hereâs the disko code I came up with so far (which isnât tested yet). I just want to know whether the general idea is alright.
Iâve read a bunch of tutorials and guides on the ZFS options I want to use, but I am still not 100% certain whether I did everything alright.
I am especially concerned about the LARC2 cache, where I am not sure whether this needs to be a small partition only (something like 16GB) or whether I rather want something quite big.
The usecase of the device is 2 users, but not even 2 users watching movies in parallel, only maybe running backups while watching a movie, which we do not care whether it takes 10 or 30 minutes to run the backup.
_:
let
dataDiskDefaults = {
type = "disk";
content = {
type = "gpt";
partitions.zfs = {
size = "100%";
content.type = "zfs";
};
};
};
in
{
disko.devices = {
disk = {
ssd1 = {
type = "disk";
device = null; # TODO
content = {
type = "gpt";
partitions = {
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
zfs = {
size = "100%";
content = {
type = "zfs";
pool = "zroot";
};
};
swap = {
size = "16G";
content = {
type = "swap";
randomEncryption = true;
priority = 100;
};
};
};
};
};
ssd2 = {
type = "disk";
device = null; # TODO
content = {
type = "gpt";
partitions = {
ssd2data1 = {
# TODO: See ssd2zfs_larc2
size = "100%";
content = {
type = "zfs";
pool = "zssddata";
};
};
swap = {
size = "16G";
content = {
type = "swap";
randomEncryption = true;
priority = 100;
};
};
ssd2zfs_larc2 = {
# TODO: I don't yet understand how big the LARC2 cache should be
# and whether it actually is possible / a good idea to have a dedicated partition for it
size = "100%";
content = {
type = "zfs";
pool = "zdata";
};
};
};
};
};
data1 = dataDiskDefaults // {
device = ""; # TODO
content.partitions.zfs.content.pool = "zdata";
};
data2 = dataDiskDefaults // {
device = ""; # TODO
content.partitions.zfs.content.pool = "zdata";
};
};
zpool = {
zroot = {
type = "zpool";
mode = {
topology = {
type = "topology";
vdev = [
{
members = [
"ssd1"
];
}
];
};
};
rootFsOptions = {
compression = "off";
"com.sun:auto-snapshot" = "false";
};
datasets = {
"nixroot" = {
type = "zfs_fs";
options = {
mountpoint = "/";
acltype = "posixacl";
xattr = "sa";
atime = "off";
refreservation = "1G";
compression = "zstd";
};
};
};
};
zssddata = {
type = "zpool";
mode = {
topology = {
type = "topology";
vdev = [
{
members = [
"ssd2data1"
];
}
];
};
};
rootFsOptions = {
compression = "off";
"com.sun:auto-snapshot" = "false";
};
datasets = {
"cache/immich" = {
type = "zfs_fs";
options = {
mountpoint = "/zfs_immich_cache";
acltype = "posixacl";
xattr = "sa";
atime = "off";
refreservation = "1G";
compression = "zstd";
quota = "50G";
# TODO
};
};
"cache/syncthing" = {
type = "zfs_fs";
options = {
mountpoint = "/zfs_syncthing_cache";
acltype = "posixacl";
xattr = "sa";
atime = "off";
refreservation = "1G";
compression = "zstd";
quota = "200G";
};
};
"db/postgres" = {
type = "zfs_fs";
options = {
mountpoint = "none";
encryption = "aes-256-gcm";
keyformat = "passphrase";
acltype = "posixacl";
compression = "off";
xattr = "sa";
atime = "off";
refreservation = "1G";
# TODO
};
};
};
};
zdata = {
type = "zpool";
options.cachefile = "none";
rootFsOptions = {
# No compression on the root device
# compression = "zstd";
compression = "off";
# Do not snapshot the root device
"com.sun:auto-snapshot" = "false";
};
mode = {
topology = {
type = "topology";
vdev = [
{
mode = "raidz1";
members = [
"data1"
"data2"
];
}
];
cache = ["ssd2zfs_larc2"];
};
};
datasets = {
"media/images" = {
type = "zfs_fs";
options = {
mountpoint = "none";
encryption = "aes-256-gcm";
keyformat = "passphrase";
acltype = "posixacl";
compression = "off";
xattr = "sa";
atime = "off";
refreservation = "1G";
};
};
"media/music" = {
type = "zfs_fs";
options = {
mountpoint = "none";
encryption = "aes-256-gcm";
keyformat = "passphrase";
acltype = "posixacl";
compression = "off";
xattr = "sa";
atime = "off";
refreservation = "1G";
};
};
"media/movies" = {
type = "zfs_fs";
options = {
mountpoint = "none";
encryption = "aes-256-gcm";
keyformat = "passphrase";
acltype = "posixacl";
compression = "off";
xattr = "sa";
atime = "off";
refreservation = "1G";
};
};
"media/library" = {
type = "zfs_fs";
options = {
mountpoint = "none";
encryption = "aes-256-gcm";
keyformat = "passphrase";
acltype = "posixacl";
compression = "off";
xattr = "sa";
atime = "off";
refreservation = "1G";
};
};
backups = {
type = "zfs_fs";
mountpoint = "/zfs_backups";
options = {
acltype = "posixacl";
compression = "off";
xattr = "sa";
atime = "off";
refreservation = "1G";
};
};
mirrors = {
type = "zfs_fs";
mountpoint = "/zfs_mirrors";
options = {
acltype = "posixacl";
compression = "off";
xattr = "sa";
atime = "off";
refreservation = "1G";
};
};
};
};
};
};
}
I hope I did not forget anything here.