2026-08-05 22:06:01 +01:00
|
|
|
{...}: {
|
|
|
|
|
# Every filesystem on shadow lives here, hand-maintained.
|
|
|
|
|
#
|
|
|
|
|
# hardware.nix is generated with `--no-filesystems` precisely so it never
|
|
|
|
|
# emits fileSystems/swapDevices entries of its own. That keeps regeneration
|
|
|
|
|
# (`nix run .#sync-hardware`) safe: re-running it can never clobber these
|
|
|
|
|
# definitions, nor produce duplicates for whichever data drives happened to
|
|
|
|
|
# be mounted at the time it ran.
|
|
|
|
|
flake.nixosModules.shadowDisks = {...}: let
|
2026-08-05 22:17:53 +01:00
|
|
|
# Secondary data drives, addressed by filesystem label.
|
2026-08-05 22:06:01 +01:00
|
|
|
#
|
2026-08-05 22:17:53 +01:00
|
|
|
# nofail on all of them: it stops a missing or dying disk from becoming a
|
|
|
|
|
# failed boot dependency that drops the machine into emergency mode.
|
2026-08-05 22:06:01 +01:00
|
|
|
#
|
|
|
|
|
# On-disk ownership is already ahmza mode 755 on all three, so no uid mapping
|
|
|
|
|
# is needed — ext4 stores ownership in the filesystem and ignores uid=/gid=.
|
2026-08-05 22:17:53 +01:00
|
|
|
|
|
|
|
|
# Spinning disks (sda/sdc, both WD, rotational=1). noauto +
|
|
|
|
|
# x-systemd.automount makes systemd generate an .automount unit and mount on
|
|
|
|
|
# first access to the path rather than at boot, so they stay parked until
|
|
|
|
|
# something actually touches them; idle-timeout unmounts them again once
|
|
|
|
|
# quiet so they can spin back down.
|
|
|
|
|
#
|
|
|
|
|
# Note the idle unmount fails with "target is busy" while any shell has its
|
|
|
|
|
# cwd inside the mount. That is harmless — it simply stays mounted and retries.
|
|
|
|
|
spinningDrive = label: {
|
2026-08-05 22:06:01 +01:00
|
|
|
device = "/dev/disk/by-label/${label}";
|
|
|
|
|
fsType = "ext4";
|
|
|
|
|
options = [
|
|
|
|
|
"nofail"
|
|
|
|
|
"noauto"
|
|
|
|
|
"x-systemd.automount"
|
|
|
|
|
"x-systemd.idle-timeout=600"
|
|
|
|
|
"x-systemd.device-timeout=10"
|
|
|
|
|
];
|
|
|
|
|
};
|
2026-08-05 22:17:53 +01:00
|
|
|
|
|
|
|
|
# Always-on drive. Used for the games library: it is an SSD (Samsung 870 QVO,
|
|
|
|
|
# rotational=0) so there is no spin-down to gain, and a Steam library is
|
|
|
|
|
# better off never sitting behind an automount trigger.
|
|
|
|
|
#
|
|
|
|
|
# Unrelated but worth knowing, since it looks like a mount problem: Steam's
|
|
|
|
|
# FHS sandbox builds its bind list at launch by iterating /*, so a top-level
|
|
|
|
|
# directory that does not exist when Steam starts is invisible to that
|
|
|
|
|
# instance for its whole lifetime, and Steam reports it as "not writable".
|
|
|
|
|
# /mnt only comes into existence when these entries are activated, so Steam
|
|
|
|
|
# must be restarted after a fresh boot-time change here.
|
|
|
|
|
eagerDrive = label: {
|
|
|
|
|
device = "/dev/disk/by-label/${label}";
|
|
|
|
|
fsType = "ext4";
|
|
|
|
|
options = [
|
|
|
|
|
"nofail"
|
|
|
|
|
"x-systemd.device-timeout=10"
|
|
|
|
|
];
|
|
|
|
|
};
|
2026-08-05 22:06:01 +01:00
|
|
|
in {
|
|
|
|
|
fileSystems = {
|
|
|
|
|
# Boot essentials, by UUID. UUIDs rather than labels here on purpose:
|
|
|
|
|
# these two must resolve unambiguously, and a label is only as unique as
|
|
|
|
|
# the last disk someone plugged in.
|
|
|
|
|
"/" = {
|
|
|
|
|
device = "/dev/disk/by-uuid/deff63fc-1738-4cfc-a79c-06e58c78471a";
|
|
|
|
|
fsType = "ext4";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
"/boot" = {
|
|
|
|
|
device = "/dev/disk/by-uuid/5873-AD05";
|
|
|
|
|
fsType = "vfat";
|
|
|
|
|
options = ["fmask=0077" "dmask=0077"];
|
|
|
|
|
};
|
|
|
|
|
|
2026-08-05 22:17:53 +01:00
|
|
|
"/mnt/dump" = spinningDrive "DUMP";
|
|
|
|
|
"/mnt/bak" = spinningDrive "BAK";
|
|
|
|
|
"/mnt/games" = eagerDrive "GAMES";
|
2026-08-05 22:06:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
swapDevices = [];
|
|
|
|
|
};
|
|
|
|
|
}
|