disko: support multiple disks
This commit is contained in:
parent
31d255b388
commit
7e3a98d68f
|
@ -1,4 +1,4 @@
|
||||||
{ config, pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [ ./hardware-configuration.nix ];
|
imports = [ ./hardware-configuration.nix ];
|
||||||
|
@ -9,12 +9,12 @@
|
||||||
autoUpdate = true;
|
autoUpdate = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
disko = {
|
disko.disks = [ {
|
||||||
enableCeph = false;
|
device = "/dev/sda";
|
||||||
enableLuks = false;
|
name = "";
|
||||||
name = config.networking.hostName;
|
withCeph = false;
|
||||||
rootDisk = "/dev/sda";
|
withLuks = false;
|
||||||
};
|
} ];
|
||||||
|
|
||||||
nix.settings = {
|
nix.settings = {
|
||||||
cores = 4;
|
cores = 4;
|
||||||
|
|
|
@ -4,72 +4,91 @@ let
|
||||||
cfg = config.disko;
|
cfg = config.disko;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.disko = {
|
options.disko.disks = lib.mkOption {
|
||||||
name = lib.mkOption {
|
description = lib.mdDoc "Disk names to format.";
|
||||||
type = lib.types.str;
|
type = with lib.types; listOf (submodule (_: {
|
||||||
example = "chaos";
|
options = {
|
||||||
description = "Machine name used in eg zpool name.";
|
device = lib.mkOption {
|
||||||
};
|
type = lib.types.str;
|
||||||
|
default = null;
|
||||||
|
example = "/dev/sda";
|
||||||
|
description = "Path of the disk.";
|
||||||
|
};
|
||||||
|
|
||||||
rootDisk = lib.mkOption {
|
name = lib.mkOption {
|
||||||
type = with lib.types; nullOr str;
|
type = lib.types.str;
|
||||||
default = null;
|
default = null;
|
||||||
example = "/dev/sda";
|
example = "ssd0";
|
||||||
description = "Path of the root disk.";
|
description = "Name of the disk.";
|
||||||
};
|
};
|
||||||
|
|
||||||
enableCeph = lib.mkOption {
|
withBoot = lib.mkOption {
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
default = true;
|
default = true;
|
||||||
description = "Wether to include a ceph on the root disk.";
|
description = "Wether to include a boot partition.";
|
||||||
};
|
};
|
||||||
|
|
||||||
enableLuks = lib.mkOption {
|
withCeph = lib.mkOption {
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
default = true;
|
default = true;
|
||||||
description = "Wether to encrypt the root disk.";
|
description = "Wether to include a ceph partition.";
|
||||||
};
|
};
|
||||||
|
|
||||||
enableZfs = lib.mkOption {
|
withLuks = lib.mkOption {
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
default = true;
|
default = true;
|
||||||
description = "Wether to include a zfs on the root disk.";
|
description = "Wether to encrypt the paritions.";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
withZfs = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Wether to include a zfs parition.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
default = [ ];
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
assertions = [
|
assertions = map
|
||||||
{
|
(disk: [
|
||||||
assertion = cfg.enableCeph || cfg.enableZfs;
|
{
|
||||||
message = "Must enable ceph or zfs!";
|
assertion = disk.withCeph || disk.withZfs;
|
||||||
}
|
message = "Must enable ceph or zfs!";
|
||||||
{
|
}
|
||||||
assertion = cfg.enableCeph -> cfg.enableLuks;
|
{
|
||||||
message = "Ceph requires Luks!";
|
assertion = disk.withCeph -> disk.withLuks;
|
||||||
}
|
message = "Ceph requires Luks!";
|
||||||
];
|
}
|
||||||
|
])
|
||||||
|
(lib.attrNames cfg.disks);
|
||||||
|
|
||||||
disko = {
|
disko = {
|
||||||
devices =
|
devices = lib.mkIf (cfg.disks != [ ]) (lib.head (map
|
||||||
let
|
(disk:
|
||||||
rootSize = 200;
|
let
|
||||||
zfs = {
|
diskName = if disk.name != "" then "-${disk.name}" else "";
|
||||||
size = if (!cfg.enableCeph) then "100%FREE" else "${toString rootSize}GiB";
|
luksName = "crypt-${config.networking.hostName}${diskName}";
|
||||||
content = {
|
rootSize = 200;
|
||||||
pool = cfg.name;
|
vgName = "lvm-${config.networking.hostName}${diskName}";
|
||||||
type = "zfs";
|
zfs = {
|
||||||
|
size = if (!disk.withCeph) then "100%FREE" else "${toString rootSize}GiB";
|
||||||
|
content = {
|
||||||
|
pool = disk.name;
|
||||||
|
type = "zfs";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
zfsName = "${config.networking.hostName}${diskName}";
|
||||||
in
|
in
|
||||||
lib.mkIf (cfg.rootDisk != "")
|
({
|
||||||
{
|
disk.${disk.device} = {
|
||||||
disk.${cfg.rootDisk} = {
|
inherit (disk) device;
|
||||||
device = cfg.rootDisk;
|
|
||||||
type = "disk";
|
type = "disk";
|
||||||
content = {
|
content = {
|
||||||
type = "table";
|
type = "table";
|
||||||
format = "gpt";
|
format = "gpt";
|
||||||
partitions = lib.optional cfg.enableZfs
|
partitions = lib.optional disk.withZfs
|
||||||
{
|
{
|
||||||
name = "ESP";
|
name = "ESP";
|
||||||
start = "1MiB";
|
start = "1MiB";
|
||||||
|
@ -83,107 +102,109 @@ in
|
||||||
} ++ [
|
} ++ [
|
||||||
{
|
{
|
||||||
name = "root";
|
name = "root";
|
||||||
start = if cfg.enableZfs then "512MiB" else "1MiB";
|
start = if disk.withZfs then "512MiB" else "1MiB";
|
||||||
end = "100%";
|
end = "100%";
|
||||||
part-type = "primary";
|
part-type = "primary";
|
||||||
content = lib.optionalAttrs cfg.enableLuks
|
content = lib.optionalAttrs disk.withLuks
|
||||||
{
|
{
|
||||||
type = "luks";
|
type = "luks";
|
||||||
name = "crypt-${cfg.name}";
|
name = luksName;
|
||||||
# TODO: add password, otherwise prompt opens
|
# TODO: add password, otherwise prompt opens
|
||||||
keyFile = "/$PWD/keyFile";
|
keyFile = "/$PWD/keyFile";
|
||||||
content = {
|
content = {
|
||||||
type = "lvm_pv";
|
type = "lvm_pv";
|
||||||
vg = "lvm-${cfg.name}";
|
vg = vgName;
|
||||||
};
|
};
|
||||||
} // lib.optionalAttrs (!cfg.enableLuks) zfs.content;
|
} // lib.optionalAttrs (!disk.withLuks) zfs.content;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} // lib.optionalAttrs cfg.enableLuks {
|
} // lib.optionalAttrs disk.withLuks {
|
||||||
lvm_vg."lvm-${cfg.name}" = {
|
lvm_vg.${vgName} = {
|
||||||
type = "lvm_vg";
|
type = "lvm_vg";
|
||||||
lvs = lib.optionalAttrs cfg.enableCeph
|
lvs = lib.optionalAttrs disk.withCeph
|
||||||
{
|
{
|
||||||
# the header is 3650 byte long and substract an additional 446 byte for aligment
|
# TODO: delete old code if this works
|
||||||
# error messages:
|
ceph.size = "100%FREE";
|
||||||
# Volume group "lvm-chaos" has insufficient free space (51195 extents): 51200 required.
|
# the header is 3650 byte long and substract an additional 446 byte for aligment
|
||||||
# Size is not a multiple of 512. Try using 40057405440 or 40057405952.
|
# error messages:
|
||||||
ceph.size =
|
# Volume group "lvm-chaos" has insufficient free space (51195 extents): 51200 required.
|
||||||
let
|
# Size is not a multiple of 512. Try using 40057405440 or 40057405952.
|
||||||
# convert GiB to bytes
|
# ceph.size =
|
||||||
rootSizeMiB = rootSize * 1024 * 1024 * 1024;
|
# let
|
||||||
# convert back to MiB and allign to 4 MiB in the process
|
# # convert GiB to bytes
|
||||||
roundToMiB = "/1024/1024/4*4";
|
# rootSizeMiB = rootSize * 1024 * 1024 * 1024;
|
||||||
# substract 512 MiB for /boot and 20 MiB for luks+header+other
|
# # convert back to MiB and allign to 4 MiB in the process
|
||||||
bootOther = "-512-20";
|
# roundToMiB = "/1024/1024/4*4";
|
||||||
in
|
# # substract 512 MiB for /boot and 20 MiB for luks+header+other
|
||||||
"$((($(lsblk /dev/sda --noheadings --nodeps --output SIZE --bytes)-${toString rootSizeMiB})${roundToMiB}${bootOther}))MiB";
|
# bootOther = "-512-20";
|
||||||
} // lib.optionalAttrs cfg.enableZfs { inherit zfs; };
|
# in
|
||||||
};
|
# "$((($(lsblk ${disk.device} --noheadings --nodeps --output SIZE --bytes)-${toString rootSizeMiB})${roundToMiB}${bootOther}))MiB";
|
||||||
} // {
|
} // lib.optionalAttrs disk.withZfs { inherit zfs; };
|
||||||
zpool."${cfg.name}" = {
|
|
||||||
type = "zpool";
|
|
||||||
mountpoint = null;
|
|
||||||
mountRoot = "/mnt";
|
|
||||||
rootFsOptions.acltype = "posixacl";
|
|
||||||
options = {
|
|
||||||
ashift = "12";
|
|
||||||
autotrim = "on";
|
|
||||||
};
|
};
|
||||||
datasets =
|
} // {
|
||||||
let
|
zpool.${zfsName} = {
|
||||||
dataset = mountpoint: {
|
type = "zpool";
|
||||||
options = {
|
mountpoint = null;
|
||||||
canmount = "on";
|
rootFsOptions.acltype = "posixacl";
|
||||||
compression = "zstd";
|
options = {
|
||||||
dnodesize = "auto";
|
ashift = "12";
|
||||||
normalization = "formD";
|
autotrim = "on";
|
||||||
xattr = "sa";
|
|
||||||
inherit mountpoint;
|
|
||||||
};
|
|
||||||
type = "zfs_fs";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
"data" = dataset "/";
|
|
||||||
"data/etc" = dataset "/etc";
|
|
||||||
"data/home" = dataset "/home";
|
|
||||||
"data/var" = dataset "/var";
|
|
||||||
# used by services.postgresqlBackup and later by restic
|
|
||||||
"data/var/backup" = dataset "/var/backup";
|
|
||||||
"data/var/lib" = dataset "/var/lib";
|
|
||||||
"data/var/log" = dataset "/var/log";
|
|
||||||
"nixos" = {
|
|
||||||
options = {
|
|
||||||
canmount = "off";
|
|
||||||
mountpoint = "none";
|
|
||||||
};
|
|
||||||
type = "zfs_fs";
|
|
||||||
};
|
|
||||||
"nixos/nix" = dataset "/nix";
|
|
||||||
"nixos/nix/store" = {
|
|
||||||
options = {
|
|
||||||
atime = "off";
|
|
||||||
canmount = "on";
|
|
||||||
mountpoint = "/nix/store";
|
|
||||||
};
|
|
||||||
type = "zfs_fs";
|
|
||||||
};
|
|
||||||
"nixos/nix/var" = dataset "/nix/var";
|
|
||||||
"reserved" = {
|
|
||||||
# zfs uses copy on write and requires some free space to delete files when the disk is completely filled
|
|
||||||
options = {
|
|
||||||
canmount = "off";
|
|
||||||
mountpoint = "none";
|
|
||||||
reservation = "5GiB";
|
|
||||||
};
|
|
||||||
type = "zfs_fs";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
datasets =
|
||||||
};
|
let
|
||||||
|
dataset = mountpoint: {
|
||||||
|
options = {
|
||||||
|
canmount = "on";
|
||||||
|
compression = "zstd";
|
||||||
|
dnodesize = "auto";
|
||||||
|
normalization = "formD";
|
||||||
|
xattr = "sa";
|
||||||
|
inherit mountpoint;
|
||||||
|
};
|
||||||
|
type = "zfs_fs";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
"data" = dataset "/";
|
||||||
|
"data/etc" = dataset "/etc";
|
||||||
|
"data/home" = dataset "/home";
|
||||||
|
"data/var" = dataset "/var";
|
||||||
|
# used by services.postgresqlBackup and later by restic
|
||||||
|
"data/var/backup" = dataset "/var/backup";
|
||||||
|
"data/var/lib" = dataset "/var/lib";
|
||||||
|
"data/var/log" = dataset "/var/log";
|
||||||
|
"nixos" = {
|
||||||
|
options = {
|
||||||
|
canmount = "off";
|
||||||
|
mountpoint = "none";
|
||||||
|
};
|
||||||
|
type = "zfs_fs";
|
||||||
|
};
|
||||||
|
"nixos/nix" = dataset "/nix";
|
||||||
|
"nixos/nix/store" = {
|
||||||
|
options = {
|
||||||
|
atime = "off";
|
||||||
|
canmount = "on";
|
||||||
|
mountpoint = "/nix/store";
|
||||||
|
};
|
||||||
|
type = "zfs_fs";
|
||||||
|
};
|
||||||
|
"nixos/nix/var" = dataset "/nix/var";
|
||||||
|
"reserved" = {
|
||||||
|
# zfs uses copy on write and requires some free space to delete files when the disk is completely filled
|
||||||
|
options = {
|
||||||
|
canmount = "off";
|
||||||
|
mountpoint = "none";
|
||||||
|
reservation = "5GiB";
|
||||||
|
};
|
||||||
|
type = "zfs_fs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}))
|
||||||
|
cfg.disks));
|
||||||
# we use our own hardware-configuration.nix
|
# we use our own hardware-configuration.nix
|
||||||
enableConfig = false;
|
enableConfig = false;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue