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}