624 lines
18 KiB
Nix
624 lines
18 KiB
Nix
|
|
{
|
|||
|
|
config,
|
|||
|
|
lib,
|
|||
|
|
pkgs,
|
|||
|
|
utils,
|
|||
|
|
...
|
|||
|
|
}@moduleArgs:
|
|||
|
|
let
|
|||
|
|
inherit (lib)
|
|||
|
|
any
|
|||
|
|
attrValues
|
|||
|
|
concatMapStrings
|
|||
|
|
concatMapStringsSep
|
|||
|
|
concatStringsSep
|
|||
|
|
elem
|
|||
|
|
filter
|
|||
|
|
flip
|
|||
|
|
head
|
|||
|
|
literalExpression
|
|||
|
|
mkDefault
|
|||
|
|
mkEnableOption
|
|||
|
|
mkIf
|
|||
|
|
mkMerge
|
|||
|
|
mkOption
|
|||
|
|
optional
|
|||
|
|
optionalAttrs
|
|||
|
|
optionalString
|
|||
|
|
toposort
|
|||
|
|
types
|
|||
|
|
;
|
|||
|
|
inherit (utils) fsBefore;
|
|||
|
|
|
|||
|
|
# https://wiki.archlinux.org/index.php/fstab#Filepath_spaces
|
|||
|
|
escape = string: builtins.replaceStrings [ " " "\t" ] [ "\\040" "\\011" ] string;
|
|||
|
|
|
|||
|
|
# A list of attrnames is coerced into an attrset of bools by
|
|||
|
|
# setting the values to true.
|
|||
|
|
attrNamesToTrue = types.coercedTo (types.listOf types.str) (
|
|||
|
|
enabledList: lib.genAttrs enabledList (_attrName: true)
|
|||
|
|
) (types.attrsOf types.bool);
|
|||
|
|
|
|||
|
|
addCheckDesc =
|
|||
|
|
desc: elemType: check:
|
|||
|
|
types.addCheck elemType check // { description = "${elemType.description} (with check: ${desc})"; };
|
|||
|
|
|
|||
|
|
isNonEmpty = s: (builtins.match "[ \t\n]*" s) == null;
|
|||
|
|
nonEmptyStr = addCheckDesc "non-empty" types.str isNonEmpty;
|
|||
|
|
|
|||
|
|
fileSystems' = toposort fsBefore (attrValues config.fileSystems);
|
|||
|
|
|
|||
|
|
fileSystems =
|
|||
|
|
if fileSystems' ? result then
|
|||
|
|
# use topologically sorted fileSystems everywhere
|
|||
|
|
fileSystems'.result
|
|||
|
|
else
|
|||
|
|
# the assertion below will catch this,
|
|||
|
|
# but we fall back to the original order
|
|||
|
|
# anyway so that other modules could check
|
|||
|
|
# their assertions too
|
|||
|
|
(attrValues config.fileSystems);
|
|||
|
|
|
|||
|
|
specialFSTypes = [
|
|||
|
|
"proc"
|
|||
|
|
"sysfs"
|
|||
|
|
"tmpfs"
|
|||
|
|
"ramfs"
|
|||
|
|
"devtmpfs"
|
|||
|
|
"devpts"
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
nonEmptyWithoutTrailingSlash = addCheckDesc "non-empty without trailing slash" types.str (
|
|||
|
|
s: isNonEmpty s && (builtins.match ".+/" s) == null
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
coreFileSystemOpts =
|
|||
|
|
{ name, config, ... }:
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
options = {
|
|||
|
|
enable = mkEnableOption "the filesystem mount" // {
|
|||
|
|
default = true;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
mountPoint = mkOption {
|
|||
|
|
example = "/mnt/usb";
|
|||
|
|
type = nonEmptyWithoutTrailingSlash;
|
|||
|
|
default = name;
|
|||
|
|
description = ''
|
|||
|
|
Location where the file system will be mounted.
|
|||
|
|
|
|||
|
|
This is called `mountpoint` in {manpage}`mount(8)` and `fs_file` in {manpage}`fstab(5)`
|
|||
|
|
'';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
stratis.poolUuid = mkOption {
|
|||
|
|
type = types.uniq (types.nullOr types.str);
|
|||
|
|
description = ''
|
|||
|
|
UUID of the stratis pool that the fs is located in
|
|||
|
|
|
|||
|
|
This is only relevant if you are using [stratis](https://stratis-storage.github.io/).
|
|||
|
|
'';
|
|||
|
|
example = "04c68063-90a5-4235-b9dd-6180098a20d9";
|
|||
|
|
default = null;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
device = mkOption {
|
|||
|
|
default = null;
|
|||
|
|
example = "/dev/sda";
|
|||
|
|
type = types.nullOr nonEmptyStr;
|
|||
|
|
description = ''
|
|||
|
|
The device as passed to `mount`.
|
|||
|
|
|
|||
|
|
This can be any of:
|
|||
|
|
|
|||
|
|
- a filename of a block special device such as `/dev/sdc3`
|
|||
|
|
- a tag such as `UUID=fdd68895-c307-4549-8c9c-90e44c71f5b7`
|
|||
|
|
- (for bind mounts only) the source path
|
|||
|
|
- something else depending on the {option}`fsType`. For example, `nfs` device may look like `knuth.cwi.nl:/dir`
|
|||
|
|
|
|||
|
|
This is called `device` in {manpage}`mount(8)` and `fs_spec` in {manpage}`fstab(5)`.
|
|||
|
|
'';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
fsType = mkOption {
|
|||
|
|
default = "auto";
|
|||
|
|
example = "ext3";
|
|||
|
|
type = nonEmptyStr;
|
|||
|
|
description = ''
|
|||
|
|
Type of the file system.
|
|||
|
|
|
|||
|
|
This is the `fstype` passed to `-t` in the {manpage}`mount(8)` command, and is called `fs_vfstype` in {manpage}`fstab(5)`.
|
|||
|
|
'';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
options = mkOption {
|
|||
|
|
default = [ "defaults" ];
|
|||
|
|
example = [ "data=journal" ];
|
|||
|
|
description = ''
|
|||
|
|
Options used to mount the file system.
|
|||
|
|
|
|||
|
|
This is called `options` in {manpage}`mount(8)` and `fs_mntops` in {manpage}`fstab(5)`
|
|||
|
|
|
|||
|
|
Some options that can be used for all mounts are documented in {manpage}`mount(8)` under `FILESYSTEM-INDEPENDENT MOUNT OPTIONS`.
|
|||
|
|
|
|||
|
|
Options that systemd understands are documented in {manpage}`systemd.mount(5)` under `FSTAB`.
|
|||
|
|
|
|||
|
|
Each filesystem supports additional options, see the docs for that filesystem.
|
|||
|
|
'';
|
|||
|
|
type = types.nonEmptyListOf nonEmptyStr;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
depends = mkOption {
|
|||
|
|
default = [ ];
|
|||
|
|
example = [ "/persist" ];
|
|||
|
|
type = types.listOf nonEmptyWithoutTrailingSlash;
|
|||
|
|
description = ''
|
|||
|
|
List of paths that should be mounted before this one. This filesystem's
|
|||
|
|
{option}`device` and {option}`mountPoint` are always
|
|||
|
|
checked and do not need to be included explicitly. If a path is added
|
|||
|
|
to this list, any other filesystem whose mount point is a parent of
|
|||
|
|
the path will be mounted before this filesystem. The paths do not need
|
|||
|
|
to actually be the {option}`mountPoint` of some other filesystem.
|
|||
|
|
|
|||
|
|
This is useful for mounts which require keys and/or configuration files residing on another filesystem.
|
|||
|
|
'';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
config = {
|
|||
|
|
device = mkIf (elem config.fsType specialFSTypes) (mkDefault config.fsType);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
fileSystemOpts =
|
|||
|
|
{ config, ... }:
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
options = {
|
|||
|
|
|
|||
|
|
label = mkOption {
|
|||
|
|
default = null;
|
|||
|
|
example = "root-partition";
|
|||
|
|
type = types.nullOr nonEmptyStr;
|
|||
|
|
description = ''
|
|||
|
|
Label of the device. This simply sets {option}`device` to
|
|||
|
|
`/dev/disk/by-id/''${label}`. Note that devices will not
|
|||
|
|
have a label unless they contain a filesystem which
|
|||
|
|
supports labels, such as ext4 or fat32.
|
|||
|
|
'';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
autoFormat = mkOption {
|
|||
|
|
default = false;
|
|||
|
|
type = types.bool;
|
|||
|
|
description = ''
|
|||
|
|
If the device does not currently contain a filesystem (as
|
|||
|
|
determined by {command}`blkid`), then automatically
|
|||
|
|
format it with the filesystem type specified in
|
|||
|
|
{option}`fsType`. Use with caution.
|
|||
|
|
'';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
formatOptions = mkOption {
|
|||
|
|
visible = false;
|
|||
|
|
type = types.unspecified;
|
|||
|
|
default = null;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
autoResize = mkOption {
|
|||
|
|
default = false;
|
|||
|
|
type = types.bool;
|
|||
|
|
description = ''
|
|||
|
|
If set, the filesystem is grown to its maximum size before
|
|||
|
|
being mounted. (This is typically the size of the containing
|
|||
|
|
partition.) This is currently only supported for ext2/3/4
|
|||
|
|
filesystems that are mounted during early boot.
|
|||
|
|
'';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
noCheck = mkOption {
|
|||
|
|
default = false;
|
|||
|
|
type = types.bool;
|
|||
|
|
description = "Disable running fsck on this filesystem.";
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
config.device = mkIf (config.label != null) (mkDefault "/dev/disk/by-label/${escape config.label}");
|
|||
|
|
|
|||
|
|
config.options =
|
|||
|
|
let
|
|||
|
|
inInitrd = utils.fsNeededForBoot config;
|
|||
|
|
in
|
|||
|
|
mkMerge [
|
|||
|
|
(mkIf config.autoResize [ "x-systemd.growfs" ])
|
|||
|
|
(mkIf config.autoFormat [ "x-systemd.makefs" ])
|
|||
|
|
(mkIf (utils.fsNeededForBoot config) [ "x-initrd.mount" ])
|
|||
|
|
(mkIf
|
|||
|
|
# With scripted stage 1, depends is implemented by sorting 'config.system.build.fileSystems'
|
|||
|
|
(lib.length config.depends > 0 && (inInitrd -> moduleArgs.config.boot.initrd.systemd.enable))
|
|||
|
|
(map (x: "x-systemd.requires-mounts-for=${optionalString inInitrd "/sysroot"}${x}") config.depends)
|
|||
|
|
)
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
# Makes sequence of `specialMount device mountPoint options fsType` commands.
|
|||
|
|
# `systemMount` should be defined in the sourcing script.
|
|||
|
|
makeSpecialMounts =
|
|||
|
|
mounts:
|
|||
|
|
pkgs.writeText "mounts.sh" (
|
|||
|
|
concatMapStringsSep "\n" (mount: ''
|
|||
|
|
specialMount "${mount.device}" "${mount.mountPoint}" "${concatStringsSep "," mount.options}" "${mount.fsType}"
|
|||
|
|
'') mounts
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
makeFstabEntries =
|
|||
|
|
let
|
|||
|
|
fsToSkipCheck = [
|
|||
|
|
"none"
|
|||
|
|
"auto"
|
|||
|
|
"overlay"
|
|||
|
|
"iso9660"
|
|||
|
|
"bindfs"
|
|||
|
|
"udf"
|
|||
|
|
"btrfs"
|
|||
|
|
"zfs"
|
|||
|
|
"tmpfs"
|
|||
|
|
"bcachefs"
|
|||
|
|
"nfs"
|
|||
|
|
"nfs4"
|
|||
|
|
"nilfs2"
|
|||
|
|
"vboxsf"
|
|||
|
|
"squashfs"
|
|||
|
|
"glusterfs"
|
|||
|
|
"apfs"
|
|||
|
|
"9p"
|
|||
|
|
"cifs"
|
|||
|
|
"prl_fs"
|
|||
|
|
"vmhgfs"
|
|||
|
|
]
|
|||
|
|
++ lib.optionals (!config.boot.initrd.checkJournalingFS) [
|
|||
|
|
"ext3"
|
|||
|
|
"ext4"
|
|||
|
|
"reiserfs"
|
|||
|
|
"xfs"
|
|||
|
|
"jfs"
|
|||
|
|
"f2fs"
|
|||
|
|
];
|
|||
|
|
isBindMount = fs: builtins.elem "bind" fs.options;
|
|||
|
|
skipCheck =
|
|||
|
|
fs: fs.noCheck || fs.device == "none" || builtins.elem fs.fsType fsToSkipCheck || isBindMount fs;
|
|||
|
|
in
|
|||
|
|
fstabFileSystems:
|
|||
|
|
{ }:
|
|||
|
|
concatMapStrings (
|
|||
|
|
fs:
|
|||
|
|
(
|
|||
|
|
if fs.device != null then
|
|||
|
|
escape fs.device
|
|||
|
|
else
|
|||
|
|
throw "No device specified for mount point ‘${fs.mountPoint}’."
|
|||
|
|
)
|
|||
|
|
+ " "
|
|||
|
|
+ escape fs.mountPoint
|
|||
|
|
+ " "
|
|||
|
|
+ fs.fsType
|
|||
|
|
+ " "
|
|||
|
|
+ escape (builtins.concatStringsSep "," fs.options)
|
|||
|
|
+ " 0 "
|
|||
|
|
+ (
|
|||
|
|
if skipCheck fs then
|
|||
|
|
"0"
|
|||
|
|
else if fs.mountPoint == "/" then
|
|||
|
|
"1"
|
|||
|
|
else
|
|||
|
|
"2"
|
|||
|
|
)
|
|||
|
|
+ "\n"
|
|||
|
|
) fstabFileSystems;
|
|||
|
|
|
|||
|
|
initrdFstab = pkgs.writeText "initrd-fstab" (
|
|||
|
|
makeFstabEntries (filter utils.fsNeededForBoot fileSystems) { }
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
in
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
###### interface
|
|||
|
|
|
|||
|
|
options = {
|
|||
|
|
|
|||
|
|
fileSystems = mkOption {
|
|||
|
|
default = { };
|
|||
|
|
example = literalExpression ''
|
|||
|
|
{
|
|||
|
|
"/".device = "/dev/hda1";
|
|||
|
|
"/data" = {
|
|||
|
|
device = "/dev/hda2";
|
|||
|
|
fsType = "ext3";
|
|||
|
|
options = [ "data=journal" ];
|
|||
|
|
};
|
|||
|
|
"/bigdisk".label = "bigdisk";
|
|||
|
|
}
|
|||
|
|
'';
|
|||
|
|
type = types.attrsOf (
|
|||
|
|
types.submodule [
|
|||
|
|
coreFileSystemOpts
|
|||
|
|
fileSystemOpts
|
|||
|
|
]
|
|||
|
|
);
|
|||
|
|
apply = lib.filterAttrs (_: fs: fs.enable);
|
|||
|
|
description = ''
|
|||
|
|
The file systems to be mounted. It must include an entry for
|
|||
|
|
the root directory (`mountPoint = "/"`). Each
|
|||
|
|
entry in the list is an attribute set with the following fields:
|
|||
|
|
`mountPoint`, `device`,
|
|||
|
|
`fsType` (a file system type recognised by
|
|||
|
|
{command}`mount`; defaults to
|
|||
|
|
`"auto"`), and `options`
|
|||
|
|
(the mount options passed to {command}`mount` using the
|
|||
|
|
{option}`-o` flag; defaults to `[ "defaults" ]`).
|
|||
|
|
|
|||
|
|
Instead of specifying `device`, you can also
|
|||
|
|
specify a volume label (`label`) for file
|
|||
|
|
systems that support it, such as ext2/ext3 (see {command}`mke2fs -L`).
|
|||
|
|
'';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
system.fsPackages = mkOption {
|
|||
|
|
internal = true;
|
|||
|
|
default = [ ];
|
|||
|
|
description = "Packages supplying file system mounters and checkers.";
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
boot.supportedFilesystems = mkOption {
|
|||
|
|
default = { };
|
|||
|
|
example = literalExpression ''
|
|||
|
|
{
|
|||
|
|
btrfs = true;
|
|||
|
|
zfs = lib.mkForce false;
|
|||
|
|
}
|
|||
|
|
'';
|
|||
|
|
type = attrNamesToTrue;
|
|||
|
|
description = ''
|
|||
|
|
Names of supported filesystem types, or an attribute set of file system types
|
|||
|
|
and their state. The set form may be used together with `lib.mkForce` to
|
|||
|
|
explicitly disable support for specific filesystems, e.g. to disable ZFS
|
|||
|
|
with an unsupported kernel.
|
|||
|
|
'';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
boot.specialFileSystems = mkOption {
|
|||
|
|
default = { };
|
|||
|
|
type = types.attrsOf (types.submodule coreFileSystemOpts);
|
|||
|
|
apply = lib.filterAttrs (_: fs: fs.enable);
|
|||
|
|
internal = true;
|
|||
|
|
description = ''
|
|||
|
|
Special filesystems that are mounted very early during boot.
|
|||
|
|
'';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
boot.devSize = mkOption {
|
|||
|
|
default = "5%";
|
|||
|
|
example = "32m";
|
|||
|
|
type = types.str;
|
|||
|
|
description = ''
|
|||
|
|
Size limit for the /dev tmpfs. Look at {manpage}`mount(8)`, tmpfs size option,
|
|||
|
|
for the accepted syntax.
|
|||
|
|
'';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
boot.devShmSize = mkOption {
|
|||
|
|
default = "50%";
|
|||
|
|
example = "256m";
|
|||
|
|
type = types.str;
|
|||
|
|
description = ''
|
|||
|
|
Size limit for the /dev/shm tmpfs. Look at {manpage}`mount(8)`, tmpfs size option,
|
|||
|
|
for the accepted syntax.
|
|||
|
|
'';
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
boot.runSize = mkOption {
|
|||
|
|
default = "25%";
|
|||
|
|
example = "256m";
|
|||
|
|
type = types.str;
|
|||
|
|
description = ''
|
|||
|
|
Size limit for the /run tmpfs. Look at {manpage}`mount(8)`, tmpfs size option,
|
|||
|
|
for the accepted syntax.
|
|||
|
|
'';
|
|||
|
|
};
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
###### implementation
|
|||
|
|
|
|||
|
|
config = {
|
|||
|
|
|
|||
|
|
assertions =
|
|||
|
|
let
|
|||
|
|
ls = sep: concatMapStringsSep sep (x: x.mountPoint);
|
|||
|
|
resizableFSes = [
|
|||
|
|
"ext3"
|
|||
|
|
"ext4"
|
|||
|
|
"btrfs"
|
|||
|
|
"xfs"
|
|||
|
|
];
|
|||
|
|
notAutoResizable = fs: fs.autoResize && !(builtins.elem fs.fsType resizableFSes);
|
|||
|
|
in
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
assertion = !(fileSystems' ? cycle);
|
|||
|
|
message = "The ‘fileSystems’ option can't be topologically sorted: mountpoint dependency path ${ls " -> " fileSystems'.cycle} loops to ${ls ", " fileSystems'.loops}";
|
|||
|
|
}
|
|||
|
|
{
|
|||
|
|
assertion = !(any notAutoResizable fileSystems);
|
|||
|
|
message =
|
|||
|
|
let
|
|||
|
|
fs = head (filter notAutoResizable fileSystems);
|
|||
|
|
in
|
|||
|
|
''
|
|||
|
|
Mountpoint '${fs.mountPoint}': 'autoResize = true' is not supported for 'fsType = "${fs.fsType}"'
|
|||
|
|
${optionalString (fs.fsType == "auto") "fsType has to be explicitly set and"}
|
|||
|
|
only the following support it: ${lib.concatStringsSep ", " resizableFSes}.
|
|||
|
|
'';
|
|||
|
|
}
|
|||
|
|
{
|
|||
|
|
assertion = !(any (fs: fs.formatOptions != null) fileSystems);
|
|||
|
|
message = ''
|
|||
|
|
'fileSystems.<name>.formatOptions' has been removed, since
|
|||
|
|
systemd-makefs does not support any way to provide formatting
|
|||
|
|
options.
|
|||
|
|
'';
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
++ lib.map (fs: {
|
|||
|
|
assertion = fs.label != null -> fs.device == "/dev/disk/by-label/${escape fs.label}";
|
|||
|
|
message = ''
|
|||
|
|
The filesystem with mount point ${fs.mountPoint} has its label and device set to inconsistent values:
|
|||
|
|
label: ${toString fs.label}
|
|||
|
|
device: ${toString fs.device}
|
|||
|
|
'filesystems.<name>.label' and 'filesystems.<name>.device' are mutually exclusive. Please set only one.
|
|||
|
|
'';
|
|||
|
|
}) fileSystems;
|
|||
|
|
|
|||
|
|
# Export for use in other modules
|
|||
|
|
system.build.fileSystems = fileSystems;
|
|||
|
|
system.build.earlyMountScript = makeSpecialMounts (toposort fsBefore (
|
|||
|
|
attrValues config.boot.specialFileSystems
|
|||
|
|
)).result;
|
|||
|
|
|
|||
|
|
boot.supportedFilesystems = map (fs: fs.fsType) fileSystems;
|
|||
|
|
|
|||
|
|
# Add the mount helpers to the system path so that `mount' can find them.
|
|||
|
|
system.fsPackages = [ pkgs.dosfstools ];
|
|||
|
|
|
|||
|
|
environment.systemPackages = config.system.fsPackages;
|
|||
|
|
|
|||
|
|
environment.etc.fstab.text =
|
|||
|
|
let
|
|||
|
|
swapOptions =
|
|||
|
|
sw:
|
|||
|
|
concatStringsSep "," (
|
|||
|
|
sw.options
|
|||
|
|
++ optional (sw.priority != null) "pri=${toString sw.priority}"
|
|||
|
|
++
|
|||
|
|
optional (sw.discardPolicy != null)
|
|||
|
|
"discard${optionalString (sw.discardPolicy != "both") "=${toString sw.discardPolicy}"}"
|
|||
|
|
);
|
|||
|
|
in
|
|||
|
|
''
|
|||
|
|
# This is a generated file. Do not edit!
|
|||
|
|
#
|
|||
|
|
# To make changes, edit the fileSystems and swapDevices NixOS options
|
|||
|
|
# in your /etc/nixos/configuration.nix file.
|
|||
|
|
#
|
|||
|
|
# <file system> <mount point> <type> <options> <dump> <pass>
|
|||
|
|
|
|||
|
|
# Filesystems.
|
|||
|
|
${makeFstabEntries fileSystems { }}
|
|||
|
|
|
|||
|
|
${optionalString (config.swapDevices != [ ]) "# Swap devices."}
|
|||
|
|
${flip concatMapStrings config.swapDevices (sw: "${sw.realDevice} none swap ${swapOptions sw}\n")}
|
|||
|
|
'';
|
|||
|
|
|
|||
|
|
boot.initrd.systemd.storePaths = [ initrdFstab ];
|
|||
|
|
boot.initrd.systemd.managerEnvironment.SYSTEMD_SYSROOT_FSTAB = initrdFstab;
|
|||
|
|
boot.initrd.systemd.services.initrd-parse-etc.environment.SYSTEMD_SYSROOT_FSTAB = initrdFstab;
|
|||
|
|
|
|||
|
|
# Provide a target that pulls in all filesystems.
|
|||
|
|
systemd.targets.fs = {
|
|||
|
|
description = "All File Systems";
|
|||
|
|
wants = [
|
|||
|
|
"local-fs.target"
|
|||
|
|
"remote-fs.target"
|
|||
|
|
];
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
systemd.tmpfiles.rules = [
|
|||
|
|
"d /run/keys 0750 root ${toString config.ids.gids.keys}"
|
|||
|
|
"z /run/keys 0750 root ${toString config.ids.gids.keys}"
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
# Sync mount options with systemd's src/core/mount-setup.c: mount_table.
|
|||
|
|
boot.specialFileSystems = {
|
|||
|
|
# To hold secrets that shouldn't be written to disk
|
|||
|
|
"/run/keys" = {
|
|||
|
|
fsType = "ramfs";
|
|||
|
|
options = [
|
|||
|
|
"nosuid"
|
|||
|
|
"nodev"
|
|||
|
|
"mode=750"
|
|||
|
|
];
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
// optionalAttrs (!config.boot.isContainer) {
|
|||
|
|
# systemd-nspawn populates /sys by itself, and remounting it causes all
|
|||
|
|
# kinds of weird issues (most noticeably, waiting for host disk device
|
|||
|
|
# nodes).
|
|||
|
|
"/sys" = {
|
|||
|
|
fsType = "sysfs";
|
|||
|
|
options = [
|
|||
|
|
"nosuid"
|
|||
|
|
"noexec"
|
|||
|
|
"nodev"
|
|||
|
|
];
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
// optionalAttrs (!config.boot.isNspawnContainer) {
|
|||
|
|
"/proc" = {
|
|||
|
|
fsType = "proc";
|
|||
|
|
options = [
|
|||
|
|
"nosuid"
|
|||
|
|
"noexec"
|
|||
|
|
"nodev"
|
|||
|
|
];
|
|||
|
|
};
|
|||
|
|
"/run" = {
|
|||
|
|
fsType = "tmpfs";
|
|||
|
|
options = [
|
|||
|
|
"nosuid"
|
|||
|
|
"nodev"
|
|||
|
|
"strictatime"
|
|||
|
|
"mode=755"
|
|||
|
|
"size=${config.boot.runSize}"
|
|||
|
|
];
|
|||
|
|
};
|
|||
|
|
"/dev" = {
|
|||
|
|
fsType = "devtmpfs";
|
|||
|
|
options = [
|
|||
|
|
"nosuid"
|
|||
|
|
"strictatime"
|
|||
|
|
"mode=755"
|
|||
|
|
"size=${config.boot.devSize}"
|
|||
|
|
];
|
|||
|
|
};
|
|||
|
|
"/dev/shm" = {
|
|||
|
|
fsType = "tmpfs";
|
|||
|
|
options = [
|
|||
|
|
"nosuid"
|
|||
|
|
"nodev"
|
|||
|
|
"strictatime"
|
|||
|
|
"mode=1777"
|
|||
|
|
"size=${config.boot.devShmSize}"
|
|||
|
|
];
|
|||
|
|
};
|
|||
|
|
"/dev/pts" = {
|
|||
|
|
fsType = "devpts";
|
|||
|
|
options = [
|
|||
|
|
"nosuid"
|
|||
|
|
"noexec"
|
|||
|
|
"mode=620"
|
|||
|
|
"ptmxmode=0666"
|
|||
|
|
"gid=${toString config.ids.gids.tty}"
|
|||
|
|
];
|
|||
|
|
};
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
}
|