greenhouse

kore

my public infrastructure monorepo

git clone [email protected]:kore.git

kore / nixos / features / global.nix192 lines · 4537B · raw

1{ inputs, outputs, config, lib, pkgs, utils, ... }:
2
3# Policy for every host. Values under mkForce are invariants: roles and
4# hosts must not weaken them.
5let
6  impermanence = config.kore.impermanence.enable;
7  rollback = impermanence && config ? disko && config.disko.devices.disk ? main;
8
9  rootDevice = config.fileSystems."/".device;
10  rootUnit = "${utils.escapeSystemdPath rootDevice}.device";
11in {
12  imports = [ inputs.impermanence.nixosModules.impermanence ];
13
14  i18n = {
15    defaultLocale = "en_US.UTF-8";
16    supportedLocales = [ "en_US.UTF-8/UTF-8" ];
17  };
18  time.timeZone = "UTC";
19
20  documentation = {
21    nixos.enable = false;
22    doc.enable = false;
23    info.enable = false;
24  };
25
26  nix = {
27    package = pkgs.nixVersions.latest;
28
29    gc = {
30      automatic = true;
31      dates = "daily";
32      options = "--delete-older-than 7d";
33    };
34
35    settings = {
36      keep-outputs = false;
37      keep-derivations = false;
38      auto-optimise-store = true;
39
40      trusted-users = [ "root" "@wheel" ];
41      experimental-features = [ "nix-command" "flakes" ];
42    };
43  };
44
45  nixpkgs = {
46    overlays = builtins.attrValues outputs.overlays;
47
48    config = {
49      allowUnfree = lib.mkForce false;
50      allowBroken = lib.mkForce false;
51    };
52  };
53
54  system.tools = {
55    nixos-build-vms.enable = false;
56    nixos-enter.enable = false;
57    nixos-generate-config.enable = false;
58    nixos-install.enable = false;
59    nixos-option.enable = false;
60  };
61
62  networking = {
63    domain = "lostduk.com";
64
65    useDHCP = true;
66    enableIPv6 = lib.mkForce false;
67
68    firewall = {
69      enable = lib.mkForce true;
70      allowPing = lib.mkForce false;
71      allowedTCPPorts = [];
72      allowedUDPPorts = [];
73    };
74  };
75
76  services = {
77    pcscd.enable = true;
78
79    openssh = {
80      enable = true;
81      settings = {
82        PermitRootLogin = "no";
83        PasswordAuthentication = false;
84        KbdInteractiveAuthentication = false;
85      };
86      hostKeys = [{
87        path = "${lib.optionalString impermanence "/persist"}/etc/ssh/ssh_host_ed25519_key";
88        type = "ed25519";
89      }];
90    };
91  };
92
93  security = {
94    protectKernelImage = true;
95
96    audit = {
97      enable = true;
98      rules = [ "-a exit,always -F arch=b64 -S execve" ];
99    };
100
101    sudo = {
102      execWheelOnly = true;
103      wheelNeedsPassword = lib.mkForce true;
104    };
105
106    auditd.enable = true;
107    pam.sshAgentAuth.enable = true;
108  };
109
110  users = {
111    mutableUsers = lib.mkForce false;
112
113    users.root.hashedPassword = lib.mkForce "!";
114  };
115
116  environment = {
117    defaultPackages = lib.mkForce [];
118
119    persistence."/persist" = {
120      enable = impermanence;
121      hideMounts = false;
122
123      directories = [
124        "/srv"
125        "/var/lib/nixos"
126        "/var/lib/systemd"
127      ];
128    };
129  };
130
131  programs.nano.enable = false;
132
133  fileSystems = lib.mkIf impermanence {
134    "/persist".neededForBoot = true;
135  };
136
137  system.activationScripts.persistent-dirs = lib.mkIf impermanence {
138    deps = [ "users" ];
139    text =
140      let
141        mkHomePersist = user: lib.optionalString user.createHome ''
142          mkdir -p /persist${user.home}
143          chown ${user.name}:${user.group} /persist${user.home}
144          chmod ${user.homeMode} /persist${user.home}
145        '';
146      in
147        lib.concatLines (map mkHomePersist (lib.attrValues config.users.users));
148  };
149
150  assertions = [{
151    assertion = rollback -> config.boot.initrd.systemd.enable;
152    message = "kore: root rollback needs boot.initrd.systemd.enable";
153  }];
154
155  boot.initrd = lib.mkIf rollback {
156    supportedFilesystems = [ "btrfs" ];
157
158    systemd.services.wipe-root = {
159      wantedBy = [ "initrd.target" ];
160      requires = [ rootUnit ];
161      after = [ rootUnit ];
162      before = [ "sysroot.mount" ];
163      unitConfig.DefaultDependencies = "no";
164      serviceConfig = {
165        Type = "oneshot";
166        RemainAfterExit = true;
167      };
168      script = ''
169        mkdir -p /tmp
170        MNTPOINT=$(mktemp -d)
171        (
172          mount ${rootDevice} "$MNTPOINT"
173          trap 'umount "$MNTPOINT"' EXIT
174
175          if [[ -e $MNTPOINT/@ ]]; then
176            echo "Backing up root..."
177            mkdir -p $MNTPOINT/old_roots
178            mv "$MNTPOINT/@" "$MNTPOINT/old_roots/@_$(date "+%Y-%m-%-d_%H:%M:%S")"
179          fi
180
181          echo "Deleting 7+ days old roots..."
182          find "$MNTPOINT/old_roots" -mindepth 1 -maxdepth 1 \
183            -mtime +7 \
184            -exec btrfs sub del -R {} +
185
186          echo "Creating new root..."
187          btrfs sub cre "$MNTPOINT/@"
188        )
189      '';
190    };
191  };
192}