I’m thinking of creating a tmpfs folder under /home/tmp and I found it to be very simple:
fileSystems."/home/tmp".fsType = "tmpfs";
However, I wanted to inherit settings from config.boot.tmp to avoid repeating code. In looking for how to do this, I found that the module uses a completely different way to mount /tmp:
tmpfs nix code
systemd.mounts = lib.mkIf cfg.useTmpfs [
{
what = "tmpfs";
where = "/tmp";
type = "tmpfs";
mountConfig.Options = lib.concatStringsSep "," [
"mode=1777"
"strictatime"
"rw"
"nosuid"
"nodev"
"size=${toString cfg.tmpfsSize}"
"huge=${cfg.tmpfsHugeMemoryPages}"
];
}
];
Now I wonder, what’s the practical difference? The implementation for fileSystems does seems somewhat long and monolithic, but in the end it creates systemd mount units like mnt-data.mount anyway.
I would of course prefer the fileSystems snippet, but I don’t know if there’s a good way to reuse options from /tmp with that. If I were to use systemd.mounts, then perhaps I can copy the entry in the list, replace the path, (/tmp to /home/tmp) and append it with the rest?
Some context for why I would want a /home/tmp; I like to use tmpfs extensively to avoid clutter and reduce disk IO, like for downloads that I’d unzip and throw away the zip file. However the global tmpfs in /tmp isn’t very nice for this because there’s a lot of system files and directories there that add clutter. Hence, /home/tmp, which also creates the interesting option of having a user named “tmp” with a completely temporary home directory for some minor tests.
fileSystems will be added to /etc/fstab, which is parsed by systemd on bootup to create the necessary transient mount units. systemd.mounts generates an actual mount unit and doesn’t write to /etc/fstab.
1 Like
fileSystems will be added to /etc/fstab, which is parsed by systemd on bootup to create the necessary transient mount units
I did notice that /tmp doesn’t show in /etc/fstab. However, even via the fileSystems option, /home/tmp was mounted for me on system activation, not just on bootup.
This doesn’t really tell me why to use one over the other though.
This is what I came up with, but it is of course infinite recursion…
systemd.mounts =
let
tmpMount = lib.findFirst (mount: mount.where == "/tmp") null config.systemd.mounts;
in
lib.mkIf (tmpMount != null) (
builtins.mapAttrs (name: value: if name == "where" then "/home/tmp" else value) tmpMount
);
This is what works for me, but it’s not exactly clean…
fileSystems."/home/tmp" = lib.mkDefault {
fsType = "tmpfs";
# inherit options created by boot.tmp.useTmpfs if avaliable
options =
let
tmpMount = lib.findFirst (mount: mount.where == "/tmp") null config.systemd.mounts;
in
lib.mkIf (tmpMount != null) (lib.splitStringBy (p: c: c == ",") false tmpMount.mountConfig.Options);
};
As a user, there really isn’t a strong reason to prefer one over the other. Normally people just stick to /etc/fstab since its a little bit quicker to write mounts into, but on NixOS the process is pretty much identical thanks to the module system so that really doesn’t apply here. Creating a mount unit can be helpful if you have specific service dependencies that would otherwise be more difficult/impossible to declare in /etc/fstab (suppose you want to fire up a mount alongside some other service), though that’s also a niche case.
Personally, I’d say that if you don’t have a specific reason to want a systemd mount unit, just stick to fileSystems.
2 Likes