diff --git a/machines/gerd.nix b/machines/gerd.nix index d2b585a..8e7d583 100644 --- a/machines/gerd.nix +++ b/machines/gerd.nix @@ -4,13 +4,7 @@ let sources = import ./../shared/sources/sources.nix; in { imports = [ - (modulesPath + "/installer/scan/not-detected.nix") - (modulesPath + "/profiles/qemu-guest.nix") - (sources.disko + "/module.nix") - ./../shared/modules - ./../shared/platforms/hetzner.nix - - ./gerd/disk-zfs.nix + ./../shared ./../shared/applications/server/nginx.nix ./../shared/applications/state/ssh.nix @@ -22,41 +16,29 @@ in { networking.hostName = "gerd"; networking.hostId = "e1166ac9"; boot.loader.grub = { - # no need to set devices, disko will add all devices that have a EF02 partition to the list already - # devices = [ ]; efiSupport = true; efiInstallAsRemovable = true; }; - services.openssh.enable = true; mine = { state.enable = true; + disks = { + disk = "/dev/sda"; + pools.rpool.datasets = { + "safe/svcs/forgejo" = { mountpoint = "/srv/forgejo"; extra.options.quota = "5G"; }; + }; + }; + ssh-on-boot.enable = true; - platforms.hetzner.network.address = [ - "65.108.221.240/32" - "2a01:4f9:c012:743e::1/64" - ]; - }; - - services.teeworlds = { + platforms.hetzner = { enable = true; - openPorts = true; + network.address = [ + "65.108.221.240/32" + "2a01:4f9:c012:743e::1/64" + ]; + }; }; - boot.initrd.postDeviceCommands = lib.mkAfter '' - zfs rollback -r rpool/root@blank - ''; - - environment.systemPackages = with pkgs; [ - vim - jq - ]; - - users.users.root.openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPuma8g+U8Wh+4mLvZoV9V+ngPqxjuIG4zhsbaTeXq65 eyjhb@chronos" - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGee4uz+HDOj4Y4ANOhWJhoc4mMLP1gz6rpKoMueQF2J rendal@popper" - ]; - system.stateVersion = "24.05"; } diff --git a/machines/gerd/disk-zfs.nix b/machines/gerd/disk-zfs.nix deleted file mode 100644 index 843327c..0000000 --- a/machines/gerd/disk-zfs.nix +++ /dev/null @@ -1,85 +0,0 @@ -{ lib, ... }: - -let - makeZFSDatasets = datasets: (lib.mapAttrs' (n: v: lib.nameValuePair v.dataset ({ - type = "zfs_fs"; - mountpoint = n; - options.mountpoint = "legacy"; - } // (if v ? extra then v.extra else {}))) datasets); -in { - disko.devices = { - disk.disk1 = { - type = "disk"; - device = lib.mkDefault "/dev/sda"; - content = { - type = "gpt"; - partitions = { - boot = { - name = "boot"; - size = "1M"; - type = "EF02"; - }; - esp = { - name = "ESP"; - size = "500M"; - type = "EF00"; - content = { - type = "filesystem"; - format = "vfat"; - mountpoint = "/boot"; - }; - }; - - luks = { - size = "100%"; - content = { - type = "luks"; - name = "cryptroot"; - settings.allowDiscards = true; - # passwordFile = "/tmp/luks.pass"; - - content = { - type = "zfs"; - pool = "rpool"; - }; - }; - }; - }; - }; - }; - - zpool = { - rpool = { - type = "zpool"; - # rootFsOptions.compression = "zstd"; - rootFsOptions = { - compression = "on"; - atime = "off"; - acltype = "posixacl"; - xattr = "sa"; - - # test - # "com.sun:auto-snapshot" = "false"; - # "com.klarasystems:vdev_zaps_v2" = "false"; - }; - - datasets = let - baseDatasets = { - "/" = { dataset = "root"; extra = { postCreateHook = "zfs snapshot rpool/root@blank"; }; }; - "/nix".dataset = "local/nix"; - "/state/stash".dataset = "local/stash"; - "/state/home".dataset = "safe/home"; - "/state/root".dataset = "safe/persistent"; - - # extra datasets - "/srv/forgejo" = { dataset = "safe/svcs/forgejo"; extra.options.quota = "5G"; }; - }; - in (makeZFSDatasets baseDatasets); - }; - }; - }; - - fileSystems."/state/root".neededForBoot = true; - fileSystems."/state/home".neededForBoot = true; - fileSystems."/state/stash".neededForBoot = true; -} diff --git a/machines/gerd/zrepl.nix b/machines/gerd/zrepl.nix deleted file mode 100644 index 3ce74bd..0000000 --- a/machines/gerd/zrepl.nix +++ /dev/null @@ -1,35 +0,0 @@ -{ - services.zrepl = { - enable = true; - settings.jobs = [ - { - type = "push"; - name = "safesnapshots"; - - filesystems = [ - "rpool/safe<" - ]; - - snapshotting = { - type = "periodic"; - interval = "5m"; - prefix = "zrepl_"; - }; - - pruning = { - keep_sender = [ - { - type = "grid"; - regex = "^zrepl_.*"; - - # 1. keep all snapshots for 30 minutes - # 2. keep one every 15 minutes for 2 hours - # 3. keep one every hour for 1 day - grid = "1x30m(keep=all) | 8x15m | 14x1d"; - } - ]; - }; - } - ]; - }; -} diff --git a/shared/base/common-config.nix b/shared/base/common-config.nix new file mode 100644 index 0000000..63aea17 --- /dev/null +++ b/shared/base/common-config.nix @@ -0,0 +1,52 @@ +{ + services = { + openssh = { + enable = true; + openFirewall = true; + settings.PasswordAuthentication = false; + }; + + journald.extraConfig = "SystemMaxUse=100M"; + }; + + nix = { + settings.auto-optimise-store = true; + gc = { + automatic = true; + options = "--delete-older-than 7d"; + dates = "daily"; + }; + }; + + # clean on boot + boot.tmp.cleanOnBoot = true; + + # enable doas instead of sudo + security = { + sudo.enable = false; + + doas = { + enable = true; + extraRules = [{ + groups = [ "wheel" ]; + persist = true; + }]; + }; + }; + + # always allow unfree + nixpkgs.config.allowUnfree = true; + environment.variables = { + NIXPKGS_ALLOW_UNFREE = "1"; + }; + + # enable nftables based firewall + networking.nftables = { + enable = true; + }; + + users.users.root.openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPuma8g+U8Wh+4mLvZoV9V+ngPqxjuIG4zhsbaTeXq65 eyjhb@chronos" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGee4uz+HDOj4Y4ANOhWJhoc4mMLP1gz6rpKoMueQF2J rendal@popper" + ]; +} diff --git a/shared/default.nix b/shared/default.nix new file mode 100644 index 0000000..25ef441 --- /dev/null +++ b/shared/default.nix @@ -0,0 +1,7 @@ +{ + imports = [ + ./base/common-config.nix + ./platforms + ./modules + ]; +} diff --git a/shared/modules/default.nix b/shared/modules/default.nix index 4736e64..5623c73 100644 --- a/shared/modules/default.nix +++ b/shared/modules/default.nix @@ -1,5 +1,6 @@ { imports = [ + ./disko.nix ./state.nix ./ssh-luks-zfs-on-boot.nix ./easy-zfs-mounts.nix diff --git a/shared/modules/disko.nix b/shared/modules/disko.nix new file mode 100644 index 0000000..613705a --- /dev/null +++ b/shared/modules/disko.nix @@ -0,0 +1,234 @@ +{ config, lib, ... }: + +with lib; + +# default pool for root device is named rpool, cannot be changed atm. + +# IDEA +# mine.disks.root = "/dev/sda1"; +# mine.disks.pools.rpool.device = "/dev/disk/...."; +# mine.disks.pools.rpool.createDisk = false; +# mine.disks.pools.rpool.extra = {}; +# mine.disks.pools.rpool.datasets = { "local/nix" = { mountpoint = "/nix/store"; extra = {}; }; }; + +let + cfg = config.mine.disks; + + datasetOpts = { name, config, ... }: { + options = { + name = lib.mkOption { + type = types.str; + default = name; + description = "The name of the name dataset"; + }; + + mountpoint = lib.mkOption { + type = types.nullOr types.str; + description = "Where to mount the ZFS dataset"; + }; + + extra = lib.mkOption { + type = types.attrsOf types.anything; + default = {}; + }; + }; + }; + + poolOpts = { name, config, ... }: { + options = { + name = lib.mkOption { + type = types.str; + default = name; + description = "The name of the zfs pool, defaults to name"; + }; + + diskoDiskName = lib.mkOption { + type = types.str; + default = "disk-${name}"; + description = "The name of the disk attribute in disko, defaults to disk-"; + }; + + device = lib.mkOption { + type = types.nullOr types.str; + default = null; + description = "Device to use for the pool (needed if the pool should be created)"; + }; + + createDisk = lib.mkOption { + type = types.bool; + default = true; + description = "Indicates if the disk should be created (only set to false for the root)"; + }; + + extra = lib.mkOption { + type = types.attrsOf types.anything; + default = {}; + }; + + datasets = mkOption { + type = types.attrsOf (types.submodule datasetOpts); + default = {}; + }; + }; + }; + + sources = import ./../sources/sources.nix; +in { + imports = [ + (sources.disko + "/module.nix") + ]; + + options.mine.disks = { + disk = mkOption { + type = types.str; + default = "/dev/sda"; + }; + + rollbackOnBoot = mkOption { + type = types.bool; + default = true; + }; + + pools = mkOption { + type = types.attrsOf (types.submodule poolOpts); + default = {}; + }; + }; + + config = { + # default rpool (cannot be changed) + mine.disks.pools.rpool = { + createDisk = false; + + datasets = { + "local/nix".mountpoint = "/nix"; + "root" = { mountpoint = "/"; extra = { postCreateHook = "zfs snapshot rpool/root@blank"; }; }; + "safe/persistent".mountpoint = "/state/root"; + }; + }; + + # state things are needed on BOOT! + fileSystems."${cfg.pools.rpool.datasets."safe/persistent".mountpoint}".neededForBoot = true; + + # rollback on boot! + boot.initrd.postDeviceCommands = lib.mkIf cfg.rollbackOnBoot (lib.mkAfter '' + zfs rollback -r rpool/root@blank + ''); + + disko.devices = { + disk = let + diskPoolsToCreate = lib.filterAttrs (_: v: v.createDisk) cfg.pools; + extraDisks = lib.mapAttrs' (_: v: lib.nameValuePair v.diskoDiskName (lib.recursiveUpdate { + type = "disk"; + device = v.device; + content = { + type = "gpt"; + partitions = { + zfs = { + size = "100%"; + content = { + type = "zfs"; + pool = v.name; + }; + }; + }; + }; + } v.extra)) diskPoolsToCreate; + in { + root = { + type = "disk"; + device = cfg.disk; + content = { + type = "gpt"; + partitions = { + boot = { + name = "boot"; + size = "1M"; + type = "EF02"; + }; + esp = { + name = "ESP"; + size = "500M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + }; + }; + + luks = { + size = "100%"; + content = { + type = "luks"; + name = "cryptroot"; + settings.allowDiscards = true; + + content = { + type = "zfs"; + pool = "rpool"; + }; + }; + }; + }; + }; + }; + } // extraDisks; + + zpool = let + # helper functions + makeZFSDatasets = datasets: (lib.mapAttrs' (n: v: lib.nameValuePair v.name (lib.recursiveUpdate { + type = "zfs_fs"; + mountpoint = v.mountpoint; + options.mountpoint = "legacy"; + } (if v ? extra then v.extra else {}))) datasets); + + mkZFSPool = zfsPool: { + type = "zpool"; + # rootFsOptions.compression = "zstd"; + rootFsOptions = { + compression = "on"; + atime = "off"; + acltype = "posixacl"; + xattr = "sa"; + }; + + datasets = makeZFSDatasets zfsPool.datasets; + }; + in lib.mapAttrs' (n: v: lib.nameValuePair v.name (mkZFSPool v)) cfg.pools; + # { + # rpool = { + # type = "zpool"; + # # rootFsOptions.compression = "zstd"; + # rootFsOptions = { + # compression = "on"; + # atime = "off"; + # acltype = "posixacl"; + # xattr = "sa"; + + # # test + # # "com.sun:auto-snapshot" = "false"; + # # "com.klarasystems:vdev_zaps_v2" = "false"; + # }; + + # datasets = let + # baseDatasets = { + # "/" = { dataset = "root"; extra = { postCreateHook = "zfs snapshot rpool/root@blank"; }; }; + # "/nix".dataset = "local/nix"; + # "/state/stash".dataset = "local/stash"; + # "/state/home".dataset = "safe/home"; + # "/state/root".dataset = "safe/persistent"; + + # # extra datasets + # "/srv/forgejo" = { dataset = "safe/svcs/forgejo"; extra.options.quota = "5G"; }; + # }; + # in (makeZFSDatasets baseDatasets); + # }; + # }; + }; + + # fileSystems."/state/root".neededForBoot = true; + # fileSystems."/state/home".neededForBoot = true; + # fileSystems."/state/stash".neededForBoot = true; + }; +} diff --git a/shared/platforms/default.nix b/shared/platforms/default.nix new file mode 100644 index 0000000..0b022af --- /dev/null +++ b/shared/platforms/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./hetzner.nix + ]; +} diff --git a/shared/platforms/hetzner.nix b/shared/platforms/hetzner.nix index 042893c..766829d 100644 --- a/shared/platforms/hetzner.nix +++ b/shared/platforms/hetzner.nix @@ -10,10 +10,7 @@ let ) attrset; in { options.mine.platforms.hetzner= { - enable = mkOption { - type = types.bool; - default = true; - }; + enable = mkEnableOption "Enable Hetzner platform profile"; network = { address = mkOption {