greenhouse

kore

my public infrastructure monorepo

git clone [email protected]:kore.git

kore / nixos / features / global.nix276 lines · 7105B · raw

1{ inputs, outputs, config, lib, pkgs, utils, modulesPath, ... }:
2
3let
4  impermanence = config.kore.impermanence.enable;
5  rollback = impermanence && config ? disko && config.disko.devices.disk ? main;
6  wsl = config ? wsl && config.wsl.enable;
7
8  rootDevice = config.fileSystems."/".device;
9  rootUnit = "${utils.escapeSystemdPath rootDevice}.device";
10in {
11  imports = [
12    inputs.impermanence.nixosModules.impermanence
13
14    ( modulesPath + "/profiles/minimal.nix" )
15  ];
16
17  i18n = {
18    defaultLocale = "en_US.UTF-8";
19    supportedLocales = [ "en_US.UTF-8/UTF-8" ];
20  };
21  time.timeZone = "UTC";
22
23  nix = {
24    package = pkgs.nixVersions.latest;
25
26    gc = {
27      automatic = true;
28      dates = "daily";
29      options = "--delete-older-than 7d";
30    };
31
32    settings = {
33      keep-outputs = false;
34      keep-derivations = false;
35      auto-optimise-store = true;
36
37      trusted-users = [ "root" "@wheel" ];
38      experimental-features = [ "nix-command" "flakes" ];
39    };
40  };
41
42  nixpkgs = {
43    overlays = builtins.attrValues outputs.overlays;
44
45    flake = {
46      setFlakeRegistry = false;
47      setNixPath = false;
48    };
49
50    config = {
51      allowUnfree = lib.mkForce false;
52      allowBroken = lib.mkForce false;
53    };
54  };
55
56  system.tools = {
57    nixos-build-vms.enable = false;
58    nixos-enter.enable = false;
59    nixos-generate-config.enable = false;
60    nixos-install.enable = false;
61    nixos-option.enable = false;
62  };
63
64  networking = {
65    domain = "lostduk.com";
66
67    useDHCP = lib.mkDefault true;
68    enableIPv6 = lib.mkForce false;
69
70    firewall = {
71      enable = lib.mkForce true;
72      allowPing = lib.mkForce false;
73      allowedTCPPorts = [];
74      allowedUDPPorts = [];
75    };
76  };
77
78  networking.dhcpcd.extraConfig = lib.mkIf (!wsl) "nohook resolv.conf";
79
80  services = {
81    pcscd.enable = true;
82
83    resolved = lib.mkIf (!wsl) {
84      enable = true;
85
86      settings.Resolve = {
87        DNS = [
88          "194.242.2.2#dns.mullvad.net"
89          "9.9.9.9#dns.quad9.net"
90          "149.112.112.112#dns.quad9.net"
91        ];
92        FallbackDNS = [];
93        Domains = [ "~." ];
94        DNSOverTLS = true;
95        DNSSEC = false;
96      };
97    };
98
99    openssh = {
100      enable = lib.mkDefault true;
101      settings = {
102        PermitRootLogin = "no";
103        PasswordAuthentication = false;
104        KbdInteractiveAuthentication = false;
105      };
106      hostKeys = [{
107        path = "${lib.optionalString impermanence "/persist"}/etc/ssh/ssh_host_ed25519_key";
108        type = "ed25519";
109      }];
110    };
111  };
112
113  security = {
114    protectKernelImage = true;
115
116    audit = {
117      enable = true;
118      rules = [ "-a exit,always -F arch=b64 -S execve" ];
119    };
120
121    sudo = {
122      execWheelOnly = true;
123      wheelNeedsPassword = lib.mkForce true;
124    };
125
126    auditd.enable = true;
127    pam.sshAgentAuth.enable = true;
128  };
129
130  users = {
131    mutableUsers = lib.mkForce false;
132
133    users.root.hashedPassword = lib.mkForce "!";
134  };
135
136  boot = {
137    kernelParams = [
138      "slab_nomerge"
139      "init_on_alloc=1"
140      "init_on_free=1"
141      "page_alloc.shuffle=1"
142      "randomize_kstack_offset=on"
143      "vsyscall=none"
144      "debugfs=off"
145    ];
146
147    kernel.sysctl = {
148      "kernel.kptr_restrict" = 2;
149      "kernel.dmesg_restrict" = 1;
150      "kernel.printk" = "3 3 3 3";
151      "kernel.unprivileged_bpf_disabled" = 1;
152      "net.core.bpf_jit_harden" = 2;
153      "kernel.yama.ptrace_scope" = 1;
154      "kernel.sysrq" = 0;
155      "kernel.perf_event_paranoid" = 3;
156      "dev.tty.ldisc_autoload" = 0;
157      "vm.unprivileged_userfaultfd" = 0;
158      "fs.suid_dumpable" = 0;
159      "fs.protected_fifos" = 2;
160      "fs.protected_regular" = 2;
161      "fs.protected_symlinks" = 1;
162      "fs.protected_hardlinks" = 1;
163
164      "net.ipv4.tcp_syncookies" = 1;
165      "net.ipv4.tcp_rfc1337" = 1;
166      "net.ipv4.conf.all.rp_filter" = 1;
167      "net.ipv4.conf.default.rp_filter" = 1;
168      "net.ipv4.conf.all.accept_redirects" = 0;
169      "net.ipv4.conf.default.accept_redirects" = 0;
170      "net.ipv4.conf.all.secure_redirects" = 0;
171      "net.ipv4.conf.default.secure_redirects" = 0;
172      "net.ipv4.conf.all.send_redirects" = 0;
173      "net.ipv4.conf.default.send_redirects" = 0;
174      "net.ipv4.conf.all.accept_source_route" = 0;
175      "net.ipv4.conf.default.accept_source_route" = 0;
176      "net.ipv4.icmp_echo_ignore_broadcasts" = 1;
177    };
178
179    blacklistedKernelModules = [
180      "dccp" "sctp" "rds" "tipc" "n-hdlc" "ax25" "netrom" "x25" "rose"
181      "decnet" "econet" "af_802154" "ipx" "appletalk" "psnap" "p8023"
182      "p8022" "can" "atm"
183      "cramfs" "freevxfs" "jffs2" "hfs" "hfsplus"
184      "firewire-core" "thunderbolt" "vivid"
185    ];
186  };
187
188  systemd.coredump.settings.Coredump = {
189    Storage = "none";
190    ProcessSizeMax = 0;
191  };
192
193  environment = {
194    defaultPackages = lib.mkForce [];
195
196    etc = lib.mkIf (!config.services.openssh.enable) (lib.mapAttrs' (name: user:
197      lib.nameValuePair "ssh/authorized_keys.d/${name}" {
198        mode = "0444";
199        text = lib.concatLines user.openssh.authorizedKeys.keys;
200      }) (lib.filterAttrs (_: user: user.openssh.authorizedKeys.keys != []) config.users.users));
201
202    persistence."/persist" = {
203      enable = impermanence;
204      hideMounts = false;
205
206      directories = [
207        "/srv"
208        "/var/log"
209        "/var/lib/nixos"
210        "/var/lib/systemd"
211      ];
212    };
213  };
214
215  programs.nano.enable = false;
216
217  fileSystems = lib.mkIf impermanence {
218    "/persist".neededForBoot = true;
219  };
220
221  system.activationScripts.persistent-dirs = lib.mkIf impermanence {
222    deps = [ "users" ];
223    text =
224      let
225        mkHomePersist = user: lib.optionalString user.createHome ''
226          mkdir -p /persist${user.home}
227          chown ${user.name}:${user.group} /persist${user.home}
228          chmod ${user.homeMode} /persist${user.home}
229        '';
230      in
231        lib.concatLines (map mkHomePersist (lib.attrValues config.users.users));
232  };
233
234  assertions = [{
235    assertion = rollback -> config.boot.initrd.systemd.enable;
236    message = "kore: root rollback needs boot.initrd.systemd.enable";
237  }];
238
239  boot.initrd = lib.mkIf rollback {
240    supportedFilesystems = [ "btrfs" ];
241
242    systemd.services.wipe-root = {
243      wantedBy = [ "initrd.target" ];
244      requires = [ rootUnit ];
245      after = [ rootUnit ];
246      before = [ "sysroot.mount" ];
247      unitConfig.DefaultDependencies = "no";
248      serviceConfig = {
249        Type = "oneshot";
250        RemainAfterExit = true;
251      };
252      script = ''
253        mkdir -p /tmp
254        MNTPOINT=$(mktemp -d)
255        (
256          mount ${rootDevice} "$MNTPOINT"
257          trap 'umount "$MNTPOINT"' EXIT
258
259          if [[ -e $MNTPOINT/@ ]]; then
260            echo "Backing up root..."
261            mkdir -p $MNTPOINT/old_roots
262            mv "$MNTPOINT/@" "$MNTPOINT/old_roots/@_$(date "+%Y-%m-%-d_%H:%M:%S")"
263          fi
264
265          echo "Deleting 7+ days old roots..."
266          find "$MNTPOINT/old_roots" -mindepth 1 -maxdepth 1 \
267            -mtime +7 \
268            -exec btrfs sub del -R {} +
269
270          echo "Creating new root..."
271          btrfs sub cre "$MNTPOINT/@"
272        )
273      '';
274    };
275  };
276}