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