summaryrefslogtreecommitdiff
path: root/hosts
diff options
context:
space:
mode:
authorvin <vin@vineetk.net>2025-09-20 17:31:10 -0400
committervin <vin@vineetk.net>2025-09-20 17:59:06 -0400
commitbd18f4a8f3d5d3d360216bbb01ae83514c28d00c (patch)
tree020d9404a8b4825f9bd4ab3f4f0146012e75183d /hosts
parent1718f4f19bc947c3e1179a278e816310a3c8cec6 (diff)
prepare repo for switching back to nixos
Diffstat (limited to 'hosts')
-rw-r--r--hosts/demiurge/default.nix509
-rw-r--r--hosts/hastur/default.nix297
2 files changed, 460 insertions, 346 deletions
diff --git a/hosts/demiurge/default.nix b/hosts/demiurge/default.nix
index ab36f02..c53c3eb 100644
--- a/hosts/demiurge/default.nix
+++ b/hosts/demiurge/default.nix
@@ -21,14 +21,6 @@
21 allowUnfreePredicate = 21 allowUnfreePredicate =
22 pkg: 22 pkg:
23 builtins.elem (lib.getName pkg) [ 23 builtins.elem (lib.getName pkg) [
24 /*
25 "cuda_cccl"
26 "cuda_cudart"
27 "cuda_nvcc"
28 "cudnn"
29 "libcublas"
30 "libcufile"
31 */
32 "steam" 24 "steam"
33 "steam-unwrapped" 25 "steam-unwrapped"
34 ]; 26 ];
@@ -44,30 +36,6 @@
44 36
45 overlays = [ 37 overlays = [
46 (self: super: { 38 (self: super: {
47 invidious = super.invidious.overrideAttrs (old: {
48 # try removing shorts by ignoring any videos shorter than 65 seconds
49 postPatch =
50 old.postPatch
51 + ''
52 sed -i '/GROUP BY channel/a\ AND length_seconds > 65' src/invidious/database/channels.cr
53 sed -i 's/\({view_name}\) \(ORDER BY published\)/\1 WHERE length_seconds > 65 \2/' src/invidious/users.cr
54 sed -i 's/\({values})\) \(ORDER BY published\)/\1 AND length_seconds > 65 \2/' src/invidious/users.cr
55 '';
56 });
57 })
58 (self: super: {
59 inv-sig-helper = super.inv-sig-helper.overrideAttrs (old: {
60 version = "0-unstable-2025-04-23";
61
62 src = super.fetchFromGitHub {
63 owner = "iv-org";
64 repo = "inv_sig_helper";
65 rev = "5d3c7a4574fafe0bc5fbed9e7e33483889832fd4";
66 hash = "sha256-WGh62tjKGe9OD19aq+lP9GfYs5PrGqkeT6VvmtNottQ=";
67 };
68 });
69 })
70 (self: super: {
71 alvr = super.alvr.overrideAttrs (old: { 39 alvr = super.alvr.overrideAttrs (old: {
72 buildInputs = old.buildInputs ++ [ 40 buildInputs = old.buildInputs ++ [
73 super.android-tools 41 super.android-tools
@@ -91,11 +59,8 @@
91 59
92 # decrypt agenix secrets 60 # decrypt agenix secrets
93 age.secrets = { 61 age.secrets = {
94 tailscale_demiurge = { 62 wg0_demiurge.file = ../../secrets/wg0_demiurge.age;
95 file = ../../secrets/tailscale_demiurge.age; 63 wg1_demiurge.file = ../../secrets/wg0_demiurge.age;
96 owner = "root";
97 group = "root";
98 };
99 }; 64 };
100 65
101 # boot options 66 # boot options
@@ -114,7 +79,7 @@
114 79
115 zfs.extraPools = [ 80 zfs.extraPools = [
116 "data_wd" 81 "data_wd"
117 "nvme_warm" 82 "data"
118 ]; 83 ];
119 }; 84 };
120 85
@@ -134,34 +99,101 @@
134 allowedUDPPorts = [ 51413 ]; 99 allowedUDPPorts = [ 51413 ];
135 }; 100 };
136 101
137 # mullvad to miami 102 wg-quick.interfaces = {
138 wg-quick.interfaces.us-mia-wg-002 = { 103 # mullvad
139 address = [ 104 wg0 = {
140 "10.135.221.102/32" 105 address = [
141 "fc00:bbbb:bbbb:bb01:d:0:7:dd66/128" 106 "10.68.117.111/32"
142 ]; 107 "fc00:bbbb:bbbb:bb01::5:756e/128"
143 privateKey = "***REDACTED_WG_KEY***="; 108 ];
109 privateKeyFile = config.age.secrets.wg0_demiurge.path;
144 110
145 # supposed to be done by tailscale instead \_(:/)_/ 111 postUp = "ip route add 45.134.142.206 dev eth0";
146 postUp = '' 112 postDown = "ip route del 45.134.142.206 dev eth0";
147 ip route add 100.64.0.0/24 dev tailscale0
148 ip route add 100.100.100.100/32 dev tailscale0
149 '';
150 postDown = ''
151 ip route del 100.64.0.0/24 dev tailscale0
152 ip route del 100.100.100.100/32 dev tailscale0
153 '';
154 113
155 peers = [ 114 peers = [{
156 { 115 allowedIPs = [
157 allowedIPs = [ 116 "0.0.0.0/0"
158 "0.0.0.0/0" 117 "::0/0"
159 "::0/0" 118 ];
160 ]; 119 endpoint = "45.134.142.206:51820";
161 endpoint = "45.134.142.206:51820"; 120 publicKey = "H5t7PsMDnUAHrR8D2Jt3Mh6N6w43WmCzrOHShlEU+zw=";
162 publicKey = "H5t7PsMDnUAHrR8D2Jt3Mh6N6w43WmCzrOHShlEU+zw="; 121 }];
163 } 122 };
164 ]; 123
124 # epistemia
125 wg1 = {
126 address = [
127 "10.0.13.2/24"
128 "fd00:b0ba:cafe:babe::2/64"
129 ];
130 privateKeyFile = config.age.secrets.wg1_demiurge.path;
131 listenPort = 51820;
132 fwMark = 51821;
133 MTU = 1420;
134
135 table = false;
136 postUp = ''
137PostUp = ip rule add from 10.0.13.0/24 lookup main pref 31000
138PostUp = ip rule add from all fwmark 51821 lookup 51821 pref 32000
139PostUp = ip route add default via 192.168.1.1 dev eth0 table 51821
140
141# NAT iphonebob and allow traffic between peers (when routing through demiurge)
142PostUp = iptables -F FORWARD
143PostUp = iptables -t nat -I POSTROUTING 1 -s 10.0.13.4/32 -o wg0 -j MASQUERADE
144PostUp = iptables -A FORWARD -i wg1 -o wg1 -j ACCEPT
145PostUp = iptables -A FORWARD -i wg1 -o wg0 -j ACCEPT
146PostUp = iptables -A FORWARD -i wg0 -o wg1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
147 '';
148 preDown = ''
149PreDown = ip rule del from all fwmark 51821 lookup 51821 pref 32000
150PreDown = ip rule del from 10.0.13.0/24 lookup main pref 31000
151PreDown = ip route flush table 51821
152
153PreDown = iptables -t nat -D POSTROUTING -s 10.0.13.4/32 -o wg0 -j MASQUERADE
154PreDown = iptables -F FORWARD
155 '';
156
157 peers = [
158 # saklas
159 {
160 allowedIPs = [
161 "10.0.13.1/32"
162 "fd00:b0ba:cafe:babe::1/128"
163 ];
164 endpoint = "157.180.125.215:51820";
165 persistentKeepalive = 25;
166 publicKey = "XvRailvccuc7LJIF4aaYM/MLkU4upiprwFlCfBllhl0=";
167 }
168 # hastur
169 {
170 allowedIPs = [
171 "10.0.13.3/32"
172 "fd00:b0ba:cafe:babe::3/128"
173 ];
174 persistentKeepalive = 25;
175 publicKey = "MOmRjVbRuWEuK0oHQ+C0jTaceCUPd2fpzDbh8ue6bDc=";
176 }
177 # iphonebob
178 {
179 allowedIPs = [
180 "10.0.13.4/32"
181 "fd00:b0ba:cafe:babe::4/128"
182 ];
183 persistentKeepalive = 25;
184 publicKey = "Xn0EmeRZdpMejBgzr98mYtb/2f5O58GAzQLNZV/SS30=";
185 }
186 # lab
187 {
188 allowedIPs = [
189 "10.0.13.5/32"
190 "fd00:b0ba:cafe:babe::5/128"
191 ];
192 persistentKeepalive = 25;
193 publicKey = "iMDEwvXjPAlQH8ZCmP63FM5ICYIFIX5XIyGxjnXoNVE=";
194 }
195 ];
196 };
165 }; 197 };
166 }; 198 };
167 199
@@ -186,24 +218,19 @@
186 isNormalUser = true; 218 isNormalUser = true;
187 219
188 extraGroups = [ 220 extraGroups = [
189 "input"
190 "kvm"
191 "libvirtd"
192 "transmission" 221 "transmission"
193 "video"
194 "wheel" 222 "wheel"
195 ]; 223 ];
196 224
197 shell = pkgs.zsh; 225 shell = pkgs.zsh;
198 226
199 openssh.authorizedKeys.keys = [ 227 openssh.authorizedKeys.keys = [
200 "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEvM0xCLziR+ZT/SYE1aZM6dklbw4fEC17TWqbADIZRH kou@demiurge" 228 "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEvM0xCLziR+ZT/SYE1aZM6dklbw4fEC17TWqbADIZRH vin@demiurge"
201 ]; 229 ];
202 230
203 packages = with pkgs; [ 231 packages = with pkgs; [
204 alvr 232 alvr
205 bs-manager 233 bs-manager
206 distrobox
207 (llama-cpp.packages.x86_64-linux.rocm.override { useVulkan = true; }) 234 (llama-cpp.packages.x86_64-linux.rocm.override { useVulkan = true; })
208 #(vllm.override { cudaSupport = false; rocmSupport = true; gpuTargets = [ "gfx906" "gfx1100" ]; }) 235 #(vllm.override { cudaSupport = false; rocmSupport = true; gpuTargets = [ "gfx906" "gfx1100" ]; })
209 ]; 236 ];
@@ -249,9 +276,6 @@
249 # steam, proprietary. I sometimes like playing nonfree games too. 276 # steam, proprietary. I sometimes like playing nonfree games too.
250 steam.enable = true; 277 steam.enable = true;
251 278
252 # virtualization
253 virt-manager.enable = true;
254
255 # configuration in home-manager 279 # configuration in home-manager
256 zsh.enable = true; 280 zsh.enable = true;
257 zsh.promptInit = "PS1='$ '"; 281 zsh.promptInit = "PS1='$ '";
@@ -270,53 +294,57 @@
270 ]; 294 ];
271 }; 295 };
272 296
273 pki.certificates = [
274 ''
275 -----BEGIN CERTIFICATE-----
276 MIIDMDCCAhigAwIBAgIUcSUafnojcFKod3f436VELfEKoFkwDQYJKoZIhvcNAQEL
277 BQAwHTEbMBkGA1UEAwwSZGVtaXVyZ2UuZXBpc3RlbWlhMB4XDTI1MDMwMzEwMjQw
278 OVoXDTI2MDMwMzEwMjQwOVowHTEbMBkGA1UEAwwSZGVtaXVyZ2UuZXBpc3RlbWlh
279 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwiRlreCXc7f+yWclxR2M
280 639g0+Lr/c9HrX7EM2/olavPAtZgCzqqvJsDmXq4AURlwd82wZUZxXjWFwlRji/+
281 WViXQBTWwnXVjc9MJlxTq2X2zfU2GIxYsrA1ZQuj0wVHlA+R/66oL0Padc/qQZfv
282 sshQnrqnutvGobBWEGJXcCIDiwUGgHlIoelwY9G0GLE/rkVujNjAonyMhVGJHVUv
283 lXyc3RNslQHymr4Wl6+lL6V6XfuB1taECJYSLXPx66TvJqod2Io+b7T7cWp+9g9U
284 B2jQu1YnPRpwjdPvbOCPjPbOP6UcbyHdbHAidSM0FSL5riVUmugwDwbQKXFFX2gH
285 hwIDAQABo2gwZjAfBgNVHREEGDAWghQqLmRlbWl1cmdlLmVwaXN0ZW1pYTATBgNV
286 HSUEDDAKBggrBgEFBQcDATAPBgNVHRMECDAGAQH/AgEAMB0GA1UdDgQWBBTjMVhw
287 zmkE6P5jFHkLVQE2gNB2ejANBgkqhkiG9w0BAQsFAAOCAQEAWvnwB83vXzQFpObF
288 vn/nfZ9wYpNaBsE15ab3Fwd2nDc55KDkDWgBi5Xl8fwN3OhFOU2XXBCYqbCU6asx
289 OnSx9glbhJioORO7B5ENbEYrpB97SaWASNXrBQ2KiQT5aC+9xb52K53kkk0tTn2l
290 nBb+jyLItzWX99H6EavOq69a4T2BObZaSPQAfpM8FIrKl+UZC3152+bi8wKfG4K4
291 FQsOJMjIvhTm2IiOS8xIaZz7EJORxFjtOkLEIGGZBNK6QcnD714/nYbHSrQx4eNM
292 /ek8Rmf6DTLaFBx+raWyDTgMY23lvWTKDTT1+dZnRNcg72bFpIdqHsDrIg/IBjZ0
293 3eGfkQ==
294 -----END CERTIFICATE-----
295 ''
296 ];
297
298 sudo.enable = false; 297 sudo.enable = false;
299 }; 298 };
300 299
301 services = { 300 services = {
302 # control unicorn barf
303 hardware.openrgb.enable = true;
304
305 # dns 301 # dns
306 dnsmasq = { 302 unbound = {
307 enable = true; 303 enable = true;
308 settings = { 304 settings = {
309 server = [ 305 server = {
310 "192.168.1.1" 306 interface = [ "127.0.0.1" "10.0.13.2" "fd00:b0ba:cafe:babe::2" "::1" ];
311 "/epistemia/100.100.100.100" 307 access-control = [ "0.0.0.0/0 allow" "::0/0 allow" ];
312 ]; 308
309 hide-identity = yes;
310 hide-version = yes;
311
312 # Synthesize NXDOMAINs from DNSSEC NSEC chains.
313 # https://tools.ietf.org/html/rfc8198
314 aggressive-nsec = no;
315
316 local-zone = "saklas.epistemia." redirect;
317 local-data = "saklas.epistemia. 86400 IN A 10.0.13.1";
318 local-data = "saklas.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::1";
319 local-zone = "demiurge.epistemia." redirect;
320 local-data = "demiurge.epistemia. 86400 IN A 10.0.13.2";
321 local-data = "demiurge.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::2";
322 local-zone = "hastur.epistemia." redirect;
323 local-data = "hastur.epistemia. 86400 IN A 10.0.13.3";
324 local-data = "hastur.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::3";
325 local-zone = "iphonebob.epistemia." redirect;
326 local-data = "iphonebob.epistemia. 86400 IN A 10.0.13.4";
327 local-data = "iphonebob.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::4";
328 local-zone = "lab.epistemia." redirect;
329 local-data = "lab.epistemia. 86400 IN A 10.0.13.5";
330 local-data = "lab.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::5";
331 local-zone = "paraclete.epistemia." redirect;
332 local-data = "paraclete.epistemia. 86400 IN A 10.0.13.6";
333 local-data = "paraclete.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::6";
334 };
313 335
314 interface = "lo"; 336 # hagezi for dns-based adblocking (in addition to others)
315 listen-address = "127.0.0.1"; 337 rpz = {
316 bind-interfaces = true; 338 name = "hagezi.ultimate";
317 no-resolv = true; 339 zonefile = "hagezi.ultimate";
340 url = "https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/ultimate.txt";
341 };
318 342
319 conf-file = "/data/src/clones/networking/hagezi_dns-blocklists/dnsmasq/ultimate.txt"; 343 # go through mullvad for regular dns queries
344 forward-zone = {
345 name = ".";
346 forward-addr = [ "100.64.0.3" ];
347 };
320 }; 348 };
321 }; 349 };
322 350
@@ -361,39 +389,6 @@
361 }; 389 };
362 }; 390 };
363 391
364 # invidious
365 invidious = {
366 enable = true;
367
368 http3-ytproxy.enable = true;
369 nginx.enable = true;
370 sig-helper.enable = true;
371
372 domain = "invidious.demiurge.epistemia";
373 extraSettingsFile = "/run/invidious_settings";
374 settings = {
375 admins = [ "vin" ];
376 captcha_enabled = false;
377 registration_enabled = false;
378 hmac_key = "zCYyRa7vD0qt";
379 default_user_preferences = {
380 captions = [ "English" ];
381 dark_mode = "dark";
382 feed_menu = [
383 "Popular"
384 "Subscriptions"
385 "Playlists"
386 ];
387 max_results = 100;
388 quality = "dash";
389 save_player_pos = true;
390 unseen_only = true;
391 local = true;
392 extend_desc = true;
393 };
394 };
395 };
396
397 # graphical input 392 # graphical input
398 libinput = { 393 libinput = {
399 enable = true; 394 enable = true;
@@ -420,7 +415,7 @@
420 nginx = { 415 nginx = {
421 enable = true; 416 enable = true;
422 417
423 defaultListenAddresses = [ "100.64.0.2" ]; 418 defaultListenAddresses = [ "10.0.13.2" "fd00:b0ba:cafe:babe::2" ];
424 419
425 recommendedGzipSettings = true; 420 recommendedGzipSettings = true;
426 recommendedOptimisation = true; 421 recommendedOptimisation = true;
@@ -460,22 +455,14 @@
460 }; 455 };
461 456
462 "sdui.demiurge.epistemia" = { 457 "sdui.demiurge.epistemia" = {
463 # addSSL = true; 458 addSSL = true;
464 # sslCertificate = "/var/demiurge.epistemia.crt"; 459 sslCertificate = "/var/demiurge.epistemia.crt";
465 # sslCertificateKey = "/var/demiurge.epistemia.key"; 460 sslCertificateKey = "/var/demiurge.epistemia.key";
466 locations."/" = { 461 locations."/" = {
467 proxyPass = "http://127.0.0.1:7860"; 462 proxyPass = "http://127.0.0.1:7860";
468 proxyWebsockets = true; 463 proxyWebsockets = true;
469 }; 464 };
470 }; 465 };
471
472 "invidious.demiurge.epistemia" = {
473 addSSL = true;
474 enableACME = false;
475 forceSSL = false;
476 sslCertificate = "/var/demiurge.epistemia.crt";
477 sslCertificateKey = "/var/demiurge.epistemia.key";
478 };
479 }; 466 };
480 }; 467 };
481 468
@@ -508,7 +495,127 @@
508 # using pulseaudio and home-manager, so had to disable pulseaudio. 495 # using pulseaudio and home-manager, so had to disable pulseaudio.
509 pipewire = { 496 pipewire = {
510 enable = true; 497 enable = true;
498 alsa.enable = true;
499 audio.enable = true;
511 pulse.enable = true; 500 pulse.enable = true;
501
502 extraConfig.pipewire = {
503 "99-filter-he5xx.conf" = {
504 "context.modules" = [
505 {
506 name = "libpipewire-module-filter-chain";
507 args = {
508 node.name = "peq-he5xx-sink";
509 node.description = "PEQ HE5XX (auto)";
510 # playback.props is the virtual sink/device properties
511 playback.props = {
512 media.class = "Audio/Sink";
513 "filter.smart" = true;
514 "filter.smart.name" = "peq-he5xx";
515 # tell WirePlumber what target properties this filter is intended for
516 # (we leave this unset here; smart target matching will be done by wireplumber)
517 };
518 # filter graph: single builtin param_eq node that loads the param file
519 filter.graph = [
520 {
521 type = "builtin";
522 name = "param_eq";
523 label = "param_eq_he5xx";
524 config.filename = "/etc/pipewire/parametric/he5xx.txt";
525 }
526 ];
527 };
528 };
529 ];
530 };
531
532 "99-filter-airpods.conf" = {
533 "context.modules" = [
534 {
535 name = "libpipewire-module-filter-chain";
536 args = {
537 node.name = "peq-airpods-pro-2-sink";
538 node.description = "PEQ AirPods Pro 2 (auto)";
539 playback.props = {
540 media.class = "Audio/Sink";
541 "filter.smart" = true;
542 "filter.smart.name" = "peq-airpods-pro-2";
543 };
544 filter.graph = [
545 {
546 type = "builtin";
547 name = "param_eq";
548 label = "param_eq_airpods";
549 config.filename = "/etc/pipewire/parametric/airpods-pro-2.txt";
550 }
551 ];
552 };
553 }
554 ];
555 };
556 };
557
558 # TODO run nixfmt to fix indenting of below (can't right now because on gentoo without nixfmt)
559 wireplumber = {
560 enable = true;
561 extraConfig."50-smartfilters-airpods.conf".text = ''
562 {
563 "monitor.bluez.rules" : [
564 # When a BlueZ device is detected we set an identifying property that the smart filter will match.
565 # (This fragment adds nothing by default; we're using a policy to match target.node later.)
566 ],
567
568 "policy.rules" : [
569 # The core smart filter matching is done by matching the target.node properties
570 # WirePlumber's smart filters will look for filter.smart.target (set below).
571 ],
572
573 "policy" : {
574 "smart_filters" : {
575 "rules" : [
576 {
577 "matches" : [
578 { "device.props" : { "bluez5.device.name" : "AirPods Pro 2" } }
579 ],
580 "actions" : {
581 # If target device matches, set the 'target.node' metadata for smart filters to use
582 "update-metadata" : {
583 "target.node" : { "name" : "bluez_output.*AirPods.*" }
584 }
585 }
586 }
587 ]
588 }
589 },
590
591 "endpoint.rules" : [
592 {
593 "matches" : [
594 { "node.name" : "peq-airpods-pro-2-sink" }
595 ],
596 "actions" : {
597 "update-props" : {
598 # Mark this WF sink as intended for a specific target device.
599 # WirePlumber will use filter.smart.target to identify which device to chain to.
600 "filter.smart.target" : { "bluez5.device.name" : "AirPods Pro 2" }
601 }
602 }
603 },
604 {
605 "matches" : [
606 { "node.name" : "peq-he5xx-sink" }
607 ],
608 "actions" : {
609 "update-props" : {
610 # He5xx is a generic filter (no specific bluez target) — it could be matched by other rules.
611 "filter.smart.target" : {}
612 }
613 }
614 }
615 ]
616 }
617 '';
618 };
512 }; 619 };
513 620
514 # reddit 621 # reddit
@@ -555,11 +662,11 @@
555 # Disable autoplay videos by default 662 # Disable autoplay videos by default
556 REDLIB_DEFAULT_AUTOPLAY_VIDEOS = false; 663 REDLIB_DEFAULT_AUTOPLAY_VIDEOS = false;
557 # Define a default list of subreddit subscriptions (format: sub1+sub2+sub3) 664 # Define a default list of subreddit subscriptions (format: sub1+sub2+sub3)
558 REDLIB_DEFAULT_SUBSCRIPTIONS = "ergomechkeyboards+localllama+factorio+warframe+elitedangerous+unixporn+usabilityporn"; 665 REDLIB_DEFAULT_SUBSCRIPTIONS = "ergomechkeyboards+localllama+elitedangerous";
559 # Define a default list of subreddit filters (format: sub1+sub2+sub3) 666 # Define a default list of subreddit filters (format: sub1+sub2+sub3)
560 REDLIB_DEFAULT_FILTERS = "popular+all+funny+memes"; 667 REDLIB_DEFAULT_FILTERS = "popular+all+funny+memes";
561 # Hide awards by default 668 # Hide awards by default
562 REDLIB_DEFAULT_HIDE_AWARDS = false; 669 REDLIB_DEFAULT_HIDE_AWARDS = true;
563 # Hide sidebar and summary 670 # Hide sidebar and summary
564 REDLIB_DEFAULT_HIDE_SIDEBAR_AND_SUMMARY = false; 671 REDLIB_DEFAULT_HIDE_SIDEBAR_AND_SUMMARY = false;
565 # Disable the confirmation before visiting Reddit 672 # Disable the confirmation before visiting Reddit
@@ -604,8 +711,8 @@
604 711
605 hostnames = { 712 hostnames = {
606 replace = { 713 replace = {
607 "(.*\.)?youtube\.com$" = "invidious.demiurge.epistemia"; 714 "(.*\.)?youtube\.com$" = "yewtu.be";
608 "(.*\.)?youtu\.be$" = "invidious.demiurge.epistemia"; 715 "(.*\.)?youtu\.be$" = "yewtu.be";
609 "(.*\.)?reddit\.com$" = "redlib.demiurge.epistemia"; 716 "(.*\.)?reddit\.com$" = "redlib.demiurge.epistemia";
610 "(.*\.)?redd\.it$" = "redlib.demiurge.epistemia"; 717 "(.*\.)?redd\.it$" = "redlib.demiurge.epistemia";
611 }; 718 };
@@ -967,7 +1074,6 @@
967 doi_resolvers = { 1074 doi_resolvers = {
968 "oadoi.org" = "https://oadoi.org/"; 1075 "oadoi.org" = "https://oadoi.org/";
969 "doi.org" = "https://doi.org/"; 1076 "doi.org" = "https://doi.org/";
970 "doai.io" = "https://dissem.in/";
971 "sci-hub.se" = "https://sci-hub.se/"; 1077 "sci-hub.se" = "https://sci-hub.se/";
972 "sci-hub.st" = "https://sci-hub.st/"; 1078 "sci-hub.st" = "https://sci-hub.st/";
973 "sci-hub.ru" = "https://sci-hub.ru/"; 1079 "sci-hub.ru" = "https://sci-hub.ru/";
@@ -977,25 +1083,10 @@
977 }; 1083 };
978 }; 1084 };
979 1085
980 # vpn
981 tailscale = {
982 enable = true;
983 authKeyFile = config.age.secrets.tailscale_demiurge.path;
984 extraDaemonFlags = [ "--no-logs-no-support" ];
985 extraUpFlags = [
986 "--login-server=https://headscale.13f0.net"
987 "--advertise-exit-node"
988 ];
989 openFirewall = true;
990 };
991
992 # udev rules 1086 # udev rules
993 udev = { 1087 udev = {
994 enable = true; 1088 enable = true;
995 extraRules = '' 1089 extraRules = ''
996 # ST-Link v2.1
997 SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE:="0666"
998
999 # Oculus Quest 2 1090 # Oculus Quest 2
1000 SUBSYSTEM=="usb", ATTR{idVendor}=="2833", ATTR{idProduct}=="0186", MODE="0660", 1091 SUBSYSTEM=="usb", ATTR{idVendor}=="2833", ATTR{idProduct}=="0186", MODE="0660",
1001 GROUP="input", SYMLINK+="ocuquest%n" 1092 GROUP="input", SYMLINK+="ocuquest%n"
@@ -1015,53 +1106,10 @@
1015 }; 1106 };
1016 1107
1017 # extra systemd stuff 1108 # extra systemd stuff
1018 systemd = { 1109 systemd.services.nginx = {
1019 services = { 1110 after = [ "wg-quick@wg1.service" ];
1020 invidious_token = { 1111 requires = [ "wg-quick@wg1.service" ];
1021 script = '' 1112 serviceConfig.Type = lib.mkForce "idle";
1022 set -euo pipefail
1023
1024 a="$(${pkgs.podman}/bin/podman run quay.io/invidious/youtube-trusted-session-generator | sed -n 4,5p)"
1025 visitor_data=$(echo "$a" | sed -n 1p | cut -d' ' -f2)
1026 po_token=$(echo "$a" | sed -n 2p | cut -d' ' -f2)
1027 day=$(date +%e | tr -d ' ')
1028
1029 printf '{"visitor_data": "%s",\n"po_token": "%s",\n' \
1030 "$visitor_data" "$po_token" \
1031 >/run/invidious_settings
1032
1033 if [ $((day % 2)) -eq 0 ]; then
1034 printf '"force_resolve": "ipv6"}\n' >>/run/invidious_settings
1035 else
1036 printf '"force_resolve": "ipv4"}\n' >>/run/invidious_settings
1037 fi
1038
1039 ${pkgs.systemd}/bin/systemctl restart invidious-sig-helper
1040 ${pkgs.systemd}/bin/systemctl restart invidious
1041 '';
1042 serviceConfig = {
1043 Type = "oneshot";
1044 User = "root";
1045 };
1046 };
1047
1048 nginx = {
1049 after = [ "tailscaled.service" ];
1050 requires = [ "tailscaled.service" ];
1051 serviceConfig.Type = lib.mkForce "idle";
1052 };
1053
1054 postgresql.serviceConfig.Type = lib.mkForce "idle";
1055 tailscaled.serviceConfig.Type = lib.mkForce "idle";
1056 };
1057
1058 timers.invidious_token = {
1059 timerConfig = {
1060 OnCalendar = "hourly";
1061 Persistent = true;
1062 };
1063 wantedBy = [ "timers.target" ];
1064 };
1065 }; 1113 };
1066 1114
1067 # create caches and use mandoc 1115 # create caches and use mandoc
@@ -1072,20 +1120,5 @@
1072 mandoc.enable = true; 1120 mandoc.enable = true;
1073 }; 1121 };
1074 1122
1075 # virtualization stuff
1076 virtualisation = {
1077 libvirtd.enable = true;
1078
1079 podman = {
1080 enable = true;
1081 dockerCompat = true;
1082 };
1083 };
1084
1085 xdg.portal = {
1086 config.common.default = [ "wlr" ];
1087 wlr.enable = true;
1088 };
1089
1090 system.stateVersion = "24.05"; 1123 system.stateVersion = "24.05";
1091} 1124}
diff --git a/hosts/hastur/default.nix b/hosts/hastur/default.nix
index 5127533..d9507c4 100644
--- a/hosts/hastur/default.nix
+++ b/hosts/hastur/default.nix
@@ -19,11 +19,9 @@
19 19
20 # decrypt agenix secrets 20 # decrypt agenix secrets
21 age.secrets = { 21 age.secrets = {
22 tailscale_hastur = { 22 wg0_hastur.file = ../../secrets/wg0_hastur.age;
23 file = ../../secrets/tailscale_hastur.age; 23 wg1_hastur.file = ../../secrets/wg1_hastur.age;
24 owner = "root"; 24 wpa_supplicant.file = ../../secrets/wpa_supplicant.age;
25 group = "root";
26 };
27 }; 25 };
28 26
29 # boot options 27 # boot options
@@ -40,34 +38,14 @@
40 ]; 38 ];
41 }; 39 };
42 40
43 # disable wifi and open some ports
44 networking = { 41 networking = {
45 hostName = "hastur"; 42 hostName = "hastur";
46 hostId = "deadcafe"; 43 hostId = "deadcafe";
47 44
48 wireless = { 45 wireless = {
49 enable = true; 46 enable = true;
50 47 userControlled = true;
51 networks = { 48 allowAuxiliaryImperativeNetworks = true;
52 OpenDyna.pskRaw = "***REDACTED_PSK***";
53
54 FloridaPoly = {
55 authProtocols = [ "WPA-EAP" ];
56 auth = ''
57 eap=PEAP
58 phase2="auth=MSCHAPv2"
59 identity="***REDACTED_EMAIL***"
60 password="***REDACTED_PASSWORD***"
61 '';
62 };
63
64 USF-Guest = { };
65
66 iphonebob.pskRaw = "***REDACTED_PSK***";
67 Retreat_86WiFi.pskRaw = "***REDACTED_PSK***";
68 Orbi-1.pskRaw = "***REDACTED_PSK***";
69 SETUP-E55E.pskRaw = "***REDACTED_PSK***";
70 };
71 }; 49 };
72 50
73 firewall = { 51 firewall = {
@@ -75,34 +53,58 @@
75 # allowedUDPPorts = [ ]; 53 # allowedUDPPorts = [ ];
76 }; 54 };
77 55
78 # mullvad to miami 56 wg-quick.interfaces = {
79 wg-quick.interfaces.us-mia-wg-001 = { 57 # mullvad
80 address = [ 58 wg0 = {
81 "10.70.235.16/32" 59 address = [
82 "fc00:bbbb:bbbb:bb01::7:eb0f/128" 60 "10.75.226.117/32"
83 ]; 61 "fc00:bbbb:bbbb:bb01::c:e274/128"
84 privateKey = "***REDACTED_WG_KEY***="; 62 ];
85 63 privateKeyFile = config.age.secrets.wg0_hastur.path;
86 # supposed to be done by tailscale instead \_(:/)_/ 64
87 postUp = '' 65 peers = [{
88 ip route add 100.64.0.0/24 dev tailscale0 66 allowedIPs = [
89 ip route add 100.100.100.100/32 dev tailscale0 67 "0.0.0.0/0"
90 ''; 68 "::0/0"
91 postDown = '' 69 ];
92 ip route del 100.64.0.0/24 dev tailscale0 70 endpoint = "45.134.142.206:51820";
93 ip route del 100.100.100.100/32 dev tailscale0 71 publicKey = "H5t7PsMDnUAHrR8D2Jt3Mh6N6w43WmCzrOHShlEU+zw=";
94 ''; 72 }];
73 };
95 74
96 peers = [ 75 # epistemia
97 { 76 wg1 = {
98 allowedIPs = [ 77 address = [
99 "0.0.0.0/0" 78 "10.0.13.3/24"
100 "::0/0" 79 "fd00:b0ba:cafe:babe::3/64"
101 ]; 80 ];
102 endpoint = "45.134.142.219:51820"; 81 privateKeyFile = config.age.secrets.wg1_hastur.path;
103 publicKey = "FVEKAMJqaJU2AwWn5Mg9TK9IAfJc4XDUmSzEeC/VXGs="; 82
104 } 83 peers = [
105 ]; 84 # saklas
85 {
86 allowedIPs = [
87 "10.0.13.1/32"
88 "fd00:b0ba:cafe:babe::1/128"
89 ];
90 endpoint = "vineetk.net:51820";
91 persistentKeepalive = 25;
92 publicKey = "XvRailvccuc7LJIF4aaYM/MLkU4upiprwFlCfBllhl0=";
93 }
94 # demiurge (and lab through it)
95 {
96 allowedIPs = [
97 "10.0.13.2/32"
98 "10.0.13.5/32"
99 "fd00:b0ba:cafe:babe::2/128"
100 "fd00:b0ba:cafe:babe::5/128"
101 ];
102 endpoint = "carcosa.13f0.net:51820";
103 persistentKeepalive = 25;
104 publicKey = "FMLvbSxY6vA8CRV4S1vl4+pMeCr/kR9n0G5w9buNqh4=";
105 }
106 ];
107 };
106 }; 108 };
107 }; 109 };
108 110
@@ -126,8 +128,6 @@
126 isNormalUser = true; 128 isNormalUser = true;
127 129
128 extraGroups = [ 130 extraGroups = [
129 "kvm"
130 "libvirtd"
131 "transmission" 131 "transmission"
132 "wheel" 132 "wheel"
133 ]; 133 ];
@@ -135,7 +135,12 @@
135 shell = pkgs.zsh; 135 shell = pkgs.zsh;
136 136
137 openssh.authorizedKeys.keys = [ 137 openssh.authorizedKeys.keys = [
138 "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEvM0xCLziR+ZT/SYE1aZM6dklbw4fEC17TWqbADIZRH kou@demiurge" 138 "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEvM0xCLziR+ZT/SYE1aZM6dklbw4fEC17TWqbADIZRH vin@hastur"
139 ];
140
141 packages = with pkgs; [
142 acpi
143 acpilight
139 ]; 144 ];
140 }; 145 };
141 146
@@ -149,6 +154,8 @@
149 ]; 154 ];
150 155
151 pathsToLink = [ "/share/zsh" ]; 156 pathsToLink = [ "/share/zsh" ];
157
158 etc."wpa_supplicant.conf".source = config.age.secrets.wpa_supplicant.path;
152 }; 159 };
153 160
154 # enable bluetooth and add some udev rules 161 # enable bluetooth and add some udev rules
@@ -190,39 +197,57 @@
190 ]; 197 ];
191 }; 198 };
192 199
193 pki.certificates = [
194 ''
195 -----BEGIN CERTIFICATE-----
196 MIIBoDCCAUagAwIBAgIRANI8aOT3LE+pzmsQWjcDOIgwCgYIKoZIzj0EAwIwLjER
197 MA8GA1UEChMIZGVtaXVyZ2UxGTAXBgNVBAMTEGRlbWl1cmdlIFJvb3QgQ0EwHhcN
198 MjUwMjE4MDUzNTA5WhcNMzUwMjE2MDUzNTA5WjAuMREwDwYDVQQKEwhkZW1pdXJn
199 ZTEZMBcGA1UEAxMQZGVtaXVyZ2UgUm9vdCBDQTBZMBMGByqGSM49AgEGCCqGSM49
200 AwEHA0IABMv8weeXJSDLygVlBxxAHLCvQCdf2COCk0QffNeDaVlIU/NFo3IyPSqG
201 E3YtWEWamU/icgsJS999z3BZ5O+cTP6jRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNV
202 HRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBRM51S3OgTxXwNhdSSHw6llz0APFzAK
203 BggqhkjOPQQDAgNIADBFAiA9alHJ1XHLlKNRUGRL4tdFC3RZYHtoN8BmBHEfDa1S
204 LQIhANgsvYmyCp/Nur2RKaV25CDg3kMYVBXED2HVDy8qa+3i
205 -----END CERTIFICATE-----
206 ''
207 ];
208
209 sudo.enable = false; 200 sudo.enable = false;
210 }; 201 };
211 202
212 services = { 203 services = {
213 # dns 204 # dns
214 dnsmasq = { 205 unbound = {
215 enable = true; 206 enable = true;
216 settings = { 207 settings = {
217 server = [ 208 server = {
218 "/epistemia/100.100.100.100" 209 interface = [ "127.0.0.1" "10.0.13.2" "fd00:b0ba:cafe:babe::2" "::1" ];
219 "9.9.9.9" 210 access-control = [ "0.0.0.0/0 allow" "::0/0 allow" ];
220 ]; 211
212 hide-identity = yes;
213 hide-version = yes;
214
215 # Synthesize NXDOMAINs from DNSSEC NSEC chains.
216 # https://tools.ietf.org/html/rfc8198
217 aggressive-nsec = no;
218
219 local-zone = "saklas.epistemia." redirect;
220 local-data = "saklas.epistemia. 86400 IN A 10.0.13.1";
221 local-data = "saklas.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::1";
222 local-zone = "demiurge.epistemia." redirect;
223 local-data = "demiurge.epistemia. 86400 IN A 10.0.13.2";
224 local-data = "demiurge.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::2";
225 local-zone = "hastur.epistemia." redirect;
226 local-data = "hastur.epistemia. 86400 IN A 10.0.13.3";
227 local-data = "hastur.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::3";
228 local-zone = "iphonebob.epistemia." redirect;
229 local-data = "iphonebob.epistemia. 86400 IN A 10.0.13.4";
230 local-data = "iphonebob.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::4";
231 local-zone = "lab.epistemia." redirect;
232 local-data = "lab.epistemia. 86400 IN A 10.0.13.5";
233 local-data = "lab.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::5";
234 local-zone = "paraclete.epistemia." redirect;
235 local-data = "paraclete.epistemia. 86400 IN A 10.0.13.6";
236 local-data = "paraclete.epistemia. 86400 IN AAAA fd00:b0ba:cafe:babe::6";
237 };
238
239 # hagezi for dns-based adblocking (in addition to others)
240 rpz = {
241 name = "hagezi.ultimate";
242 zonefile = "hagezi.ultimate";
243 url = "https://raw.githubusercontent.com/hagezi/dns-blocklists/main/rpz/ultimate.txt";
244 };
221 245
222 interface = "lo"; 246 # go through mullvad for regular dns queries
223 listen-address = "127.0.0.1"; 247 forward-zone = {
224 bind-interfaces = true; 248 name = ".";
225 no-resolv = true; 249 forward-addr = [ "100.64.0.3" ];
250 };
226 }; 251 };
227 }; 252 };
228 253
@@ -258,33 +283,90 @@
258 # using pulseaudio and home-manager, so had to disable pulseaudio. 283 # using pulseaudio and home-manager, so had to disable pulseaudio.
259 pipewire = { 284 pipewire = {
260 enable = true; 285 enable = true;
286 alsa.enable = true;
287 audio.enable = true;
261 pulse.enable = true; 288 pulse.enable = true;
262 };
263 289
264 # vpn 290 extraConfig.pipewire = {
265 tailscale = { 291 "99-filter-airpods.conf" = {
266 enable = true; 292 "context.modules" = [
267 authKeyFile = config.age.secrets.tailscale_hastur.path; 293 {
268 extraDaemonFlags = [ "--no-logs-no-support" ]; 294 name = "libpipewire-module-filter-chain";
269 extraUpFlags = [ 295 args = {
270 "--login-server=https://headscale.13f0.net" 296 node.name = "peq-airpods-pro-2-sink";
271 "--advertise-exit-node" 297 node.description = "PEQ AirPods Pro 2 (auto)";
272 ]; 298 playback.props = {
273 openFirewall = true; 299 media.class = "Audio/Sink";
300 "filter.smart" = true;
301 "filter.smart.name" = "peq-airpods-pro-2";
302 };
303 filter.graph = [
304 {
305 type = "builtin";
306 name = "param_eq";
307 label = "param_eq_airpods";
308 config.filename = "/etc/pipewire/parametric/airpods-pro-2.txt";
309 }
310 ];
311 };
312 }
313 ];
314 };
315 };
316
317 # TODO run nixfmt to fix indenting of below (can't right now because on gentoo without nixfmt)
318 wireplumber = {
319 enable = true;
320 extraConfig."50-smartfilters-airpods.conf".text = ''
321 {
322 "monitor.bluez.rules" : [
323 # When a BlueZ device is detected we set an identifying property that the smart filter will match.
324 # (This fragment adds nothing by default; we're using a policy to match target.node later.)
325 ],
326
327 "policy.rules" : [
328 # The core smart filter matching is done by matching the target.node properties
329 # WirePlumber's smart filters will look for filter.smart.target (set below).
330 ],
331
332 "policy" : {
333 "smart_filters" : {
334 "rules" : [
335 {
336 "matches" : [
337 { "device.props" : { "bluez5.device.name" : "AirPods Pro 2" } }
338 ],
339 "actions" : {
340 # If target device matches, set the 'target.node' metadata for smart filters to use
341 "update-metadata" : {
342 "target.node" : { "name" : "bluez_output.*AirPods.*" }
343 }
344 }
345 }
346 ]
347 }
348 },
349
350 "endpoint.rules" : [
351 {
352 "matches" : [
353 { "node.name" : "peq-airpods-pro-2-sink" }
354 ],
355 "actions" : {
356 "update-props" : {
357 "filter.smart.target" : { "bluez5.device.name" : "AirPods Pro 2" }
358 }
359 }
360 }
361 ]
362 }
363 '';
364 };
274 }; 365 };
275 366
276 # enable better power management 367 # enable better power management
277 tlp.enable = true; 368 tlp.enable = true;
278 369
279 # udev rules
280 udev = {
281 enable = true;
282 extraRules = ''
283 # ST-Link v2.1
284 SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE:="0666"
285 '';
286 };
287
288 # to get startx and use amdgpu driver 370 # to get startx and use amdgpu driver
289 # WM in home-manager 371 # WM in home-manager
290 xserver = { 372 xserver = {
@@ -295,6 +377,11 @@
295 }; 377 };
296 }; 378 };
297 379
380 systemd.services."wg-quick@wg1" = {
381 after = [ "wg-quick@wg0.service" ];
382 requires = [ "wg-quick@wg0.service" ];
383 };
384
298 # create caches and use mandoc 385 # create caches and use mandoc
299 documentation.man = { 386 documentation.man = {
300 enable = true; 387 enable = true;
@@ -303,11 +390,5 @@
303 mandoc.enable = true; 390 mandoc.enable = true;
304 }; 391 };
305 392
306 # virtualization stuff
307 virtualisation.podman = {
308 enable = true;
309 dockerCompat = true;
310 };
311
312 system.stateVersion = "24.05"; 393 system.stateVersion = "24.05";
313} 394}