Compare commits

...

314 Commits

Author SHA1 Message Date
aeb2f63d65 impermanence: defer to fs.nix module for permissions & dir creation 2022-12-31 00:38:15 +00:00
528ffdb58e add a new 'fs.nix' file i'll use to factor the impermanence stuff better 2022-12-30 14:45:34 +00:00
b6887b305e impermanence: split out the root-on-tmpfs stuff 2022-12-30 04:35:34 +00:00
08dfc80c98 impermanence: split out sops setup 2022-12-30 04:31:24 +00:00
5a273213f6 sops: remove sops.age.sshKeyPaths override: sops gets this from openssh config already 2022-12-30 03:49:31 +00:00
0a6d88dfc1 impermanence: simplify /etc/ssh/host_keys setup 2022-12-30 03:34:59 +00:00
50dfd482cf document plans for better handling of /etc/ssh 2022-12-29 19:19:51 +00:00
9743aee79d ssh keys: document the issues i'm seeing 2022-12-29 18:42:59 +00:00
0819899102 remove dead commented-out code 2022-12-29 18:34:03 +00:00
d3ff68217e impermanence: enable hyphenated folder names 2022-12-29 18:29:27 +00:00
1a96859994 impermanence: re-enable mpv watch_later dir 2022-12-29 18:10:40 +00:00
af92a2250e impermanence: fix up circular dependencies and permissions
this is now a proof of concept. still has some rough edges.
2022-12-29 18:03:41 +00:00
d00f9b15d7 impermanence: fix typo in permissions service 2022-12-29 17:16:27 +00:00
aa1c1f40cb WIP: impermanence rework (gut 3rd-party lib) 2022-12-29 16:38:58 +00:00
530b2d6385 impermanence: factor out some helpers for generating fileSystems and services 2022-12-29 08:42:15 +00:00
e6919dd16f impermanence: use systemd/fileSystems for the crypt mounts, instead of 3rd-party impermanence 2022-12-29 01:17:40 +00:00
760f2ac66d move ~/.cache into encrypted private dir 2022-12-29 01:17:40 +00:00
8e5ca11259 cleanup gocryptfs mounting
there's possibly some latent issues. i think my changes to the gocryptfs
package *might* not be necessary: if you work via the fuse front-door,
it's a lot harder to get it into these weird places.
2022-12-29 01:17:40 +00:00
121936620a impermanence: add support for encrypted clear-on-boot storage
this is useful for when we need to store files to disk purely due to
their size, but don't actually want them to be persisted.
2022-12-29 01:17:40 +00:00
f5b49e014c net: add parent's wifi 2022-12-29 00:57:36 +00:00
4bdb34775d consolidate filesystems./ across devices 2022-12-28 01:36:22 +00:00
f5fbc206f5 package signaldctl (partially tested)
it includes an extra `bin/generator` output: i'm not sure if this is
necessary yet or not.
2022-12-28 00:48:44 +00:00
a9096f3312 sane-scripts: remove /run/wrappers hack now that prologue is fixed in resholve 2022-12-26 10:02:51 +00:00
67cddecab4 Merge branch 'staging/nixpkgs-2022-12-22' 2022-12-26 09:30:21 +00:00
9a002c99eb python-data template: add requests module 2022-12-26 09:29:23 +00:00
a0ac7fa98d snippets: add secret snippets 2022-12-26 09:29:04 +00:00
b03043e513 add sane-bt-search script to search jackett/torrents 2022-12-26 09:05:26 +00:00
0713e3bad1 secrets: move bluetooth/vpn secret defn to toplevel nix file 2022-12-26 08:28:44 +00:00
d3a3f39756 move universal secrets out of net.nix -> secrets.nix 2022-12-26 08:09:58 +00:00
a7d9e5cc54 flake update: nixpkgs 2022-12-18 -> 2022-12-22
```
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/04f574a1c0fde90b51bf68198e2297ca4e7cccf4' (2022-12-18)
  → 'github:NixOS/nixpkgs/652e92b8064949a11bc193b90b74cb727f2a1405' (2022-12-22)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/cbe419ed4c8f98bd82d169c321d339ea30904f1f' (2022-12-20)
  → 'github:NixOS/nixpkgs/dac57a4eccf1442e8bf4030df6fcbb55883cb682' (2022-12-24)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/32840f16ffa0856cdf9503a8658f2dd42bf70342' (2022-12-19)
  → 'github:Mic92/sops-nix/855b8d51fc3991bd817978f0f093aa6ae0fae738' (2022-12-25)
• Updated input 'sops-nix/nixpkgs-stable':
    'github:NixOS/nixpkgs/87b58217c9a05edcf7630b9be32570f889217aef' (2022-12-19)
  → 'github:NixOS/nixpkgs/939c05a176b8485971463c18c44f48e56a7801c9' (2022-12-24)
```
2022-12-26 05:19:58 +00:00
13f3b322b0 alias to cd ~/Videos 2022-12-26 04:40:21 +00:00
5c25330891 packages: add nheko matrix client 2022-12-26 03:52:04 +00:00
dc6dc2e475 discord: remove the SKIP_HOST_UPDATE hack. it's been upstreamed 2022-12-26 03:30:25 +00:00
c4352fa9bb packages: move Signal, Discord, Tokodon to private storage 2022-12-26 03:26:50 +00:00
2c6629a658 packages: allow specifying multiple dir and private paths 2022-12-26 03:02:19 +00:00
c0496b25b5 init-keyring: try to make atomic 2022-12-25 12:02:33 +00:00
9e0346c329 snippets: update jackett to be a search query 2022-12-25 08:43:29 +00:00
364a598324 pkgs: clean up the imports to not explicitly pass pkgs 2022-12-25 07:33:24 +00:00
c6850aff23 ship fractal-latest (git tip) instead of fractal-next 2022-12-25 07:23:09 +00:00
730ef272d1 feeds: add put a num on it; remove Kaiteki code feed 2022-12-25 03:39:44 +00:00
16fa1e0eda sane-date-math: convert to LR parser 2022-12-24 05:08:17 +00:00
51a96525d9 sane-date-math: use Productions as objects 2022-12-24 01:17:19 +00:00
7b01822ee7 some kind of sane-date-math date/time util thing. idk, parsers are fun ig 2022-12-23 15:57:56 +00:00
f9aa36a620 flake update: nixos-stable 2022-12-17 -> 2022-12-20
```

• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/0938d73bb143f4ae037143572f11f4338c7b2d1c' (2022-12-17)
  → 'github:NixOS/nixpkgs/cbe419ed4c8f98bd82d169c321d339ea30904f1f' (2022-12-20)
```
2022-12-22 22:45:27 +00:00
9b75d8705b ejabberd: enable push notifications (verified working on iOS/Modal IM) 2022-12-22 14:12:15 +00:00
217ecec250 ejabberd: enable xmpps-{client,server} SRV records 2022-12-22 13:13:09 +00:00
6c7ca7630a zsh: add tmp alias for ~/tmp 2022-12-22 11:35:35 +00:00
1f99d44288 /home/colin: fix perms to 0700 2022-12-22 11:33:13 +00:00
f1aa685a03 fix p10k variable expansion 2022-12-22 11:00:49 +00:00
2b31fc8776 powerlevel10k: always show user/host 2022-12-22 10:58:02 +00:00
0c35e2b3c1 servo: enable nsncd 2022-12-22 10:34:47 +00:00
77b8d0ddc0 fuzzel: tune dialog widths 2022-12-22 10:10:03 +00:00
84f23c602e new snipper: nixos options search 2022-12-22 10:06:55 +00:00
ea5fbc63cf zsh/p10k: selectively disable gitstatus acceleration on ~/private/ 2022-12-21 14:13:20 +00:00
69361ee9a2 zsh: document prezto modules, switch dir aliases to dirHashes 2022-12-21 13:53:22 +00:00
1808d153b2 zsh: configure p10k 2022-12-21 13:08:23 +00:00
b3ad0f8f1f update ~/knowledge to live in ~/private 2022-12-21 08:52:27 +00:00
c745612cfd Merge branch 'master' of git.uninsane.org:colin/nix-files 2022-12-21 08:51:12 +00:00
278cc98c6d minor ejabberd config changes, simplify DNS %NATIVE% updating 2022-12-21 08:50:41 +00:00
fac661af15 new script: sane-git-init 2022-12-21 08:40:22 +00:00
65777c70ad snippets: add link to home-manager docs 2022-12-21 08:30:16 +00:00
09c524a5b1 Merge remote-tracking branch 'origin/staging/nixpkgs-2022-12-18' 2022-12-21 07:47:55 +00:00
0db7f0857a moby: reduce the number of configurations we keep in /boot 2022-12-21 06:33:50 +00:00
38befe502c new script to free space in /boot 2022-12-21 06:29:13 +00:00
55e09c2dbf ejabberd: port to dns-dns; add experimental STUN/TURN support
during startup it says:
```
Ignoring TLS-enabled STUN/TURN listener
```

and later
```
Invalid certificate in /var/lib/acme/uninsane.org/fullchain.pem: at line 61: certificate is signed by unknown CA
```

the invalid cert thing has always been here. it's for the root cert. idk
if i need to tell ejabberd that one's self-signed, or what.
2022-12-20 03:26:08 +00:00
bd699c887c sane-ssl-dump: new script to help debug ssl stuff 2022-12-20 03:25:07 +00:00
2de6f7d364 fix i2p to build on aarch64 2022-12-20 03:10:05 +00:00
d60e5264f3 don't bind-mount /etc/ssh/host_keys: symlink them instead 2022-12-20 00:04:09 +00:00
c66699b697 update nixpkgs: 2022-12-11 -> 2022-12-18; sops-nix
```
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/64e0bf055f9d25928c31fb12924e59ff8ce71e60' (2022-12-11)
  → 'github:NixOS/nixpkgs/04f574a1c0fde90b51bf68198e2297ca4e7cccf4' (2022-12-18)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/06278c77b5d162e62df170fec307e83f1812d94b' (2022-12-12)
  → 'github:NixOS/nixpkgs/0938d73bb143f4ae037143572f11f4338c7b2d1c' (2022-12-17)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/da98a111623101c64474a14983d83dad8f09f93d' (2022-12-04)
  → 'github:Mic92/sops-nix/32840f16ffa0856cdf9503a8658f2dd42bf70342' (2022-12-19)
• Updated input 'sops-nix/nixpkgs-stable':
    'github:NixOS/nixpkgs/86370507cb20c905800527539fc049a2bf09c667' (2022-12-04)
  → 'github:NixOS/nixpkgs/87b58217c9a05edcf7630b9be32570f889217aef' (2022-12-19)
```
2022-12-19 22:42:58 +00:00
97044bf70e trust-dns: port to dyn-dns for determining WAN IP
although the systemd wantedBy directive is working,
`before` seems to be ignored when the unit fails. so on first run,
dyn-dns runs, fails (poor net connectivity), then trust-dns starts
(fails), then they both restart 10s later.

it's not great, but good enough. also, wan IP is persisted, so this
likely won't happen much in practice.
2022-12-19 13:12:23 +00:00
3122334a41 dyn-dns: fix to only react when the IP actually changes 2022-12-19 11:54:27 +00:00
0b2faef989 /etc/ssh/host_keys: fix endlessly stacked mounts
i believe this was mounting a new /etc/ssh/host_keys on every
activation, resulting in literally thousands of mounts and slowing down
later activations
2022-12-19 11:18:08 +00:00
8acd6ca4f1 create sane.services.dyn-dns to manage dynamic DNS stuff
not yet integrated into servo
2022-12-19 11:16:30 +00:00
8169f7c6b2 ddns-trust-dns: use ddns from router rather than ipinfo.io 2022-12-19 08:24:11 +00:00
cd1aa0b376 sane-vpn-*: reference sane-ip-check instead of duplicating 2022-12-19 06:19:13 +00:00
72b627100c sane-scripts: simplify recursively referencing sane scripts 2022-12-19 06:18:44 +00:00
567c08460a add sane-ip-check-router-wan to query WAN with a more trustworthy source 2022-12-19 05:59:44 +00:00
9b66aecf1b trust-dns: port the remaining records to a structured format
SRV and MX _could_ have more structure (priority, etc).
not sure the best path there (option submodule, i guess).
2022-12-19 04:38:43 +00:00
16cb3b83a2 trust-dns: more idiomatic way to define SOA records 2022-12-19 04:00:27 +00:00
970438be8a trust-dns: rename records option -> extraConfig
i'll be adding special options for records
2022-12-19 03:12:32 +00:00
51da29555e sane-ip-reconnect: fix issue where we'd reconnect to the existing, subpar network 2022-12-19 01:47:30 +00:00
8a745a9b8a ejabberd: enable STUN (with partial discovery support)
discovery is probably not working:
```
Won't auto-announce STUN/TURN service on port 3478 (udp) without public IP address, please specify 'turn_ipv4_address' and optionally 'turn_ipv6_address'
Won't auto-announce STUN/TURN service on port 3478 (tcp) without public IP address, please specify 'turn_ipv4_address' and optionally 'turn_ipv6_address'
```

no messages for the TLS implementation, so maybe that's working?
2022-12-19 01:22:20 +00:00
3505f3b9f3 ejabberd: provision cert for conference.xmpp.uninsane.org
i guess the cert already had that because of legacy prosody setup (?),
but we weren't setup so that new requests would work, i expect.

either that or all of these nginx entries aren't necessary?
2022-12-19 01:22:20 +00:00
444595e847 disable HE and afraid DDNS 2022-12-19 01:22:20 +00:00
3e1407c30b new script to reconnect to best wifi network 2022-12-19 00:29:48 +00:00
0a744117a4 rename sane-check-ip -> sane-ip-check 2022-12-18 23:54:41 +00:00
a2935cedaa snippets: add wikipedia search 2022-12-18 22:58:53 +00:00
22e46d52c2 trust-dns: distribute records across service files 2022-12-17 01:29:12 +00:00
1e0c213adf split webconfig into each service file 2022-12-17 00:52:48 +00:00
3e1340ed61 enable i2p in firefox 2022-12-16 22:15:19 +00:00
341dd3f2b2 new zsh alias: ref -> cd ~/ref 2022-12-16 20:56:48 +00:00
1c9caa40bd snippets: update nixos wiki to include search param 2022-12-16 20:35:33 +00:00
3be15c6d05 podcasts: add Michael Malice (is it any good? we'll see.) 2022-12-16 08:04:28 +00:00
8e8168ec28 add splatmoji package and sway config 2022-12-16 07:46:06 +00:00
28397807fc gpt2tc: disable, because the mirror is unreliable 2022-12-16 07:08:55 +00:00
42ebb9a155 sane-private-do: run a command with the private store unlocked; then re-lock it 2022-12-16 06:10:44 +00:00
a8a4b8e739 kiwix: serve the full english Wikipedia 2022-12-16 05:58:51 +00:00
2550601179 serve w.uninsane.org through kiwix-serve 2022-12-16 02:25:57 +00:00
199a49755a create a kiwix-serve service 2022-12-16 02:15:17 +00:00
8c7700688f nixpatches: add kiwix-tools package that's being upstreamed 2022-12-16 01:22:38 +00:00
8fe304d6c1 trust-dns: split the service into a generic config interface 2022-12-15 11:17:50 +00:00
700fef7df3 servo: mediawiki: remove dead commented-out code 2022-12-15 11:17:50 +00:00
01db7e1f23 servo: install mediawiki 2022-12-15 11:17:50 +00:00
df6e8f1562 Merge branch 'master' of git.uninsane.org:colin/nix-files 2022-12-15 09:59:53 +00:00
1f0a40c81f snippets: add nixos wiki 2022-12-15 09:54:32 +00:00
995b41d1e8 flake: update nixpkgs-stable 22.05 -> 22.11 2022-12-14 22:32:41 +00:00
7674735d42 Merge branch 'master' of git.uninsane.org:colin/nix-files 2022-12-14 12:28:58 +00:00
329693c9ce pin grpc & users, until the grpc aarch64 build is fixed 2022-12-14 12:27:24 +00:00
5ae3bb2f6c sane-rcp: allow a destination 2022-12-14 10:07:02 +00:00
e0b1aef127 snippets: add sci-hub 2022-12-14 09:52:07 +00:00
9b8363dfb4 firefox addons: bypass-paywalls-clean: update hash 2022-12-14 08:00:42 +00:00
58ad87df8e vpns: add us-mi[ami] 2022-12-13 04:26:00 +00:00
5fc894cda9 vpn: fix us-atlanta -> us-atl to match interface length limit 2022-12-13 04:13:01 +00:00
07e6ec2533 sane-scripts: better vpn factoring 2022-12-13 04:11:58 +00:00
005a79e680 vpn: factor out more helpers 2022-12-13 03:55:18 +00:00
0f5279bbca add us-atlanta VPN 2022-12-13 03:26:23 +00:00
e9b3b7ebab simplify ovpn impl 2022-12-13 03:17:27 +00:00
7a83c1d6df trust-dns: use upstream build 2022-12-13 02:03:09 +00:00
46788fe565 servo: make uninsane.org NS records consistent with upstream 2022-12-13 01:00:16 +00:00
a473ef6db3 flake update: nixpkgs: 2022-12-02 -> 2022-12-11; others
```
• Updated input 'mobile-nixos':
    'github:nixos/mobile-nixos/25eec596116553112681d72ee4880107fc3957fa' (2022-11-19)
  → 'github:nixos/mobile-nixos/5ee45cc1f8e43f4af14ee17ccef9156b0db8cd77' (2022-12-04)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/b72b8b94cf0c012b0252a9100a636cad69696666' (2022-12-02)
  → 'github:NixOS/nixpkgs/64e0bf055f9d25928c31fb12924e59ff8ce71e60' (2022-12-11)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/5d7d1d5f742e6bb57dd2e3d7b433fb4010c7af22' (2022-12-02)
  → 'github:NixOS/nixpkgs/7b9eeb856cbf976482fa8d1cb295ea03fb3e1277' (2022-12-10)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/8295b8139ef7baadeb90c5cad7a40c4c9297ebf7' (2022-11-29)
  → 'github:Mic92/sops-nix/da98a111623101c64474a14983d83dad8f09f93d' (2022-12-04)
• Removed input 'sops-nix/nixpkgs-22_05'
• Added input 'sops-nix/nixpkgs-stable':
    'github:NixOS/nixpkgs/86370507cb20c905800527539fc049a2bf09c667' (2022-12-04)
```
2022-12-13 00:52:54 +00:00
3627d47f12 firefox: add uBlacklist 2022-12-13 00:44:38 +00:00
115f8d7054 servo: vpn services are part of 'wireguard-wg0'
this makes it so if we restart the wireguard connection, the services
themeselves _also_ restart. that should avoid leaving any of them in an
orphaned namespace
2022-12-12 11:53:34 +00:00
ac44b04d99 servo: trust-dns: note about maybe using dig instead of diff'ing the config 2022-12-12 11:35:47 +00:00
afff0aff19 servo: trust-dns: fix up the timers/ddns reliability 2022-12-12 11:33:20 +00:00
f0086dc5bd servo: trust-dns: implement some dynamic DNS shim 2022-12-12 10:30:08 +00:00
acabd34f28 servo: net: forward http requests from vpn -> host w/o NATing the source address
this ensures we have access to the source IP in our host-side logs
2022-12-12 05:21:29 +00:00
d0e6b82739 make it so wireguard-wg0 is restartable 2022-12-11 17:07:53 +00:00
dc09b7b9b2 Merge branch 'master' of git.uninsane.org:colin/nix-files 2022-12-11 16:48:16 +00:00
38c5b82a08 servo: fold wg0 setup into one single service
it doesn't restart cleanly (maybe i can't kill a netns while stuff lives
inside it?). problem for another day.
2022-12-11 16:46:55 +00:00
89def1a073 servo: remove dead net code 2022-12-11 16:15:43 +00:00
ad2ed370d9 servo: split the firewall rules across services 2022-12-11 16:12:23 +00:00
3e8f7a9ba2 servo: use ISP-provided DNS resolvers by default
this is really hacky and i hate it, but there's not a lot of good
options.
2022-12-11 16:03:41 +00:00
028ecfe93f snippets: add HN 2022-12-11 13:14:24 +00:00
c5ac792c13 servo: connect wg0 via IP addr instead of hostname
i think this fixes the connectivity issues i've seen.
2022-12-11 12:48:50 +00:00
bd1624bef9 servo: un-firewall tcp port 53 to fix trust-dns over TCP 2022-12-11 12:48:11 +00:00
3ae53d7f32 services: add RestartSec to anything which auto-restarts
this is to prevent rapid restart failures from killing the service
permanently.
2022-12-10 13:28:46 +00:00
e7f2d41b1f servo: forward DNS to root ns without NAT'ing the source address 2022-12-10 13:28:19 +00:00
3394a79e2b trust-dns: restart on failure
if the network isn't up, won't be able to bind to eth, and fails.
2022-12-10 13:02:17 +00:00
b01501663d trust-dns: listen on each address explicitly 2022-12-10 12:29:10 +00:00
cbd5ccd1c8 desko: disable wifi 2022-12-10 12:27:02 +00:00
cf857eaf9f zsh: more cd aliases (knowledge, secrets) 2022-12-10 12:16:16 +00:00
3a7eb294c7 servo: fix jackett DNS entry 2022-12-10 09:47:28 +00:00
2ccb470adc packages: add tcpdump 2022-12-10 02:56:00 +00:00
0a2a929507 Merge branch 'master' of git.uninsane.org:colin/nix-files 2022-12-09 14:18:40 +00:00
2014d5ce77 servo: bridge port 80/53 from ovpns to native using iptables instead of socat
i should probably narrow the rules to match specifically things destined
for the ovpns address, but for now this should work.
2022-12-09 14:16:48 +00:00
041adb7092 snippets: add nixos search URL 2022-12-09 01:25:24 +00:00
a979521a98 servo: enable ddns against freedns.afraid.org 2022-12-08 14:30:17 +00:00
77881be955 trust-dns: document SOA parameters 2022-12-08 14:23:35 +00:00
0450b4d9a6 trust-dns: fix SOA 2022-12-08 00:46:32 +00:00
edea64a41c trust-dns: move nameserver to subdomain ns1,ns2 2022-12-08 00:39:22 +00:00
90e479592f trust-dns: enable port 53 forward 2022-12-08 00:06:20 +00:00
62d83d94f2 add script to query public IP 2022-12-07 23:39:20 +00:00
52bbe4e9f4 trust-dns: don't restart on failure
for in case anything goes wrong
2022-12-07 12:17:03 +00:00
ab176b8d4b servo: enable trust-dns (experimental) 2022-12-07 12:15:35 +00:00
62df4492a3 Merge branch 'master' of git.uninsane.org:colin/nix-files 2022-12-07 09:47:03 +00:00
f4ed194abc package trust-dns 2022-12-07 09:45:11 +00:00
6420c9fd16 packages: add gajim (at least temporarily, for debugging) 2022-12-07 08:02:14 +00:00
86245b460b Merge branch 'master' of git.uninsane.org:colin/nix-files 2022-12-07 07:41:58 +00:00
bf1ba786b3 packages: add imagemagick (for convert) 2022-12-07 07:41:05 +00:00
35a896a3e2 shell aliases to cd to common places 2022-12-07 07:40:52 +00:00
b4314bd919 mess with XMPP stuff. ejabberd: enable mam, some other acl's that probably aren't used
prosody is still broken
2022-12-07 01:31:17 +00:00
4696209822 nixpatches: update aerc fix hash 2022-12-07 01:14:24 +00:00
c3957d81c2 ejabberd: enable MUC 2022-12-07 00:08:08 +00:00
8a5be00c93 sway: define a "snippets.txt" file for e.g. browser bookmarks 2022-12-06 11:12:27 +00:00
c2db9fe28e periodically archive my torrents so i don't lose them again 2022-12-06 07:17:19 +00:00
ccaac901f7 Merge branch 'master' of git.uninsane.org:colin/nix-files 2022-12-06 07:06:32 +00:00
7f285a8254 ejabberd: enable some more modules which don't conflict 2022-12-06 07:05:59 +00:00
b0b82a3d88 feeds: add Matrix Live podcast
haven't listened. just searching.
2022-12-06 06:58:59 +00:00
b0664d81ab ejabberd: enable mod_pubsub, mod_avatar
i'm able to do this without breaking federation now,
but it doesn't seem to fullly work.
2022-12-05 02:37:35 +00:00
8ba52bb9cd ejabberd: enable mod_{carboncopy,last,offline,private,stream_mgmt} 2022-12-05 02:16:28 +00:00
20f0a19e25 ejabberd: fix federation: disable mod_pubsub and mod_avatar
now i can send messages FROM uninsane.org again
2022-12-05 00:47:48 +00:00
9dc17a3874 ejabberd: enable avatar support
haven't tested that it federates properly -- only that Dino is able to
set it.
2022-12-04 12:38:47 +00:00
2992644901 bluetooth: persist bluetooth earbuds connection 2022-12-04 11:33:03 +00:00
d5d89a10b9 bluetooth: add key for connecting to my car 2022-12-04 10:56:50 +00:00
f7d9fdfe04 packages: add pstree 2022-12-04 03:42:54 +00:00
c42aa2847b aerc: apply patch to fix awk / message reading 2022-12-04 02:48:37 +00:00
768c5c910f update nixpkgs: 2022-11-27 -> 2022-12-02
```
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/a115bb9bd56831941be3776c8a94005867f316a7' (2022-11-27)
  → 'github:NixOS/nixpkgs/b72b8b94cf0c012b0252a9100a636cad69696666' (2022-12-02)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/fecf05d4861f3985e8dee73f08bc82668ef75125' (2022-11-27)
  → 'github:NixOS/nixpkgs/5d7d1d5f742e6bb57dd2e3d7b433fb4010c7af22' (2022-12-02)
```
2022-12-03 22:56:00 +00:00
8790a7d9fd note about persisting bluetooth config 2022-12-03 11:35:03 +00:00
7c36a0d522 bluetooth: share connections across machines 2022-12-03 11:05:09 +00:00
977a80d59e Merge branch 'staging/moby-6.1.0-rc7' 2022-12-03 09:05:13 +00:00
63c92a44ed servo: ejabberd: enable file uploads 2022-12-03 08:57:10 +00:00
bf838ea203 packages: add tree as system package 2022-12-03 08:56:26 +00:00
e8a7a1dc75 moby: upgrade kernel 6.0.2 -> 6.1.0-rc7 2022-12-03 08:41:38 +00:00
992efc1093 moby: persist pulseaudio volume status 2022-12-03 07:30:09 +00:00
d320fa39f3 packages: move gpt2tc to x86-only group
it doesn't support arm
2022-12-03 07:29:53 +00:00
e40156ed9a RSS: add Peter Saint-Andre 2022-12-03 06:31:29 +00:00
656837c810 add gpt2tc package for gpt-2 generation 2022-12-03 06:31:29 +00:00
0533ea1cc2 add awk as a system-level package 2022-12-03 06:31:29 +00:00
a1911f3001 ejabberd: fix TLS config (now successfully federating!)
TODO: verify file uploading
TODO: wire up admin panel
2022-12-03 02:16:29 +00:00
24967c53a7 servo: disable ipfs 2022-12-02 08:33:50 +00:00
8b9c18aee1 firefox: update plugin hashes 2022-12-02 04:23:20 +00:00
8d3acb104a sublime-music: ship the mobile fork
it *works* on Desktop. it's not *perfect*, but likely better than the
non-mobile one.
2022-12-02 01:24:51 +00:00
69eacf6c4d ship strace on all platforms 2022-12-02 01:02:08 +00:00
d7ad414a9c package a mobile-friendly fork of sublime-music (untested) 2022-12-01 22:03:13 +00:00
533b0a91bd remove unused vim package: nabla 2022-12-01 21:05:23 +00:00
56d87da650 feeds: add pomeroyb 2022-12-01 19:00:08 +00:00
3f33b2cb76 nginx: supply x509 certs for assorted websites under /var/www/sites 2022-11-30 11:37:37 +00:00
f8a1df790f servo: allow hosting arbitrary websites by stashing them in /var/www 2022-11-30 05:33:04 +00:00
e94186e9c9 Merge branch 'staging/nixpkgs-2022-11-27' 2022-11-30 05:15:03 +00:00
82d11a7ae1 nginx: note that OCSP stapling isn't actually working 2022-11-30 02:09:35 +00:00
0253774622 add templates.python-data
for more info, see
<https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake-init.html>
2022-11-30 00:48:27 +00:00
2f45c57310 nix flake update: nixpkgs 2022-11-21 -> 2022-11-27, others
```
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/af50806f7c6ab40df3e6b239099e8f8385f6c78b' (2022-11-21)
  → 'github:NixOS/nixpkgs/a115bb9bd56831941be3776c8a94005867f316a7' (2022-11-27)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/cf63ade6f74bbc9d2a017290f1b2e33e8fbfa70a' (2022-11-20)
  → 'github:NixOS/nixpkgs/fecf05d4861f3985e8dee73f08bc82668ef75125' (2022-11-27)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/f72e050c3ef148b1131a0d2df55385c045e4166b' (2022-11-20)
  → 'github:Mic92/sops-nix/8295b8139ef7baadeb90c5cad7a40c4c9297ebf7' (2022-11-29)
• Updated input 'sops-nix/nixpkgs-22_05':
    'github:NixOS/nixpkgs/b68a6a27adb452879ab66c0eaac0c133e32823b2' (2022-11-20)
  → 'github:NixOS/nixpkgs/6649e08812f579581bfb4cada3ba01e30485c891' (2022-11-27)
```
2022-11-29 23:12:43 +00:00
5d1e8f5f60 servo: store media on external storage 2022-11-29 21:54:33 +00:00
ff9c26b03d servo: port to Ryzen/x86 machine 2022-11-29 02:20:18 +00:00
b9533d7ee3 packages: ship some tools useful for debugging boot/HW state 2022-11-29 02:18:56 +00:00
103f7b1b2c sane-stop-all-servo script: update for currently deployed services 2022-11-29 02:18:31 +00:00
16327fd323 nix patches: fix hashes 2022-11-29 02:18:05 +00:00
abcfa2dbea update phosh: phosh: 0.21.1 -> 0.22.0 2022-11-26 08:13:52 +00:00
27403fa36d zecwallet: move data to private dir 2022-11-24 17:47:34 +00:00
96b3ac26dd remove systemd HDD spindown patch
i haven't used this for several months. it doesn't seem to matter, and
maintaining custom systemd patches is very impractical.
2022-11-24 10:28:06 +00:00
1accf264cf browserpass-extension: update the PR which generalizes file extensions 2022-11-24 10:26:32 +00:00
3772a428da browserpass: apply PR feedback: <https://github.com/browserpass/browserpass-extension/pull/312> 2022-11-23 12:59:08 +00:00
a56f2008d3 fix 'nixserv' -> 'nixserve' typo 2022-11-23 04:09:58 +00:00
04ea55499a gocryptfs: don't cross build 2022-11-22 13:46:44 +00:00
59244fa50c flake update: nixpkgs 2022-11-09 -> 2022-11-21, others
```
• Updated input 'impermanence':
    'github:nix-community/impermanence/def994adbdfc28974e87b0e4c949e776207d5557' (2022-08-31)
  → 'github:nix-community/impermanence/5df9108b346f8a42021bf99e50de89c9caa251c3' (2022-11-17)
• Updated input 'mobile-nixos':
    'github:nixos/mobile-nixos/0b69b36c989d13f08c3bc563253f68c9d6ed7244' (2022-11-01)
  → 'github:nixos/mobile-nixos/25eec596116553112681d72ee4880107fc3957fa' (2022-11-19)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/872fceeed60ae6b7766cc0a4cd5bf5901b9098ec' (2022-11-09)
  → 'github:NixOS/nixpkgs/af50806f7c6ab40df3e6b239099e8f8385f6c78b' (2022-11-21)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/fa842715565307b7e05cdb187b08c05f16ed08f1' (2022-11-09)
  → 'github:NixOS/nixpkgs/cf63ade6f74bbc9d2a017290f1b2e33e8fbfa70a' (2022-11-20)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/4407353739ad74a3d9744cf2988ab10f3b83e288' (2022-11-06)
  → 'github:Mic92/sops-nix/f72e050c3ef148b1131a0d2df55385c045e4166b' (2022-11-20)
• Updated input 'sops-nix/nixpkgs-22_05':
    'github:NixOS/nixpkgs/6440d13df2327d2db13d3b17e419784020b71d22' (2022-10-30)
  → 'github:NixOS/nixpkgs/b68a6a27adb452879ab66c0eaac0c133e32823b2' (2022-11-20)
```
2022-11-22 12:03:33 +00:00
c2a2b27002 servo: disable duplicity 2022-11-22 12:01:55 +00:00
7bd6015a9f browserpass: start pushing gpg-agnostic support upstream 2022-11-22 11:50:07 +00:00
2a010f7882 readme: update contact info, explain modules/ dir 2022-11-22 05:34:11 +00:00
b566910da0 home-manager: hide behind an enable flag 2022-11-22 05:28:41 +00:00
ca43811c16 remove sane.home-manager.extraPackages
replaced by sane.packages.extraUserPkgs
2022-11-22 05:11:02 +00:00
7284452aa5 re-enable some environment stuff that got lost during refactors 2022-11-22 04:51:03 +00:00
f772300d88 move system-packages into the main packages.nix file 2022-11-22 04:40:24 +00:00
eccb5ff3d6 rename home-packages -> packages 2022-11-22 04:31:55 +00:00
0c6b949a72 lift some more files out of modules -> hosts 2022-11-22 04:29:17 +00:00
9a6c83776d vpn: move out of modules/ 2022-11-22 03:46:25 +00:00
e408e77026 move secrets.nix out of modules 2022-11-22 03:37:57 +00:00
e0612ccfa8 move allocations out of universal
it doesn't cause any changes to the system
2022-11-22 03:35:11 +00:00
a0e85ff31b nixserve: remove the default sops path
it might make more sense to make this a runtime path (/run/secrets/...)
2022-11-22 03:20:50 +00:00
1d448a4114 migrate common settings from hosts/{instantiate -> common/default}.nix 2022-11-22 03:10:19 +00:00
ed52b5f251 nixcache: modularize 2022-11-22 03:07:11 +00:00
dc21b0d68c modularize image.nix image building 2022-11-22 03:02:41 +00:00
18ec4f9b4d browserpass-extension: update to latest tip
my PR got merged
2022-11-22 02:59:25 +00:00
84a17f4599 move hardware out of modules into hosts/common
i want for `modules/` to behave like a more typical `modules` directory,
where functionality is opt-in.
2022-11-22 02:52:07 +00:00
43fa7fdd9f rename machines -> hosts
- shorter.
- congruent with `nixos-rebuild .` choosing what to build based on `hostname`.
- more widely used within other nix repos i've seen.
- more accurate in the case that i migrate a host to a different
machine (which i plan to do with servo).
2022-11-22 02:33:47 +00:00
8fc6b05c07 duplicity: add script to restore from backup 2022-11-21 11:47:07 +00:00
439c7d9ef2 duplicity: add utility to list backup files 2022-11-21 11:31:51 +00:00
9633c4f012 packages: add kdenlive 2022-11-21 10:39:58 +00:00
b869617b09 duplicity: refactor and update files list 2022-11-21 10:39:52 +00:00
ce323ffcf9 servo: ejabberd: enable starttls on server-to-server protocol 2022-11-15 12:55:45 +00:00
ac153aecd3 servo: ejabberd: enable 2022-11-15 12:52:45 +00:00
353d97b661 servo: ejabberd: provide access to certs 2022-11-15 12:47:50 +00:00
1150ee4b50 servo: prosody: disable 2022-11-15 12:45:23 +00:00
9e51eafff0 servo: add libraspberrypi 2022-11-15 12:28:49 +00:00
afaa6343ab update nixpkgs: 2022-11-05 -> 2022-11-09
```
• Updated input 'home-manager':
    'github:nix-community/home-manager/87d55517f6f36aa1afbd7a4a064869d5a1d405b8' (2022-11-05)
  → 'github:nix-community/home-manager/6639e3a837fc5deb6f99554072789724997bc8e5' (2022-11-08)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/3bacde6273b09a21a8ccfba15586fb165078fb62' (2022-11-05)
  → 'github:NixOS/nixpkgs/872fceeed60ae6b7766cc0a4cd5bf5901b9098ec' (2022-11-09)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/f09ad462c5a121d0239fde645aacb2221553a217' (2022-11-05)
  → 'github:NixOS/nixpkgs/fa842715565307b7e05cdb187b08c05f16ed08f1' (2022-11-09)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/486b4455da16272c1ed31bc82adcdbe7af829465' (2022-11-02)
  → 'github:Mic92/sops-nix/4407353739ad74a3d9744cf2988ab10f3b83e288' (2022-11-06)
```
2022-11-15 10:04:25 +00:00
67dff6069c sane-rcp: do incremental syncs (append mode) 2022-11-15 09:46:11 +00:00
dea7ca9474 new script to locate dotfiles easier 2022-11-13 01:05:06 +00:00
ad7ae94501 home: ship dino XMPP client 2022-11-12 10:18:13 +00:00
1a0bd16b44 servo: enable prosody XMPP server 2022-11-12 10:02:06 +00:00
56f89bb3f7 servo: ejabberd: configure, but then disable because broken 2022-11-12 01:43:14 +00:00
92a67253c3 servo: lay the skeleton files for a XMPP (jabber) server 2022-11-11 12:56:09 +00:00
8d0ded0ea1 postgresql: leave some notes about future optimization opportunities 2022-11-11 10:58:57 +00:00
de820e32b7 servo: pleroma: remove unneeded prepare: :named config
doing this should increase perf
2022-11-11 10:58:29 +00:00
be286cd190 servo: nginx: enable gzip and TLS optimizations 2022-11-11 10:57:57 +00:00
7cacbd9580 goaccess: optimization only refresh stats once per 30s 2022-11-11 10:56:54 +00:00
c84f10e060 freshrss: update feeds less frequently
Freshrss is throwing some error in the logs... but it still looks to
*kinda* work? ugh.
2022-11-11 08:48:48 +00:00
fd8f660ee0 feeds: add Jeff Kaufman 2022-11-11 07:50:42 +00:00
205b6a9afb nginx: forceSSL for git and fedi 2022-11-08 13:28:41 +00:00
6b7a544df3 lightdm-mobile-greeter: update button styling 2022-11-08 10:42:08 +00:00
c3eacf7126 unpin electrum, sequoia
they build now
2022-11-08 09:08:51 +00:00
3b6f638f98 lightdm-mobile-greeter: update interface.ui 2022-11-08 09:08:39 +00:00
6057a2e665 lightdm-mobile-greeter: update libhandy dependency 2022-11-07 23:36:18 -08:00
f45b032e48 home: add plasmatube (though it might not be working well) 2022-11-08 05:34:02 +00:00
1c810dc1b8 time: switch to UTC
Daylight Savings Time is too confusing for me.
2022-11-08 02:35:50 +00:00
fdd9833b01 lightdm-mobile-greeter: update upstream (minor description change) 2022-11-07 06:32:04 -08:00
25854d3135 lightdm-mobile-greeter: update upstream 2022-11-07 05:25:25 -08:00
45f8cc3894 browserpass-native: update enableOTP PR fix 2022-11-07 04:39:16 -08:00
fc4138327a home-packaged: add rsync 2022-11-06 20:53:22 -08:00
889c47e884 link debug symbols into /run/current-system/sw/lib/debug 2022-11-06 19:25:50 -08:00
f6f500c592 fs: hopefully fix /mnt/servo-root by linking sftp-server at the remote endpoint 2022-11-06 18:54:22 -08:00
6fa9fb740a servo: update rpi linux to fix build 2022-11-06 17:12:22 -08:00
10a665d11c add a servo-cross target
though it looks like rpi4 linux actually fails to cross-compile due to
some RMW page error
2022-11-06 06:04:54 -08:00
77baf03496 Revert "servo: don't ship custom linux kernel packages anymore"
This reverts commit 12b5e68b25.
2022-11-06 05:27:04 -08:00
26f920e119 disable default environment packages 2022-11-06 05:22:16 -08:00
88fba6f496 document --substituters nix options 2022-11-06 03:47:10 -08:00
9f43444f0c ipfs: migrate settings
did not explicitly test these
2022-11-06 03:32:35 -08:00
b68fd881e4 servo: import an element-web patch which allows configuring it without rebuilding 2022-11-06 03:32:35 -08:00
5cca6ede0d emote: fix persistence dir 2022-11-06 02:30:53 -08:00
3b4e394ce8 flake update nixpkgs: 2022-11-03 -> 2022-11-05, home-manager
```
• Updated input 'home-manager':
    'github:nix-community/home-manager/d78b3488a76d251701ab58a9b7f0dd092b806c1e' (2022-11-03)
  → 'github:nix-community/home-manager/87d55517f6f36aa1afbd7a4a064869d5a1d405b8' (2022-11-05)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/a2a777538d971c6b01c6e54af89ddd6567c055e8' (2022-11-03)
  → 'github:NixOS/nixpkgs/3bacde6273b09a21a8ccfba15586fb165078fb62' (2022-11-05)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/1404483f4531560aad73bdebae4096881c910ac0' (2022-11-04)
  → 'github:NixOS/nixpkgs/f09ad462c5a121d0239fde645aacb2221553a217' (2022-11-05)
```
2022-11-06 02:20:04 -08:00
d9b3fccdfa persist emote dir 2022-11-06 02:07:32 -08:00
94366d4bf6 browserpass: patch to support OTP codes better 2022-11-06 02:00:41 -08:00
12b5e68b25 servo: don't ship custom linux kernel packages anymore
it's probably not necessary. i confirmed the kernel provides rpi400 dtb
by default.
2022-11-05 22:29:20 -07:00
a0d332766a nixcache: always trust my own caches, even if not enabled by default 2022-11-05 20:13:17 -07:00
cdd9672654 libreoffice: disable first-run dialog 2022-11-05 17:24:19 -07:00
887a431956 podcasts: add The Verge - Decoder 2022-11-05 06:16:20 -07:00
502ebafb0a update: nixpkgs 2022-11-05 05:42:11 -07:00
57ada6af4f tokodon: fix segfault on launch
also persist the ~/.cache/KDE/tokodon directory.
since the login form isn't working yet (partially the fault of my
Pleroma install?), i can't tell if this is where tokens are stashed or
not.
2022-11-04 06:52:18 -07:00
d1d64b7376 import and update Tokodon package from <https://github.com/NixOS/nixpkgs/pull/170466>
this hangs and then segfaults at start. i suppose i should `gdb` it.
2022-11-03 22:23:14 -07:00
f2188be9f2 flake update: nixpkgs 2022-10-31 -> 2022-11-02, home-manager, sops, mobile-nixos
```
• Updated input 'home-manager':
    'github:nix-community/home-manager/f0ecd4b1db5e15103e955b18cb94bea4296e5c45' (2022-11-01)
  → 'github:nix-community/home-manager/d78b3488a76d251701ab58a9b7f0dd092b806c1e' (2022-11-03)
• Updated input 'mobile-nixos':
    'github:nixos/mobile-nixos/da56c338a2b00c868697b75bdbd388f60d50c820' (2022-10-30)
  → 'github:nixos/mobile-nixos/0b69b36c989d13f08c3bc563253f68c9d6ed7244' (2022-11-01)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/d40fea9aeb8840fea0d377baa4b38e39b9582458' (2022-10-31)
  → 'github:NixOS/nixpkgs/636051e353461f073ac55d5d42c1ed062a345046' (2022-11-02)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/1b4722674c315de0e191d0d79790b4eac51570a1' (2022-10-31)
  → 'github:NixOS/nixpkgs/b3a8f7ed267e0a7ed100eb7d716c9137ff120fe3' (2022-11-01)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/448ec3e7eb7c7e4563cc2471db748a71baaf9698' (2022-10-30)
  → 'github:Mic92/sops-nix/486b4455da16272c1ed31bc82adcdbe7af829465' (2022-11-02)
```
2022-11-03 17:31:47 -07:00
6d52c0e8ab new option: sane.gui.plasma.enable to enable desktop KDE plasma
this is useful for testing applications which are designed for KDE
first.
2022-11-03 03:09:14 -07:00
14b334ff55 new script: sane-reboot, to prevent me from rebooting the wrong machine when working with multiple hosts 2022-11-03 01:27:56 -07:00
730fa8ba4b moby: fix lightdm-mobile-greeter config to work again 2022-11-02 04:59:36 -07:00
8817f661ac browser: temporarily switch back to firefox
recompiling librewolf is not practical -- until the addon signing is
upstreamed
2022-11-02 04:21:55 -07:00
3b0f505864 moby: move lightdm-mobile-greeter stuff into nixpkgs 2022-11-02 04:14:00 -07:00
b559d334c3 librewolf: work toward upstreaming the MOZ_REQUIRE_SIGNING patch 2022-11-02 02:39:56 -07:00
f6e4c0058c add mercurial to dev packages 2022-11-01 22:20:05 -07:00
775fc979fc browser: fix Extensions.Uninstall + refactor nits 2022-11-01 19:29:33 -07:00
ad6daa4e5b librewolf: allow sideloading unsigned addons
still defaulting to firefox, because this requires a recompilation of
the browser -- particularly expensive for moby.
2022-11-01 19:17:49 -07:00
3ecfea158a browser: make more easily swappable between firefox and librewolf 2022-11-01 16:23:50 -07:00
5ff47b3719 remove unused rycee flake input
it was previously used for browser addons: i've since moved those
in-house for technical reasons.
2022-11-01 16:07:57 -07:00
03ea7e7fa5 flake update: nixpkgs 2022-10-30 -> 2022-10-31 and stable home-manager
```
• Updated input 'home-manager':
    'github:nix-community/home-manager/d8b233ad03dd3d82424561512b40971569b2e5d2' (2022-10-31)
  → 'github:nix-community/home-manager/f0ecd4b1db5e15103e955b18cb94bea4296e5c45' (2022-11-01)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/412b9917cea092f3d39f9cd5dead4effd5bc4053' (2022-10-30)
  → 'github:NixOS/nixpkgs/d40fea9aeb8840fea0d377baa4b38e39b9582458' (2022-10-31)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/26eb67abc9a7370a51fcb86ece18eaf19ae9207f' (2022-10-30)
  → 'github:NixOS/nixpkgs/1b4722674c315de0e191d0d79790b4eac51570a1' (2022-10-31)
```
2022-11-01 05:09:04 -07:00
ca93518dda browser: switch from librewolf to firefox-esr
librewolf doesn't allow unsigned addons. i believe this is a bug, as the
nixpkg build file looks like it *meant* to allow addons (and maybe at
some point did)
2022-11-01 04:58:45 -07:00
7f7041351b browserpass-extension: init at 3.7.2
bringing this in-tree instead of fetching it from the mozilla addons
webpage because i plan to develop on it.
2022-11-01 04:57:34 -07:00
1c62bcd50c lightdm-mobile-greeter: update git rev & remove the Cargo.lock patch
Raatty was kind enough to upstream the Cargo.lock fix.
2022-11-01 01:15:36 -07:00
bad4fe0e76 browserpass: add support for totp, and auto-unlock the secrets store on first run
note that one needs to manually enable the TOTP setting in the
browserpass settings for this to work -- TOTP parsing is disabled by
default
2022-10-31 23:57:47 -07:00
8b473ff88f neovim: fix python tree-sitter plugin
which was otherwise yielding parsing errors.
2022-10-31 23:05:27 -07:00
ad54b9c5fb flake update: rycee: 2022-10-29 -> 2022-11-01
```
• Updated input 'rycee':
    'gitlab:rycee/nur-expressions/5fb3c4733c00a7e7be69877d057f6760d85cecb8' (2022-10-29)
  → 'gitlab:rycee/nur-expressions/f4bf327807f86c85e85050101467835a65754b51' (2022-11-01)
```
2022-10-31 23:04:39 -07:00
b805a101ba flake update: nixpkgs 2022-10-29 -> 2022-10-30; home-manager
wouldn't ordinarily update so regularly, but on the lookout for that
openssl CVE...

```
• Updated input 'home-manager':
    'github:nix-community/home-manager/b81e128fc053ab3159d7b464d9b7dedc9d6a6891' (2022-10-17)
  → 'github:nix-community/home-manager/d8b233ad03dd3d82424561512b40971569b2e5d2' (2022-10-31)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/fdebb81f45a1ba2c4afca5fd9f526e1653ad0949' (2022-10-29)
  → 'github:NixOS/nixpkgs/412b9917cea092f3d39f9cd5dead4effd5bc4053' (2022-10-30)
```
2022-10-31 20:54:11 -07:00
69a3aaa086 new script: sane-private-lock
this is handy esp for `servo`, where i don't want my keys to be
accessible after i logout.

longterm, i suppose i could run this automatically on session close
(pam-umount or something i think exists for that?)
2022-10-31 04:21:25 -07:00
9acf2dfde1 gocryptfs: cross-compile for aarch64 2022-10-31 03:05:24 -07:00
4b5accac88 flake update: nixpkgs: 2022-10-22 -> 2022-10-29 and others
```
• Updated input 'mobile-nixos':
    'github:nixos/mobile-nixos/1351091d2537040454fa232d8b94e745ab0eb5a3' (2022-10-24)
  → 'github:nixos/mobile-nixos/da56c338a2b00c868697b75bdbd388f60d50c820' (2022-10-30)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/95aeaf83c247b8f5aa561684317ecd860476fcd6' (2022-10-22)
  → 'github:NixOS/nixpkgs/fdebb81f45a1ba2c4afca5fd9f526e1653ad0949' (2022-10-29)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/3933d8bb9120573c0d8d49dc5e890cb211681490' (2022-10-22)
  → 'github:NixOS/nixpkgs/26eb67abc9a7370a51fcb86ece18eaf19ae9207f' (2022-10-30)
• Updated input 'rycee':
    'gitlab:rycee/nur-expressions/43d3a363c126968db46585b88b8eb97dd32634ad' (2022-10-27)
  → 'gitlab:rycee/nur-expressions/5fb3c4733c00a7e7be69877d057f6760d85cecb8' (2022-10-29)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/1b5f9512a265f0c9687dbff47893180f777f4809' (2022-10-23)
  → 'github:Mic92/sops-nix/448ec3e7eb7c7e4563cc2471db748a71baaf9698' (2022-10-30)
• Updated input 'sops-nix/nixpkgs-22_05':
    'github:NixOS/nixpkgs/f9115594149ebcb409a42e303bec4956814a8419' (2022-10-23)
  → 'github:NixOS/nixpkgs/6440d13df2327d2db13d3b17e419784020b71d22' (2022-10-30)
• Updated input 'uninsane':
    'git+https://git.uninsane.org/colin/uninsane?ref=refs%2fheads%2fmaster&rev=4ad1801f6cecd678bbeae5dfe5933448dd7b3360' (2022-10-14)
  → 'git+https://git.uninsane.org/colin/uninsane?ref=refs%2fheads%2fmaster&rev=80c6ec95bd430e29d231cf745f19279bb76fb382' (2022-10-27)
```
2022-10-30 23:47:29 -07:00
cb00ae4f92 update nautilus gtk4 patch SHA
it's been merged into nixpkgs; manual patch will likely go away after
next nixpkgs update
2022-10-30 21:33:58 -07:00
7c38c1dbe9 de-persist /etc/machine-id, and generate it from the ssh key instead
note that /etc/machine-id now contains a different value than before,
meaning `journalctl` will not show logs from before the time of this
change.
2022-10-30 21:02:41 -07:00
b3b45ec0f2 fix host ssh key persistence 2022-10-30 20:03:00 -07:00
34d77542e7 impermanence: ensure /etc/ssh is populated before we decode machine secrets during activation
the impermanence activation scripts don't appear to mount folders --
only files. rather, the impermanence module creates fstab entries for
each bind mount folder, and *something* (systemd?) mounts these *after*
/run/current-system/activate is run.

therefore, if we want access to a bind-mounted directory during
activateion, we have to manually mount it.
i.e. `mount /etc/ssh/host_keys`.
2022-10-30 05:59:55 -07:00
171 changed files with 6914 additions and 1816 deletions

97
flake.lock generated
View File

@@ -22,11 +22,11 @@
]
},
"locked": {
"lastModified": 1665996265,
"narHash": "sha256-/k9og6LDBQwT+f/tJ5ClcWiUl8kCX5m6ognhsAxOiCY=",
"lastModified": 1667907331,
"narHash": "sha256-bHkAwkYlBjkupPUFcQjimNS8gxWSWjOTevEuwdnp5m0=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "b81e128fc053ab3159d7b464d9b7dedc9d6a6891",
"rev": "6639e3a837fc5deb6f99554072789724997bc8e5",
"type": "github"
},
"original": {
@@ -38,11 +38,11 @@
},
"impermanence": {
"locked": {
"lastModified": 1661933071,
"narHash": "sha256-RFgfzldpbCvS+H2qwH+EvNejvqs+NhPVD5j1I7HQQPY=",
"lastModified": 1668668915,
"narHash": "sha256-QjY4ZZbs9shwO4LaLpvlU2bO9J1juYhO9NtV3nrbnYQ=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "def994adbdfc28974e87b0e4c949e776207d5557",
"rev": "5df9108b346f8a42021bf99e50de89c9caa251c3",
"type": "github"
},
"original": {
@@ -54,11 +54,11 @@
"mobile-nixos": {
"flake": false,
"locked": {
"lastModified": 1666573922,
"narHash": "sha256-CqB8Y5HajptSFE8Em990dcYZIHJWBiO9zd1us4Mzx8M=",
"lastModified": 1670131242,
"narHash": "sha256-T/o1/3gffr010fsqgNshs1NJJjsnUYvQnUZgm6hilsY=",
"owner": "nixos",
"repo": "mobile-nixos",
"rev": "1351091d2537040454fa232d8b94e745ab0eb5a3",
"rev": "5ee45cc1f8e43f4af14ee17ccef9156b0db8cd77",
"type": "github"
},
"original": {
@@ -69,11 +69,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1666447894,
"narHash": "sha256-i9WHX4w/et4qPMzEXd9POmnO0/bthjr7R4cblKNHGms=",
"lastModified": 1671722432,
"narHash": "sha256-ojcZUekIQeOZkHHzR81st7qxX99dB1Eaaq6PU5MNeKc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "95aeaf83c247b8f5aa561684317ecd860476fcd6",
"rev": "652e92b8064949a11bc193b90b74cb727f2a1405",
"type": "github"
},
"original": {
@@ -82,37 +82,37 @@
"type": "indirect"
}
},
"nixpkgs-22_05": {
"locked": {
"lastModified": 1666488099,
"narHash": "sha256-DANs2epN5QgvxWzH7xF3dzb4WE0lEuMLrMEu/vPmQxw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f9115594149ebcb409a42e303bec4956814a8419",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-22.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1666401273,
"narHash": "sha256-AG3MoIjcWwz1SPjJ2nymWu4NmeVj9P40OpB1lsmxFtg=",
"lastModified": 1671883564,
"narHash": "sha256-C15oAtyupmLB3coZY7qzEHXjhtUx/+77olVdqVMruAg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "3933d8bb9120573c0d8d49dc5e890cb211681490",
"rev": "dac57a4eccf1442e8bf4030df6fcbb55883cb682",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-22.05",
"ref": "nixos-22.11",
"type": "indirect"
}
},
"nixpkgs-stable_2": {
"locked": {
"lastModified": 1671923641,
"narHash": "sha256-flPauiL5UrfRJD+1oAcEefpEIUqTqnyKScWe/UUU+lE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "939c05a176b8485971463c18c44f48e56a7801c9",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-22.11",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"home-manager": "home-manager",
@@ -120,40 +120,23 @@
"mobile-nixos": "mobile-nixos",
"nixpkgs": "nixpkgs",
"nixpkgs-stable": "nixpkgs-stable",
"rycee": "rycee",
"sops-nix": "sops-nix",
"uninsane": "uninsane"
}
},
"rycee": {
"flake": false,
"locked": {
"lastModified": 1666843362,
"narHash": "sha256-xn2bW9/MT0u8Ptlk+f323p46Q/ktZkzMp7oj5SlYDxU=",
"owner": "rycee",
"repo": "nur-expressions",
"rev": "43d3a363c126968db46585b88b8eb97dd32634ad",
"type": "gitlab"
},
"original": {
"owner": "rycee",
"repo": "nur-expressions",
"type": "gitlab"
}
},
"sops-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-22_05": "nixpkgs-22_05"
"nixpkgs-stable": "nixpkgs-stable_2"
},
"locked": {
"lastModified": 1666499473,
"narHash": "sha256-q1eFnBFL0kHgcnUPeKagw3BfbE/5sMJNGL2E2AR+a2M=",
"lastModified": 1671937829,
"narHash": "sha256-YtaNB+mLw0d67JFYNjRWM+/AL3JCXuD/DGlnTlyX1tY=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "1b5f9512a265f0c9687dbff47893180f777f4809",
"rev": "855b8d51fc3991bd817978f0f093aa6ae0fae738",
"type": "github"
},
"original": {
@@ -170,11 +153,11 @@
]
},
"locked": {
"lastModified": 1665758541,
"narHash": "sha256-ibR8bPwHlDjavri5cNVnoo5FmFk1IfNMmQXxat5biqs=",
"lastModified": 1666870107,
"narHash": "sha256-b9eXZxSwhzdJI5uQgfrMhu4SY2POrPkinUg7F5gQVYo=",
"ref": "refs/heads/master",
"rev": "4ad1801f6cecd678bbeae5dfe5933448dd7b3360",
"revCount": 163,
"rev": "80c6ec95bd430e29d231cf745f19279bb76fb382",
"revCount": 164,
"type": "git",
"url": "https://git.uninsane.org/colin/uninsane"
},

View File

@@ -4,7 +4,7 @@
{
inputs = {
nixpkgs-stable.url = "nixpkgs/nixos-22.05";
nixpkgs-stable.url = "nixpkgs/nixos-22.11";
nixpkgs.url = "nixpkgs/nixos-unstable";
mobile-nixos = {
url = "github:nixos/mobile-nixos";
@@ -14,10 +14,6 @@
url = "github:nix-community/home-manager/release-22.05";
inputs.nixpkgs.follows = "nixpkgs";
};
rycee = {
url = "gitlab:rycee/nur-expressions";
flake = false;
};
sops-nix = {
url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
@@ -35,7 +31,6 @@
nixpkgs-stable,
mobile-nixos,
home-manager,
rycee,
sops-nix,
impermanence,
uninsane
@@ -43,14 +38,17 @@
patchedPkgs = system: nixpkgs.legacyPackages.${system}.applyPatches {
name = "nixpkgs-patched-uninsane";
src = nixpkgs;
patches = import ./nixpatches/list.nix nixpkgs.legacyPackages.${system}.fetchpatch;
patches = import ./nixpatches/list.nix {
inherit (nixpkgs.legacyPackages.${system}) fetchpatch;
inherit (nixpkgs.lib) fakeHash;
};
};
# return something which behaves like `pkgs`, for the provided system
# `local` = architecture of builder. `target` = architecture of the system beying deployed to
nixpkgsFor = local: target: import (patchedPkgs target) { crossSystem = target; localSystem = local; };
# evaluate ONLY our overlay, for the provided system
customPackagesFor = local: target: import ./pkgs/overlay.nix (nixpkgsFor local target) (nixpkgsFor local target);
decl-machine = { name, local, target }:
decl-host = { name, local, target }:
let
nixosSystem = import ((patchedPkgs target) + "/nixos/lib/eval-config.nix");
in (nixosSystem {
@@ -59,14 +57,13 @@
specialArgs = { inherit mobile-nixos home-manager impermanence; };
modules = [
./modules
(import ./machines/instantiate.nix name)
(import ./hosts/instantiate.nix name)
home-manager.nixosModule
impermanence.nixosModule
sops-nix.nixosModules.sops
{
nixpkgs.overlays = [
(import "${mobile-nixos}/overlay/overlay.nix")
(import "${rycee}/overlay.nix")
uninsane.overlay
(import ./pkgs/overlay.nix)
(next: prev: rec {
@@ -75,17 +72,23 @@
# the config can explicitly pull such packages from `pkgs.cross` to do more efficient cross-compilation.
cross = (nixpkgsFor local target) // (customPackagesFor local target);
stable = import nixpkgs-stable { system = target; };
# cross-compatible packages
# gocryptfs = cross.gocryptfs;
# pinned packages:
electrum = stable.electrum; # 2022-10-10: build break
sequoia = stable.sequoia; # 2022-10-13: build break
# 2022/12/13: grpc does not build on aarch64-linux. https://github.com/NixOS/nixpkgs/issues/205887
grpc = stable.grpc;
# depends on grpc, so pinned.
duplicity = stable.duplicity;
})
];
}
];
});
decl-bootable-machine = { name, local, target }: rec {
nixosConfiguration = decl-machine { inherit name local target; };
decl-bootable-host = { name, local, target }: rec {
nixosConfiguration = decl-host { inherit name local target; };
# this produces a EFI-bootable .img file (GPT with a /boot partition and a system (/ or /nix) partition).
# after building this:
# - flash it to a bootable medium (SD card, flash drive, HDD)
@@ -98,32 +101,41 @@
# - boot
# - if fs wasn't resized automatically, then `sudo btrfs filesystem resize max /`
# - checkout this flake into /etc/nixos AND UPDATE THE FS UUIDS.
# - `nixos-rebuild --flake './#<machine>' switch`
# - `nixos-rebuild --flake './#<host>' switch`
img = nixosConfiguration.config.system.build.img;
};
machines.servo = decl-bootable-machine { name = "servo"; local = "aarch64-linux"; target = "aarch64-linux"; };
machines.desko = decl-bootable-machine { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
machines.lappy = decl-bootable-machine { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
machines.moby = decl-bootable-machine { name = "moby"; local = "aarch64-linux"; target = "aarch64-linux"; };
hosts.servo = decl-bootable-host { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
hosts.desko = decl-bootable-host { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
hosts.lappy = decl-bootable-host { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
hosts.moby = decl-bootable-host { name = "moby"; local = "aarch64-linux"; target = "aarch64-linux"; };
# special cross-compiled variant, to speed up deploys from an x86 box to the arm target
# note that these *do* produce different store paths, because the closure for the tools used to cross compile
# v.s. emulate differ.
# so deploying moby-cross and then moby incurs some rebuilding.
machines.moby-cross = decl-bootable-machine { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
machines.rescue = decl-bootable-machine { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
# so deploying foo-cross and then foo incurs some rebuilding.
hosts.moby-cross = decl-bootable-host { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
hosts.rescue = decl-bootable-host { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
in {
nixosConfigurations = builtins.mapAttrs (name: value: value.nixosConfiguration) machines;
imgs = builtins.mapAttrs (name: value: value.img) machines;
nixosConfigurations = builtins.mapAttrs (name: value: value.nixosConfiguration) hosts;
imgs = builtins.mapAttrs (name: value: value.img) hosts;
packages = let
allPkgsFor = sys: (customPackagesFor sys sys) // {
nixpkgs = nixpkgsFor sys sys;
uninsane = uninsane.packages."${sys}";
rycee = (import "${rycee}/default.nix" { pkgs = nixpkgsFor sys sys; });
};
in {
x86_64-linux = allPkgsFor "x86_64-linux";
aarch64-linux = allPkgsFor "aarch64-linux";
};
templates = {
python-data = {
# initialize with:
# - `nix flake init -t '/home/colin/dev/nixos/#python-data'`
# then enter with:
# - `nix develop`
path = ./templates/python-data;
description = "python environment for data processing";
};
};
};
}

View File

@@ -0,0 +1,18 @@
{ lib, pkgs, ... }:
{
# TODO: don't need to depend on binsh if we were to use a nix-style shebang
system.activationScripts.linkBluetoothKeys = let
unwrapped = ../../scripts/install-bluetooth;
install-bluetooth = pkgs.writeShellApplication {
name = "install-bluetooth";
runtimeInputs = with pkgs; [ coreutils gnused ];
text = ''${unwrapped} "$@"'';
};
in (lib.stringAfter
[ "setupSecrets" "binsh" ]
''
${install-bluetooth}/bin/install-bluetooth /run/secrets/bt
''
);
}

View File

@@ -1,20 +1,37 @@
{ pkgs, ... }:
{
imports = [
./allocations.nix
./bluetooth.nix
./fs.nix
./home-manager
./home-packages.nix
./hardware
./i2p.nix
./machine-id.nix
./net.nix
./secrets.nix
./ssh.nix
./system-packages.nix
./users.nix
./vpn.nix
];
time.timeZone = "America/Los_Angeles";
sane.home-manager.enable = true;
sane.nixcache.enable-trusted-keys = true;
sane.packages.enableConsolePkgs = true;
sane.packages.enableSystemPkgs = true;
sane.impermanence.dirs = [
"/var/log"
"/var/backup" # for e.g. postgres dumps
# TODO: move elsewhere
"/var/lib/alsa" # preserve output levels, default devices
"/var/lib/bluetooth" # preserve bluetooth handshakes
"/var/lib/colord" # preserve color calibrations (?)
"/var/lib/machines" # maybe not needed, but would be painful to add a VM and forget.
];
nixpkgs.config.allowUnfree = true;
# time.timeZone = "America/Los_Angeles";
time.timeZone = "Etc/UTC"; # DST is too confusing for me => use a stable timezone
# allow `nix flake ...` command
nix.extraOptions = ''
@@ -34,6 +51,9 @@
};
};
# disable non-required packages like nano, perl, rsync, strace
environment.defaultPackages = [];
# programs.vim.defaultEditor = true;
environment.variables = {
EDITOR = "vim";
@@ -48,16 +68,8 @@
};
# enable zsh completions
environment.pathsToLink = [ "/share/zsh" ];
environment.systemPackages = with pkgs; [
# required for pam_mount
gocryptfs
];
security.pam.mount.enable = true;
# security.pam.mount.debugLevel = 1;
# security.pam.enableSSHAgentAuth = true; # ??
# needed for `allow_other` in e.g. gocryptfs mounts
# or i guess going through mount.fuse sets suid so that's not necessary?
# programs.fuse.userAllowOther = true;
# link debug symbols into /run/current-system/sw/lib/debug
# hopefully picked up by gdb automatically?
environment.enableDebugInfo = true;
}

View File

@@ -19,11 +19,17 @@ let sshOpts = rec {
optionsRoot = optionsBase ++ [
# we don't transform_symlinks because that breaks the validity of remote /nix stores
"sftp_server=/run/wrappers/bin/sudo\\040${pkgs.openssh}/libexec/sftp-server"
"sftp_server=/run/wrappers/bin/sudo\\040/run/current-system/sw/libexec/sftp-server"
];
};
in
{
environment.pathsToLink = [
# needed to achieve superuser access for user-mounted filesystems (see optionsRoot above)
# we can only link whole directories here, even though we're only interested in pkgs.openssh
"/libexec"
];
fileSystems."/mnt/servo-media-wan" = {
device = "colin@uninsane.org:/var/lib/uninsane/media";
inherit (sshOpts) fsType;

4
hosts/common/i2p.nix Normal file
View File

@@ -0,0 +1,4 @@
{ ... }:
{
services.i2p.enable = true;
}

View File

@@ -0,0 +1,16 @@
{ ... }:
{
# /etc/machine-id is a globally unique identifier used for:
# - systemd-networkd: DHCP lease renewal (instead of keying by the MAC address)
# - systemd-journald: to filter logs by host
# - chromium (potentially to track re-installations)
# - gdbus; system services that might upgrade to AF_LOCAL if both services can confirm they're on the same machine
# because of e.g. the chromium use, we *don't want* to persist this.
# however, `journalctl` won't show logs from previous boots unless the machine-ids match.
# so for now, generate something unique from the host ssh key.
# TODO: move this into modules?
system.activationScripts.machine-id = {
deps = [ "etc" ];
text = "sha256sum /etc/ssh/host_keys/ssh_host_ed25519_key | cut -c 1-32 > /etc/machine-id";
};
}

View File

@@ -46,34 +46,4 @@
${install-iwd}/bin/install-iwd /run/secrets/iwd /var/lib/iwd
''
);
# TODO: use a glob, or a list, or something?
sops.secrets."iwd/community-university.psk" = {
sopsFile = ../../secrets/universal/net/community-university.psk.bin;
format = "binary";
};
sops.secrets."iwd/friend-libertarian-dod.psk" = {
sopsFile = ../../secrets/universal/net/friend-libertarian-dod.psk.bin;
format = "binary";
};
sops.secrets."iwd/friend-rationalist-empathist.psk" = {
sopsFile = ../../secrets/universal/net/friend-rationalist-empathist.psk.bin;
format = "binary";
};
sops.secrets."iwd/home-bedroom.psk" = {
sopsFile = ../../secrets/universal/net/home-bedroom.psk.bin;
format = "binary";
};
sops.secrets."iwd/home-shared-24G.psk" = {
sopsFile = ../../secrets/universal/net/home-shared-24G.psk.bin;
format = "binary";
};
sops.secrets."iwd/home-shared.psk" = {
sopsFile = ../../secrets/universal/net/home-shared.psk.bin;
format = "binary";
};
sops.secrets."iwd/iphone" = {
sopsFile = ../../secrets/universal/net/iphone.psk.bin;
format = "binary";
};
}

124
hosts/common/secrets.nix Normal file
View File

@@ -0,0 +1,124 @@
{ config, ... }:
{
# SOPS configuration:
# docs: https://github.com/Mic92/sops-nix
#
# for each new user you want to edit sops files:
# create a private age key from ssh key:
# $ mkdir -p ~/.config/sops/age; ssh-to-age -private-key -i ~/.ssh/id_ed25519 > ~/.config/sops/age/keys.txt; chmod 600 ~/.config/sops/age/keys.txt
# if the private key was password protected, then first decrypt it:
# $ cp ~/.ssh/id_ed25519 /tmp/id_ed25519
# $ ssh-keygen -p -N "" -f /tmp/id_ed25519
#
# for each user you want to decrypt secrets:
# $ cat ~/.ssh/id_ed25519.pub | ssh-to-age
# add the result to .sops.yaml
# since we specify ssh pubkeys in the nix config, you can just grep for `ssh-ed25519` here and use those instead
#
# for each host you want to decrypt secrets:
# $ cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age
# add the result to .sops.yaml
# $ sops updatekeys secrets/example.yaml
#
# to create a new secret:
# $ sops secrets/example.yaml
# control access below (sops.secret.<x>.owner = ...)
#
# to read a secret:
# $ cat /run/secrets/example_key
# sops.age.sshKeyPaths = [ "/home/colin/.ssh/id_ed25519_dec" ];
# This will add secrets.yaml to the nix store
# You can avoid this by adding a string to the full path instead, i.e.
# sops.defaultSopsFile = "/root/.sops/secrets/example.yaml";
sops.defaultSopsFile = ../../secrets/universal.yaml;
sops.gnupg.sshKeyPaths = []; # disable RSA key import
# This is using an age key that is expected to already be in the filesystem
# sops.age.keyFile = "/home/colin/.ssh/age.pub";
# sops.age.keyFile = "/var/lib/sops-nix/key.txt";
# This will generate a new key if the key specified above does not exist
# sops.age.generateKey = true;
# This is the actual specification of the secrets.
# sops.secrets.example_key = {
# owner = config.users.users.colin.name;
# };
# sops.secrets."myservice/my_subdir/my_secret" = {};
## universal secrets
# TODO: glob these?
sops.secrets."jackett_apikey" = {
sopsFile = ../../secrets/universal.yaml;
owner = config.users.users.colin.name;
};
sops.secrets."router_passwd" = {
sopsFile = ../../secrets/universal.yaml;
};
sops.secrets."wg_ovpnd_us_privkey" = {
sopsFile = ../../secrets/universal.yaml;
};
sops.secrets."wg_ovpnd_us-atl_privkey" = {
sopsFile = ../../secrets/universal.yaml;
};
sops.secrets."wg_ovpnd_us-mi_privkey" = {
sopsFile = ../../secrets/universal.yaml;
};
sops.secrets."wg_ovpnd_ukr_privkey" = {
sopsFile = ../../secrets/universal.yaml;
};
sops.secrets."snippets" = {
sopsFile = ../../secrets/universal/snippets.bin;
format = "binary";
owner = config.users.users.colin.name;
};
sops.secrets."bt/car" = {
sopsFile = ../../secrets/universal/bt/car.bin;
format = "binary";
};
sops.secrets."bt/earbuds" = {
sopsFile = ../../secrets/universal/bt/earbuds.bin;
format = "binary";
};
sops.secrets."bt/portable-speaker" = {
sopsFile = ../../secrets/universal/bt/portable-speaker.bin;
format = "binary";
};
sops.secrets."iwd/community-university.psk" = {
sopsFile = ../../secrets/universal/net/community-university.psk.bin;
format = "binary";
};
sops.secrets."iwd/friend-libertarian-dod.psk" = {
sopsFile = ../../secrets/universal/net/friend-libertarian-dod.psk.bin;
format = "binary";
};
sops.secrets."iwd/friend-rationalist-empathist.psk" = {
sopsFile = ../../secrets/universal/net/friend-rationalist-empathist.psk.bin;
format = "binary";
};
sops.secrets."iwd/home-bedroom.psk" = {
sopsFile = ../../secrets/universal/net/home-bedroom.psk.bin;
format = "binary";
};
sops.secrets."iwd/home-shared-24G.psk" = {
sopsFile = ../../secrets/universal/net/home-shared-24G.psk.bin;
format = "binary";
};
sops.secrets."iwd/home-shared.psk" = {
sopsFile = ../../secrets/universal/net/home-shared.psk.bin;
format = "binary";
};
sops.secrets."iwd/iphone" = {
sopsFile = ../../secrets/universal/net/iphone.psk.bin;
format = "binary";
};
sops.secrets."iwd/parents" = {
sopsFile = ../../secrets/universal/net/parents.psk.bin;
format = "binary";
};
}

10
hosts/common/ssh.nix Normal file
View File

@@ -0,0 +1,10 @@
{ config, lib, ... }:
{
environment.etc."ssh/host_keys".source = "/nix/persist/etc/ssh/host_keys";
services.openssh.hostKeys = [
{ type = "rsa"; bits = 4096; path = "/etc/ssh/host_keys/ssh_host_rsa_key"; }
{ type = "ed25519"; path = "/etc/ssh/host_keys/ssh_host_ed25519_key"; }
];
}

View File

@@ -27,6 +27,8 @@ in
# sets group to "users" (?)
isNormalUser = true;
home = "/home/colin";
createHome = true;
homeMode = "700";
uid = config.sane.allocations.colin-uid;
# i don't get exactly what this is, but nixos defaults to this non-deterministically
# in /var/lib/nixos/auto-subuid-map and i don't want that.
@@ -50,30 +52,47 @@ in
passwordFile = lib.mkIf (config.sops.secrets ? "colin-passwd") config.sops.secrets.colin-passwd.path;
shell = pkgs.zsh;
openssh.authorizedKeys.keys = builtins.attrValues (import ./pubkeys.nix).users;
openssh.authorizedKeys.keys = builtins.attrValues (import ../../modules/pubkeys.nix).users;
# some other nix pam users:
# - <https://github.com/g00pix/nixconf/blob/32c04f6fa843fed97639dd3f09e157668d3eea1f/profiles/sshfs.nix>
# - <https://github.com/lourkeur/distro/blob/11173454c6bb50f7ccab28cc2c757dca21446d1d/nixos/profiles/users/louis-full.nix>
# - <https://github.com/dnr/sample-nix-code/blob/03494480c1fae550c033aa54fd96aeb3827761c5/nixos/laptop.nix>
pamMount = {
# mount encrypted stuff at login
# requires that login password == fs encryption password
# fstype = "fuse";
fstype = "fuse";
path = "gocryptfs#/nix/persist/home/colin/private";
# path = "${pkgs.gocryptfs}/bin/gocryptfs#/nix/persist/home/colin/private";
fstype = "fuse.gocryptfs";
path = "/nix/persist/home/colin/private";
# fstype = "fuse.gocryptfs";
# path = "/nix/persist/home/colin/private";
mountpoint = "/home/colin/private";
options="nodev,nosuid,quiet,allow_other";
# without allow_other, *root* isn't allowed to list anything in ~/private.
# which is weird (root can just `su colin`), but probably doesn't *hurt* anything -- right?
options="nodev,nosuid,quiet"; # allow_other
};
};
# required for PAM to find gocryptfs
security.pam.mount.additionalSearchPaths = [ pkgs.gocryptfs ];
security.pam.mount.enable = true;
# security.pam.mount.debugLevel = 1;
# security.pam.enableSSHAgentAuth = true; # ??
# needed for `allow_other` in e.g. gocryptfs mounts
# or i guess going through mount.fuse sets suid so that's not necessary?
# programs.fuse.userAllowOther = true;
sane.impermanence.home-dirs = [
# cache is probably too big to fit on the tmpfs
# TODO: we could bind-mount it to something which gets cleared per boot, though.
".cache"
# { directory = ".cache"; encryptedClearOnBoot = true; }
{ directory = ".cache/mozilla"; encryptedClearOnBoot = true; }
".cargo"
".rustup"
# TODO: move this to ~/private!
".local/share/keyrings"
];
sane.impermanence.service-dirs = mkIf cfg.guest.enable [
sane.impermanence.dirs = mkIf cfg.guest.enable [
{ user = "guest"; group = "users"; directory = "/home/guest"; }
];
users.users.guest = mkIf cfg.guest.enable {

66
hosts/common/vpn.nix Normal file
View File

@@ -0,0 +1,66 @@
{ config, lib, ... }:
# to add a new OVPN VPN:
# - generate a privkey `wg genkey`
# - add this key to `sops secrets/universal.yaml`
# - upload pubkey to OVPN.com
# - generate config @ OVPN.com
# - copy the Address, PublicKey, Endpoint from OVPN's config
# N.B.: maximum interface name in Linux is 15 characters.
let
def-ovpn = name: { endpoint, publicKey, address }: {
networking.wg-quick.interfaces."ovpnd-${name}" = {
inherit address;
privateKeyFile = config.sops.secrets."wg_ovpnd_${name}_privkey".path;
dns = [
"46.227.67.134"
"192.165.9.158"
];
peers = [
{
allowedIPs = [
"0.0.0.0/0"
"::/0"
];
inherit endpoint publicKey;
}
];
# to start: `systemctl start wg-quick-ovpnd-${name}`
autostart = false;
};
};
in lib.mkMerge [
(def-ovpn "us" {
endpoint = "vpn31.prd.losangeles.ovpn.com:9929";
publicKey = "VW6bEWMOlOneta1bf6YFE25N/oMGh1E1UFBCfyggd0k=";
address = [
"172.27.237.218/32"
"fd00:0000:1337:cafe:1111:1111:ab00:4c8f/128"
];
})
# NB: us-* share the same wg key and link-local addrs, but distinct public addresses
(def-ovpn "us-atl" {
endpoint = "vpn18.prd.atlanta.ovpn.com:9929";
publicKey = "Dpg/4v5s9u0YbrXukfrMpkA+XQqKIFpf8ZFgyw0IkE0=";
address = [
"172.21.182.178/32"
"fd00:0000:1337:cafe:1111:1111:cfcb:27e3/128"
];
})
(def-ovpn "us-mi" {
endpoint = "vpn34.prd.miami.ovpn.com:9929";
publicKey = "VtJz2irbu8mdkIQvzlsYhU+k9d55or9mx4A2a14t0V0=";
address = [
"172.21.182.178/32"
"fd00:0000:1337:cafe:1111:1111:cfcb:27e3/128"
];
})
(def-ovpn "ukr" {
endpoint = "vpn96.prd.kyiv.ovpn.com:9929";
publicKey = "CjZcXDxaaKpW8b5As1EcNbI6+42A6BjWahwXDCwfVFg=";
address = [
"172.18.180.159/32"
"fd00:0000:1337:cafe:1111:1111:ec5c:add3/128"
];
})
]

View File

@@ -4,6 +4,8 @@
./fs.nix
];
# sane.packages.enableDevPkgs = true;
sane.gui.sway.enable = true;
sane.services.duplicity.enable = true;
sane.services.nixserve.enable = true;
@@ -23,6 +25,9 @@
neededForUsers = true;
};
# don't enable wifi by default: it messes with connectivity.
systemd.services.iwd.enable = false;
# default config: https://man.archlinux.org/man/snapper-configs.5
# defaults to something like:
# - hourly snapshots

View File

@@ -1,16 +1,7 @@
{ ... }:
{
# root is a tmpfs so that we have an ephemeral system ("impermanence" handles the state)
fileSystems."/" = {
device = "none";
fsType = "tmpfs";
options = [
"mode=755"
"size=1G"
"defaults"
];
};
sane.impermanence.root-on-tmpfs = true;
# we need a /tmp for building large nix things.
# a cross-compiled kernel, particularly, will easily use 30+GB of tmp
fileSystems."/tmp" = {

10
hosts/instantiate.nix Normal file
View File

@@ -0,0 +1,10 @@
# trampoline from flake.nix into the specific host definition, while doing a tiny bit of common setup
hostName: { ... }: {
imports = [
./${hostName}
./common
];
networking.hostName = hostName;
}

View File

@@ -4,6 +4,8 @@
./fs.nix
];
# sane.packages.enableDevPkgs = true;
# sane.users.guest.enable = true;
sane.gui.sway.enable = true;
sane.impermanence.enable = true;

View File

@@ -1,16 +1,7 @@
{ ... }:
{
# root is a tmpfs so that we have an ephemeral system ("impermanence" handles the state)
fileSystems."/" = {
device = "none";
fsType = "tmpfs";
options = [
"mode=755"
"size=1G"
"defaults"
];
};
sane.impermanence.root-on-tmpfs = true;
# we need a /tmp of default size (half RAM) for building large nix things
fileSystems."/tmp" = {
device = "none";

View File

@@ -25,11 +25,12 @@
# usability compromises
sane.impermanence.home-dirs = [
".librewolf"
config.sane.web-browser.dotDir
".config/pulse" # persist pulseaudio volume
];
# sane.home-packages.enableGuiPkgs = false; # XXX faster builds/imaging for debugging
sane.home-manager.extraPackages = [
# sane.packages.enableGuiPkgs = false; # XXX faster builds/imaging for debugging
sane.packages.extraUserPkgs = [
pkgs.plasma5Packages.konsole # terminal
];
@@ -39,7 +40,9 @@
boot.loader.efi.canTouchEfiVariables = false;
# /boot space is at a premium. default was 20.
boot.loader.generic-extlinux-compatible.configurationLimit = 10;
# even 10 can be too much
# TODO: compress moby kernels!
boot.loader.generic-extlinux-compatible.configurationLimit = 8;
# mobile.bootloader.enable = false;
# mobile.boot.stage-1.enable = false;
# boot.initrd.systemd.enable = false;

View File

@@ -1,17 +1,7 @@
{ ... }:
{
# root is a tmpfs so that we have an ephemeral system ("impermanence" handles the state)
fileSystems."/" = {
device = "none";
fsType = "tmpfs";
options = [
"mode=755"
"size=1G"
"defaults"
];
};
sane.impermanence.root-on-tmpfs = true;
fileSystems."/nix" = {
device = "/dev/disk/by-uuid/1f1271f8-53ce-4081-8a29-60a4a6b5d6f9";
fsType = "btrfs";

View File

@@ -3,27 +3,22 @@
{
imports = [
./fs.nix
./hardware.nix
./net.nix
./users.nix
./services
];
sane.home-manager.extraPackages = [
sane.packages.extraUserPkgs = [
# for administering services
pkgs.matrix-synapse
pkgs.freshrss
pkgs.goaccess
];
sane.impermanence.enable = true;
sane.services.duplicity.enable = true;
sane.services.nixserve.enable = true;
sane.services.dyn-dns.enable = true;
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade
# TODO: look into the EFI stuff
boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;
boot.loader.efi.canTouchEfiVariables = false;
sane.image.extraBootFiles = [ pkgs.bootpart-u-boot-rpi-aarch64 ];
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
sops.secrets.duplicity_passphrase = {
sopsFile = ../../secrets/servo.yaml;
@@ -32,7 +27,7 @@
# both transmission and ipfs try to set different net defaults.
# we just use the most aggressive of the two here:
boot.kernel.sysctl = {
"net.core.rmem_max" = "4194304"; # 4MB
"net.core.rmem_max" = 4194304; # 4MB
};
# This value determines the NixOS release from which the default
@@ -41,6 +36,6 @@
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "21.11"; # Did you read the comment?
system.stateVersion = "21.11";
}

89
hosts/servo/fs.nix Normal file
View File

@@ -0,0 +1,89 @@
{ ... }:
{
sane.impermanence.root-on-tmpfs = true;
# we need a /tmp for building large nix things
fileSystems."/tmp" = {
device = "none";
fsType = "tmpfs";
options = [
"mode=777"
"defaults"
];
};
fileSystems."/nix" = {
device = "/dev/disk/by-uuid/cc81cca0-3cc7-4d82-a00c-6243af3e7776";
fsType = "btrfs";
options = [
"compress=zstd"
"defaults"
];
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/6EE3-4171";
fsType = "vfat";
};
# slow, external storage (for archiving, etc)
fileSystems."/nix/persist/ext" = {
device = "/dev/disk/by-uuid/aa272cff-0fcc-498e-a4cb-0d95fb60631b";
fsType = "btrfs";
options = [
"compress=zstd"
"defaults"
];
};
sane.impermanence.dirs = [
# TODO: this is overly broad; only need media and share directories to be persisted
{ user = "colin"; group = "users"; directory = "/var/lib/uninsane"; }
];
# direct these media directories to external storage
environment.persistence."/nix/persist/ext/persist" = {
directories = [
({
user = "colin";
group = "users";
mode = "0777";
directory = "/var/lib/uninsane/media/Videos";
})
({
user = "colin";
group = "users";
mode = "0777";
directory = "/var/lib/uninsane/media/freeleech";
})
];
};
# in-memory compressed RAM (seems to be dynamically sized)
# zramSwap = {
# enable = true;
# };
# btrfs doesn't easily support swapfiles
# swapDevices = [
# { device = "/nix/persist/swapfile"; size = 4096; }
# ];
# this can be a partition. create with:
# fdisk <dev>
# n
# <default partno>
# <start>
# <end>
# t
# <partno>
# 19 # set part type to Linux swap
# w # write changes
# mkswap -L swap <part>
# swapDevices = [
# {
# label = "swap";
# # TODO: randomEncryption.enable = true;
# }
# ];
}

212
hosts/servo/net.nix Normal file
View File

@@ -0,0 +1,212 @@
{ config, pkgs, ... }:
{
networking.domain = "uninsane.org";
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
# Per-interface useDHCP will be mandatory in the future, so this generated config
# replicates the default behaviour.
networking.useDHCP = false;
networking.interfaces.eth0.useDHCP = true;
# XXX colin: probably don't need this. wlan0 won't be populated unless i touch a value in networking.interfaces.wlan0
networking.wireless.enable = false;
# networking.firewall.enable = false;
networking.firewall.enable = true;
# this is needed to forward packets from the VPN to the host
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
# unless we add interface-specific settings for each VPN, we have to define nameservers globally.
# networking.nameservers = [
# "1.1.1.1"
# "9.9.9.9"
# ];
# use systemd's stub resolver.
# /etc/resolv.conf isn't sophisticated enough to use different servers per net namespace (or link).
# instead, running the stub resolver on a known address in the root ns lets us rewrite packets
# in the ovnps namespace to use the provider's DNS resolvers.
# a weakness is we can only query 1 NS at a time (unless we were to clone the packets?)
# there also seems to be some cache somewhere that's shared between the two namespaces.
# i think this is a libc thing. might need to leverage proper cgroups to _really_ kill it.
# - getent ahostsv4 www.google.com
# - try fix: <https://serverfault.com/questions/765989/connect-to-3rd-party-vpn-server-but-dont-use-it-as-the-default-route/766290#766290>
services.resolved.enable = true;
networking.nameservers = [
# use systemd-resolved resolver
# full resolver (which understands /etc/hosts) lives on 127.0.0.53
# stub resolver (just forwards upstream) lives on 127.0.0.54
"127.0.0.53"
];
# nscd -- the Name Service Caching Daemon -- caches DNS query responses
# in a way that's unaware of my VPN routing, so routes are frequently poor against
# services which advertise different IPs based on geolocation.
# nscd claims to be usable without a cache, but in practice i can't get it to not cache!
# nsncd is the Name Service NON-Caching Daemon. it's a drop-in that doesn't cache;
# this is OK on the host -- because systemd-resolved caches. it's probably sub-optimal
# in the netns and we query upstream DNS more often than needed. hm.
# TODO: run a separate recursive resolver in each namespace.
services.nscd.enableNsncd = true;
# services.resolved.extraConfig = ''
# # docs: `man resolved.conf`
# # DNS servers to use via the `wg0` interface.
# # i hope that from the root ns, these aren't visible.
# DNS=46.227.67.134%wg0 192.165.9.158%wg0
# FallbackDNS=1.1.1.1 9.9.9.9
# '';
# OVPN CONFIG (https://www.ovpn.com):
# DOCS: https://nixos.wiki/wiki/WireGuard
# if you `systemctl restart wireguard-wg0`, make sure to also restart any other services in `NetworkNamespacePath = .../ovpns`.
# TODO: why not create the namespace as a seperate operation (nix config for that?)
networking.wireguard.enable = true;
networking.wireguard.interfaces.wg0 = let
ip = "${pkgs.iproute2}/bin/ip";
in-ns = "${ip} netns exec ovpns";
iptables = "${pkgs.iptables}/bin/iptables";
veth-host-ip = "10.0.1.5";
veth-local-ip = "10.0.1.6";
vpn-ip = "185.157.162.178";
# DNS = 46.227.67.134, 192.165.9.158, 2a07:a880:4601:10f0:cd45::1, 2001:67c:750:1:cafe:cd45::1
vpn-dns = "46.227.67.134";
in {
privateKeyFile = config.sops.secrets.wg_ovpns_privkey.path;
# wg is active only in this namespace.
# run e.g. ip netns exec ovpns <some command like ping/curl/etc, it'll go through wg>
# sudo ip netns exec ovpns ping www.google.com
interfaceNamespace = "ovpns";
ips = [
"185.157.162.178/32"
];
peers = [
{
publicKey = "SkkEZDCBde22KTs/Hc7FWvDBfdOCQA4YtBEuC3n5KGs=";
endpoint = "185.157.162.10:9930";
# alternatively: use hostname, but that presents bootstrapping issues (e.g. if host net flakes)
# endpoint = "vpn36.prd.amsterdam.ovpn.com:9930";
allowedIPs = [ "0.0.0.0/0" ];
# nixOS says this is important for keeping NATs active
persistentKeepalive = 25;
# re-executes wg this often. docs hint that this might help wg notice DNS/hostname changes.
# so, maybe that helps if we specify endpoint as a domain name
# dynamicEndpointRefreshSeconds = 30;
# when refresh fails, try it again after this period instead.
# TODO: not avail until nixpkgs upgrade
# dynamicEndpointRefreshRestartSeconds = 5;
}
];
preSetup = "" + ''
${ip} netns add ovpns || echo "ovpns already exists"
'';
postShutdown = "" + ''
${in-ns} ip link del ovpns-veth-b || echo "couldn't delete ovpns-veth-b"
${ip} link del ovpns-veth-a || echo "couldn't delete ovpns-veth-a"
${ip} netns delete ovpns || echo "couldn't delete ovpns"
# restore rules/routes
${ip} rule del from ${veth-host-ip} lookup ovpns pref 50 || echo "couldn't delete init -> ovpns rule"
${ip} route del default via ${veth-local-ip} dev ovpns-veth-a proto kernel src ${veth-host-ip} metric 1002 table ovpns || echo "couldn't delete init -> ovpns route"
${ip} rule add from all lookup local pref 0
${ip} rule del from all lookup local pref 100
'';
postSetup = "" + ''
# DOCS:
# - some of this approach is described here: <https://josephmuia.ca/2018-05-16-net-namespaces-veth-nat/>
# - iptables primer: <https://danielmiessler.com/study/iptables/>
# create veth pair
${ip} link add ovpns-veth-a type veth peer name ovpns-veth-b
${ip} addr add ${veth-host-ip}/24 dev ovpns-veth-a
${ip} link set ovpns-veth-a up
# mv veth-b into the ovpns namespace
${ip} link set ovpns-veth-b netns ovpns
${in-ns} ip addr add ${veth-local-ip}/24 dev ovpns-veth-b
${in-ns} ip link set ovpns-veth-b up
# make it so traffic originating from the host side of the veth
# is sent over the veth no matter its destination.
${ip} rule add from ${veth-host-ip} lookup ovpns pref 50
# for traffic originating at the host veth to the WAN, use the veth as our gateway
# not sure if the metric 1002 matters.
${ip} route add default via ${veth-local-ip} dev ovpns-veth-a proto kernel src ${veth-host-ip} metric 1002 table ovpns
# give the default route lower priority
${ip} rule add from all lookup local pref 100
${ip} rule del from all lookup local pref 0
# bridge HTTP traffic:
# any external port-80 request sent to the VPN addr will be forwarded to the rootns.
# this exists so LetsEncrypt can procure a cert for the MX over http.
# TODO: we could use _acme_challence.mx.uninsane.org CNAME to avoid this forwarding
# - <https://community.letsencrypt.org/t/where-does-letsencrypt-resolve-dns-from/37607/8>
${in-ns} ${iptables} -A PREROUTING -t nat -p tcp --dport 80 -m iprange --dst-range ${vpn-ip} \
-j DNAT --to-destination ${veth-host-ip}:80
# we also bridge DNS traffic
${in-ns} ${iptables} -A PREROUTING -t nat -p udp --dport 53 -m iprange --dst-range ${vpn-ip} \
-j DNAT --to-destination ${veth-host-ip}:53
${in-ns} ${iptables} -A PREROUTING -t nat -p tcp --dport 53 -m iprange --dst-range ${vpn-ip} \
-j DNAT --to-destination ${veth-host-ip}:53
# in order to access DNS in this netns, we need to route it to the VPN's nameservers
# - alternatively, we could fix DNS servers like 1.1.1.1.
${in-ns} ${iptables} -A OUTPUT -t nat -p udp --dport 53 -m iprange --dst-range 127.0.0.53 \
-j DNAT --to-destination ${vpn-dns}:53
'';
};
# create a new routing table that we can use to proxy traffic out of the root namespace
# through the ovpns namespace, and to the WAN via VPN.
networking.iproute2.rttablesExtraConfig = ''
5 ovpns
'';
networking.iproute2.enable = true;
sops.secrets."wg_ovpns_privkey" = {
sopsFile = ../../secrets/servo.yaml;
};
# HURRICANE ELECTRIC CONFIG:
# networking.sits = {
# hurricane = {
# remote = "216.218.226.238";
# local = "192.168.0.5";
# # local = "10.0.0.5";
# # remote = "10.0.0.1";
# # local = "10.0.0.22";
# dev = "eth0";
# ttl = 255;
# };
# };
# networking.interfaces."hurricane".ipv6 = {
# addresses = [
# # mx.uninsane.org (publically routed /64)
# {
# address = "2001:470:b:465::1";
# prefixLength = 128;
# }
# # client addr
# # {
# # address = "2001:470:a:466::2";
# # prefixLength = 64;
# # }
# ];
# routes = [
# {
# address = "::";
# prefixLength = 0;
# # via = "2001:470:a:466::1";
# }
# ];
# };
# # after configuration, we want the hurricane device to look like this:
# # hurricane: flags=209<UP,POINTOPOINT,RUNNING,NOARP> mtu 1480
# # inet6 2001:470:a:450::2 prefixlen 64 scopeid 0x0<global>
# # inet6 fe80::c0a8:16 prefixlen 64 scopeid 0x20<link>
# # sit txqueuelen 1000 (IPv6-in-IPv4)
# # test with:
# # curl --interface hurricane http://[2607:f8b0:400a:80b::2004]
# # ping 2607:f8b0:400a:80b::2004
}

View File

@@ -0,0 +1,31 @@
{ config, lib, pkgs, ... }:
# using manual ddns now
lib.mkIf false
{
systemd.services.ddns-afraid = {
description = "update dynamic DNS entries for freedns.afraid.org";
serviceConfig = {
EnvironmentFile = config.sops.secrets.ddns_afraid.path;
# TODO: ProtectSystem = "strict";
# TODO: ProtectHome = "full";
# TODO: PrivateTmp = true;
};
script = let
curl = "${pkgs.curl}/bin/curl -4";
in ''
${curl} "https://freedns.afraid.org/dynamic/update.php?$AFRAID_KEY"
'';
};
systemd.timers.ddns-afraid = {
wantedBy = [ "multi-user.target" ];
timerConfig = {
OnStartupSec = "2min";
OnUnitActiveSec = "10min";
};
};
sops.secrets."ddns_afraid" = {
sopsFile = ../../../secrets/servo.yaml;
};
}

View File

@@ -1,5 +1,7 @@
{ config, pkgs, ... }:
{ config, lib, pkgs, ... }:
# we use manual DDNS now
lib.mkIf false
{
systemd.services.ddns-he = {
description = "update dynamic DNS entries for HurricaneElectric";

View File

@@ -1,19 +1,26 @@
{ ... }:
{
imports = [
./ddns-afraid.nix
./ddns-he.nix
./ejabberd.nix
./freshrss.nix
./gitea.nix
./goaccess.nix
./ipfs.nix
./jackett.nix
./jellyfin.nix
./kiwix-serve.nix
./matrix
./navidrome.nix
./nixserve.nix
./nginx.nix
./pleroma.nix
./postfix.nix
./postgres.nix
./prosody.nix
./transmission.nix
./trust-dns.nix
./wikipedia.nix
];
}

View File

@@ -0,0 +1,393 @@
# docs:
# - <https://docs.ejabberd.im/admin/configuration/basic>
# example configs:
# - <https://github.com/vkleen/machines/blob/138a2586ce185d7cf201d4e1fe898c83c4af52eb/hosts/europium/ejabberd.nix>
# - <https://github.com/Mic92/stockholm/blob/675ef0088624c9de1cb531f318446316884a9d3d/tv/3modules/ejabberd/default.nix>
# - <https://github.com/buffet/tararice/blob/master/programs/ejabberd.nix>
# - enables STUN and TURN
# - only over UDP 3478, not firewall-forwarding any TURN port range
# - uses stun_disco module (but with no options)
# - <https://github.com/leo60228/dotfiles/blob/39b3abba3009bdc31413d4757ca2f882a33eec8b/files/ejabberd.yml>
# - <https://github.com/Mic92/dotfiles/blob/ddf0f4821f554f7667fc803344657367c55fb9e6/nixos/eve/modules/ejabberd.nix>
# - <nixpkgs:nixos/tests/xmpp/ejabberd.nix>
# - 2013: <https://github.com/processone/ejabberd/blob/master/ejabberd.yml.example>
#
# compliance tests:
# - <https://compliance.conversations.im/server/uninsane.org/#xep0352>
{ config, lib, pkgs, ... }:
# XXX: avatar support works in MUCs but not DMs
# lib.mkIf false
{
sane.impermanence.dirs = [
{ user = "ejabberd"; group = "ejabberd"; directory = "/var/lib/ejabberd"; }
];
networking.firewall.allowedTCPPorts = [
3478 # STUN/TURN
5222 # XMPP client -> server
5223 # XMPPS client -> server (XMPP over TLS)
5269 # XMPP server -> server
5270 # XMPPS server -> server (XMPP over TLS)
5280 # bosh
5281 # bosh (https) ??
5349 # STUN/TURN (TLS)
5443 # web services (file uploads, websockets, admin)
];
networking.firewall.allowedUDPPorts = [
3478 # STUN/TURN
];
networking.firewall.allowedTCPPortRanges = [{
from = 49152; # TURN
to = 65535;
}];
networking.firewall.allowedUDPPortRanges = [{
from = 49152; # TURN
to = 65535;
}];
# provide access to certs
users.users.ejabberd.extraGroups = [ "nginx" ];
security.acme.certs."uninsane.org".extraDomainNames = [
"xmpp.uninsane.org"
"muc.xmpp.uninsane.org"
"pubsub.xmpp.uninsane.org"
"upload.xmpp.uninsane.org"
"vjid.xmpp.uninsane.org"
];
# exists so the XMPP server's cert can obtain altNames for all its resources
services.nginx.virtualHosts."xmpp.uninsane.org" = {
useACMEHost = "uninsane.org";
};
services.nginx.virtualHosts."muc.xmpp.uninsane.org" = {
useACMEHost = "uninsane.org";
};
services.nginx.virtualHosts."pubsub.xmpp.uninsane.org" = {
useACMEHost = "uninsane.org";
};
services.nginx.virtualHosts."upload.xmpp.uninsane.org" = {
useACMEHost = "uninsane.org";
};
services.nginx.virtualHosts."vjid.xmpp.uninsane.org" = {
useACMEHost = "uninsane.org";
};
sane.services.trust-dns.zones."uninsane.org".inet = {
# XXX: SRV records have to point to something with a A/AAAA record; no CNAMEs
A."xmpp" = [ "%NATIVE%" ];
CNAME."muc.xmpp" = [ "xmpp" ];
CNAME."pubsub.xmpp" = [ "xmpp" ];
CNAME."upload.xmpp" = [ "xmpp" ];
CNAME."vjid.xmpp" = [ "xmpp" ];
# _Service._Proto.Name TTL Class SRV Priority Weight Port Target
# - <https://xmpp.org/extensions/xep-0368.html>
# something's requesting the SRV records for muc.xmpp, so let's include it
# nothing seems to request XMPP SRVs for the other records (except @)
# lower numerical priority field tells clients to prefer this method
SRV."_xmpps-client._tcp.muc.xmpp" = [ "3 50 5223 xmpp" ];
SRV."_xmpps-server._tcp.muc.xmpp" = [ "3 50 5270 xmpp" ];
SRV."_xmpp-client._tcp.muc.xmpp" = [ "5 50 5222 xmpp" ];
SRV."_xmpp-server._tcp.muc.xmpp" = [ "5 50 5269 xmpp" ];
SRV."_xmpps-client._tcp" = [ "3 50 5223 xmpp" ];
SRV."_xmpps-server._tcp" = [ "3 50 5270 xmpp" ];
SRV."_xmpp-client._tcp" = [ "5 50 5222 xmpp" ];
SRV."_xmpp-server._tcp" = [ "5 50 5269 xmpp" ];
SRV."_stun._udp" = [ "5 50 3478 xmpp" ];
SRV."_stun._tcp" = [ "5 50 3478 xmpp" ];
SRV."_stuns._tcp" = [ "5 50 5349 xmpp" ];
SRV."_turn._udp" = [ "5 50 3478 xmpp" ];
SRV."_turn._tcp" = [ "5 50 3478 xmpp" ];
SRV."_turns._tcp" = [ "5 50 5349 xmpp" ];
};
# TODO: allocate UIDs/GIDs ?
services.ejabberd.enable = true;
services.ejabberd.configFile = "/var/lib/ejabberd/ejabberd.yaml";
systemd.services.ejabberd.preStart = let
config-in = pkgs.writeTextFile {
name = "ejabberd.yaml.in";
text = ''
hosts:
- uninsane.org
# none | emergency | alert | critical | error | warning | notice | info | debug
loglevel: debug
# loglevel: info
# loglevel: notice
acme:
auto: false
certfiles:
- /var/lib/acme/uninsane.org/full.pem
# ca_file: ${pkgs.cacert.unbundled}/etc/ssl/certs/
# ca_file: ${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt
pam_userinfotype: jid
acl:
admin:
user:
- "colin@uninsane.org"
local:
user_regexp: ""
loopback:
ip:
- 127.0.0.0/8
- ::1/128
access_rules:
local:
allow: local
c2s_access:
allow: all
announce:
allow: admin
configure:
allow: admin
muc_create:
allow: local
pubsub_createnode_access:
allow: all
trusted_network:
allow: loopback
# docs: <https://docs.ejabberd.im/admin/configuration/basic/#shaper-rules>
shaper_rules:
# setting this to above 1 may break outgoing messages
# - maybe some servers rate limit? or just don't understand simultaneous connections?
max_s2s_connections: 1
max_user_sessions: 10
max_user_offline_messages: 5000
c2s_shaper:
fast: all
s2s_shaper:
med: all
# docs: <https://docs.ejabberd.im/admin/configuration/basic/#shapers>
# this limits the bytes/sec.
# for example, burst: 3_000_000 and rate: 100_000 means:
# - each client has a BW budget that accumulates 100kB/sec and is capped at 3 MB
shaper:
fast: 1000000
med: 500000
# fast:
# - rate: 1000000
# - burst_size: 10000000
# med:
# - rate: 500000
# - burst_size: 5000000
# see: <https://docs.ejabberd.im/admin/configuration/listen/>
# s2s_use_starttls: true
s2s_use_starttls: optional
# lessens 504: remote-server-timeout errors
# see: <https://github.com/processone/ejabberd/issues/3105#issuecomment-562182967>
negotiation_timeout: 60
listen:
-
port: 5222
module: ejabberd_c2s
shaper: c2s_shaper
starttls: true
access: c2s_access
-
port: 5223
module: ejabberd_c2s
shaper: c2s_shaper
tls: true
access: c2s_access
-
port: 5269
module: ejabberd_s2s_in
shaper: s2s_shaper
-
port: 5270
module: ejabberd_s2s_in
shaper: s2s_shaper
tls: true
-
port: 5443
module: ejabberd_http
tls: true
request_handlers:
/admin: ejabberd_web_admin # TODO: ensure this actually works
/api: mod_http_api # ejabberd API endpoint (to control server)
/bosh: mod_bosh
/upload: mod_http_upload
/ws: ejabberd_http_ws
# /.well-known/host-meta: mod_host_meta
# /.well-known/host-meta.json: mod_host_meta
-
# STUN+TURN TCP
# note that the full port range should be forwarded ("not NAT'd")
# `use_turn=true` enables both TURN *and* STUN
port: 3478
module: ejabberd_stun
transport: tcp
use_turn: true
turn_min_port: 49152
turn_max_port: 65535
turn_ipv4_address: %NATIVE%
-
# STUN+TURN UDP
port: 3478
module: ejabberd_stun
transport: udp
use_turn: true
turn_min_port: 49152
turn_max_port: 65535
turn_ipv4_address: %NATIVE%
-
# STUN+TURN TLS over TCP
port: 5349
module: ejabberd_stun
transport: tcp
tls: true
certfile: /var/lib/acme/uninsane.org/full.pem
use_turn: true
turn_min_port: 49152
turn_max_port: 65535
turn_ipv4_address: %NATIVE%
# TODO: enable mod_fail2ban
# TODO(low): look into mod_http_fileserver for serving macros?
modules:
# mod_adhoc: {}
# mod_announce:
# access: admin
# allows users to set avatars in vCard
# - <https://docs.ejabberd.im/admin/configuration/modules/#mod-avatar>
mod_avatar: {}
mod_caps: {} # for mod_pubsub
mod_carboncopy: {} # allows multiple clients to receive a user's message
# queues messages when recipient is offline, including PEP and presence messages.
# compliance test suggests this be enabled
mod_client_state: {}
# mod_conversejs: TODO: enable once on 21.12
# allows clients like Dino to discover where to upload files
mod_disco:
server_info:
-
modules: all
name: abuse-addresses
urls:
- "mailto:admin.xmpp@uninsane.org"
- "xmpp:colin@uninsane.org"
-
modules: all
name: admin-addresses
urls:
- "mailto:admin.xmpp@uninsane.org"
- "xmpp:colin@uninsane.org"
mod_http_upload:
host: upload.xmpp.uninsane.org
hosts:
- upload.xmpp.uninsane.org
put_url: "https://@HOST@:5443/upload"
dir_mode: "0750"
file_mode: "0750"
rm_on_unregister: false
# allow discoverability of BOSH and websocket endpoints
# TODO: enable once on ejabberd 22.05 (presently 21.04)
# mod_host_meta: {}
mod_jidprep: {} # probably not needed: lets clients normalize jids
mod_last: {} # allow other users to know when i was last online
mod_mam:
# Mnesia is limited to 2GB, better to use an SQL backend
# For small servers SQLite is a good fit and is very easy
# to configure. Uncomment this when you have SQL configured:
# db_type: sql
assume_mam_usage: true
default: always
mod_muc:
access:
- allow
access_admin:
- allow: admin
access_create: muc_create
access_persistent: muc_create
access_mam:
- allow
history_size: 100 # messages to show new participants
host: muc.xmpp.uninsane.org
hosts:
- muc.xmpp.uninsane.org
default_room_options:
anonymous: false
lang: en
persistent: true
mam: true
mod_muc_admin: {}
mod_offline: # store messages for a user when they're offline (TODO: understand multi-client workflow?)
access_max_user_messages: max_user_offline_messages
store_groupchat: true
mod_ping: {}
mod_privacy: {} # deprecated, but required for `ejabberctl export_piefxis`
mod_private: {} # allow local clients to persist arbitrary data on my server
# push notifications to services integrated with e.g. Apple/Android.
# default is for a maximum amount of PII to be withheld, since these push notifs
# generally traverse 3rd party services. can opt to include message body, etc, though.
mod_push: {}
# i don't fully understand what this does, but it seems aimed at making push notifs more reliable.
mod_push_keepalive: {}
mod_roster:
versioning: true
# docs: <https://docs.ejabberd.im/admin/configuration/modules/#mod-s2s-dialback>
# s2s dialback to verify inbound messages
# unclear to what degree the XMPP network requires this
mod_s2s_dialback: {}
mod_shared_roster: {} # creates groups for @all, @online, and anything manually administered?
mod_stream_mgmt:
resend_on_timeout: if_offline # resend undelivered messages if the origin client is offline
# fallback for when DNS-based STUN discovery is unsupported.
# - see: <https://xmpp.org/extensions/xep-0215.html>
# docs: <https://docs.ejabberd.im/admin/configuration/modules/#mod-stun-disco>
# people say to just keep this defaulted (i guess ejabberd knows to return its `host` option of uninsane.org?)
mod_stun_disco: {}
# docs: <https://docs.ejabberd.im/admin/configuration/modules/#mod-vcard>
mod_vcard:
allow_return_all: true # all users are discoverable (?)
host: vjid.xmpp.uninsane.org
hosts:
- vjid.xmpp.uninsane.org
search: true
mod_vcard_xupdate: {} # needed for avatars
# docs: <https://docs.ejabberd.im/admin/configuration/modules/#mod-pubsub>
mod_pubsub: # needed for avatars
access_createnode: pubsub_createnode_access
host: pubsub.xmpp.uninsane.org
hosts:
- pubsub.xmpp.uninsane.org
ignore_pep_from_offline: false
last_item_cache: true
plugins:
- pep
- flat
force_node_config:
# ensure client bookmarks are private
storage:bookmarks:
access_model: whitelist
urn:xmpp:avatar:data:
access_model: open
urn:xmpp:avatar:metadata:
access_model: open
mod_version: {}
'';
};
sed = "${pkgs.gnused}/bin/sed";
in ''
ip=$(cat '${config.sane.services.dyn-dns.ipPath}')
# config is 444 (not 644), so we want to write out-of-place and then atomically move
# TODO: factor this out into `sane-woop` helper?
rm -f /var/lib/ejabberd/ejabberd.yaml.new
${sed} "s/%NATIVE%/$ip/" ${config-in} > /var/lib/ejabberd/ejabberd.yaml.new
mv /var/lib/ejabberd/ejabberd.yaml{.new,}
'';
sane.services.dyn-dns.restartOnChange = [ "ejabberd.service" ];
}

View File

@@ -16,7 +16,7 @@
owner = config.users.users.freshrss.name;
mode = "400";
};
sane.impermanence.service-dirs = [
sane.impermanence.dirs = [
{ user = "freshrss"; group = "freshrss"; directory = "/var/lib/freshrss"; }
];
@@ -30,7 +30,7 @@
systemd.services.freshrss-import-feeds =
let
fresh = config.systemd.services.freshrss-config;
feeds = import ../../../modules/universal/home-manager/feeds.nix { inherit lib; };
feeds = import ../../../modules/home-manager/feeds.nix { inherit lib; };
opml = pkgs.writeText "sane-freshrss.opml" (feeds.feedsToOpml feeds.all);
in {
inherit (fresh) wantedBy environment;
@@ -45,4 +45,17 @@
${pkgs.freshrss}/cli/import-for-user.php --user admin --filename ${opml}
'';
};
# the default ("*:0/5") is to run every 5 minutes.
# `systemctl list-timers` to show
systemd.services.freshrss-updater.startAt = lib.mkForce "*:3/30";
services.nginx.virtualHosts."rss.uninsane.org" = {
addSSL = true;
enableACME = true;
# inherit kTLS;
# the routing is handled by services.freshrss.virtualHost
};
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."rss" = [ "native" ];
}

View File

@@ -1,7 +1,7 @@
{ config, pkgs, lib, ... }:
{
sane.impermanence.service-dirs = [
sane.impermanence.dirs = [
# TODO: mode? could be more granular
{ user = "git"; group = "gitea"; directory = "/var/lib/gitea"; }
];
@@ -72,4 +72,18 @@
"/var/lib/gitea"
];
};
# hosted git (web view and for `git <cmd>` use
# TODO: enable publog?
services.nginx.virtualHosts."git.uninsane.org" = {
forceSSL = true; # gitea complains if served over a different protocol than its config file says
enableACME = true;
# inherit kTLS;
locations."/" = {
proxyPass = "http://127.0.0.1:3000";
};
};
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."git" = [ "native" ];
}

View File

@@ -14,6 +14,7 @@
-f /var/log/nginx/public.log \
--log-format=VCOMBINED \
--real-time-html \
--html-refresh=30 \
--no-query-string \
--anonymize-ip \
--ignore-panel=HOSTS \
@@ -24,6 +25,7 @@
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
Type = "simple";
Restart = "on-failure";
RestartSec = "10s";
# hardening
WorkingDirectory = "/tmp";
@@ -41,4 +43,26 @@
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
};
# server statistics
services.nginx.virtualHosts."sink.uninsane.org" = {
addSSL = true;
enableACME = true;
# inherit kTLS;
root = "/var/lib/uninsane/sink";
locations."/ws" = {
proxyPass = "http://127.0.0.1:7890";
# XXX not sure how much of this is necessary
extraConfig = ''
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;
proxy_read_timeout 7d;
'';
};
};
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."sink" = [ "native" ];
}

View File

@@ -6,26 +6,50 @@
# - number of open peer connections:
# - sudo -u ipfs -g ipfs ipfs -c /var/lib/ipfs/ swarm peers | wc -l
{ ... }:
{ lib, ... }:
lib.mkIf false # i don't actively use ipfs anymore
{
sane.impermanence.service-dirs = [
sane.impermanence.dirs = [
# TODO: mode? could be more granular
{ user = "261"; group = "261"; directory = "/var/lib/ipfs"; }
];
networking.firewall.allowedTCPPorts = [ 4001 ];
networking.firewall.allowedUDPPorts = [ 4001 ];
services.nginx.virtualHosts."ipfs.uninsane.org" = {
# don't default to ssl upgrades, since this may be dnslink'd from a different domain.
# ideally we'd disable ssl entirely, but some places assume it?
addSSL = true;
enableACME = true;
# inherit kTLS;
locations."/" = {
proxyPass = "http://127.0.0.1:8080";
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Ipfs-Gateway-Prefix "";
'';
};
};
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."ipfs" = [ "native" ];
# services.ipfs.enable = true;
services.kubo.localDiscovery = true;
services.kubo.swarmAddress = [
# "/dns4/ipfs.uninsane.org/tcp/4001"
# "/ip4/0.0.0.0/tcp/4001"
"/dns4/ipfs.uninsane.org/udp/4001/quic"
"/ip4/0.0.0.0/udp/4001/quic"
];
services.kubo.extraConfig = {
services.kubo.settings = {
Addresses = {
Announce = [
# "/dns4/ipfs.uninsane.org/tcp/4001"
"/dns4/ipfs.uninsane.org/udp/4001/quic"
];
Swarm = [
# "/dns4/ipfs.uninsane.org/tcp/4001"
# "/ip4/0.0.0.0/tcp/4001"
"/dns4/ipfs.uninsane.org/udp/4001/quic"
"/ip4/0.0.0.0/udp/4001/quic"
];
};
Gateway = {
# the gateway can only be used to serve content already replicated on this host

View File

@@ -1,18 +1,32 @@
{ ... }:
{
sane.impermanence.service-dirs = [
sane.impermanence.dirs = [
# TODO: mode? we only need this to save Indexer creds ==> migrate to config?
{ user = "root"; group = "root"; directory = "/var/lib/jackett"; }
];
services.jackett.enable = true;
systemd.services.jackett.after = ["wg0veth.service"];
systemd.services.jackett.after = [ "wireguard-wg0.service" ];
systemd.services.jackett.partOf = [ "wireguard-wg0.service" ];
systemd.services.jackett.serviceConfig = {
# run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns";
# patch jackett to listen on the public interfaces
# ExecStart = lib.mkForce "${pkgs.jackett}/bin/Jackett --NoUpdates --DataFolder /var/lib/jackett/.config/Jackett --ListenPublic";
};
# jackett torrent search
services.nginx.virtualHosts."jackett.uninsane.org" = {
forceSSL = true;
enableACME = true;
# inherit kTLS;
locations."/" = {
# proxyPass = "http://ovpns.uninsane.org:9117";
proxyPass = "http://10.0.1.6:9117";
};
};
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jackett" = [ "native" ];
}

View File

@@ -0,0 +1,69 @@
{ config, lib, ... }:
# TODO: re-enable after migrating media dir to /var/lib/uninsane/media
# else it's too spammy
lib.mkIf false
{
networking.firewall.allowedUDPPorts = [
1900 7359 # DLNA: https://jellyfin.org/docs/general/networking/index.html
];
sane.impermanence.dirs = [
# TODO: mode? could be more granular
{ user = "jellyfin"; group = "jellyfin"; directory = "/var/lib/jellyfin"; }
];
# Jellyfin multimedia server
# this is mostly taken from the official jellfin.org docs
services.nginx.virtualHosts."jelly.uninsane.org" = {
addSSL = true;
enableACME = true;
# inherit kTLS;
locations."/" = {
proxyPass = "http://127.0.0.1:8096";
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
'';
};
# locations."/web/" = {
# proxyPass = "http://127.0.0.1:8096/web/index.html";
# extraConfig = ''
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# proxy_set_header X-Forwarded-Protocol $scheme;
# proxy_set_header X-Forwarded-Host $http_host;
# '';
# };
locations."/socket" = {
proxyPass = "http://127.0.0.1:8096";
extraConfig = ''
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
'';
};
};
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jelly" = [ "native" ];
# users.users.jellyfin.uid = config.sane.allocations.jellyfin-uid;
# users.groups.jellyfin.gid = config.sane.allocations.jellyfin-gid;
services.jellyfin.enable = true;
}

View File

@@ -0,0 +1,17 @@
{ ... }:
{
sane.services.kiwix-serve = {
enable = true;
port = 8013;
zimPaths = [ "/var/lib/uninsane/www-archive/wikipedia_en_all_maxi_2022-05.zim" ];
};
services.nginx.virtualHosts."w.uninsane.org" = {
forceSSL = true;
enableACME = true;
# inherit kTLS;
locations."/".proxyPass = "http://127.0.0.1:8013";
};
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."w" = [ "native" ];
}

View File

@@ -1,6 +1,6 @@
# docs: https://nixos.wiki/wiki/Matrix
# docs: https://nixos.org/manual/nixos/stable/index.html#module-services-matrix-synapse
{ config, lib, ... }:
{ config, lib, pkgs, ... }:
{
imports = [
@@ -8,7 +8,7 @@
# ./irc.nix
];
sane.impermanence.service-dirs = [
sane.impermanence.dirs = [
{ user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/matrix-synapse"; }
];
services.matrix-synapse.enable = true;
@@ -77,6 +77,55 @@
# create a token with limited uses:
# curl -d '{ "uses_allowed": 1 }' --header "Authorization: Bearer <my_token>" localhost:8008/_synapse/admin/v1/registration_tokens/new
# matrix chat server
# TODO: was `publog`
services.nginx.virtualHosts."matrix.uninsane.org" = {
addSSL = true;
enableACME = true;
# inherit kTLS;
# TODO colin: replace this with something helpful to the viewer
# locations."/".extraConfig = ''
# return 404;
# '';
locations."/" = {
proxyPass = "http://127.0.0.1:8008";
};
# redirect browsers to the web client.
# i don't think native matrix clients ever fetch the root.
# ideally this would be put behind some user-agent test though.
locations."= /" = {
return = "301 https://web.matrix.uninsane.org";
};
# locations."/_matrix" = {
# proxyPass = "http://127.0.0.1:8008";
# };
};
# matrix web client
# docs: https://nixos.org/manual/nixos/stable/index.html#module-services-matrix-element-web
services.nginx.virtualHosts."web.matrix.uninsane.org" = {
forceSSL = true;
enableACME = true;
# inherit kTLS;
root = pkgs.element-web.override {
conf = {
default_server_config."m.homeserver" = {
"base_url" = "https://matrix.uninsane.org";
"server_name" = "uninsane.org";
};
};
};
};
sane.services.trust-dns.zones."uninsane.org".inet = {
CNAME."matrix" = [ "native" ];
CNAME."web.matrix" = [ "native" ];
};
sops.secrets.matrix_synapse_secrets = {
sopsFile = ../../../../secrets/servo.yaml;

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{
sane.impermanence.service-dirs = [
sane.impermanence.dirs = [
{ user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/mx-puppet-discord"; }
];

View File

@@ -1,7 +1,7 @@
{ config, lib, ... }:
{
sane.impermanence.service-dirs = [
sane.impermanence.dirs = [
# TODO: mode?
# user and group are both "matrix-appservice-irc"
{ user = "993"; group = "992"; directory = "/var/lib/matrix-appservice-irc"; }

View File

@@ -1,7 +1,7 @@
{ ... }:
{
sane.impermanence.service-dirs = [
sane.impermanence.dirs = [
{ user = "navidrome"; group = "navidrome"; directory = "/var/lib/private/navidrome"; }
];
services.navidrome.enable = true;
@@ -14,4 +14,13 @@
AutoImportPlaylists = false;
ScanSchedule = "@every 1h";
};
services.nginx.virtualHosts."music.uninsane.org" = {
forceSSL = true;
enableACME = true;
# inherit kTLS;
locations."/".proxyPass = "http://127.0.0.1:4533";
};
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."music" = [ "native" ];
}

View File

@@ -0,0 +1,168 @@
# docs: https://nixos.wiki/wiki/Nginx
{ config, pkgs, ... }:
let
# make the logs for this host "public" so that they show up in e.g. metrics
publog = vhost: vhost // {
extraConfig = (vhost.extraConfig or "") + ''
access_log /var/log/nginx/public.log vcombined;
'';
};
# kTLS = true; # in-kernel TLS for better perf
in
{
networking.firewall.allowedTCPPorts = [ 80 443 ];
services.nginx.enable = true;
services.nginx.appendConfig = ''
# use 1 process per core.
# may want to increase worker_connections too, but `ulimit -n` must be increased first.
worker_processes auto;
'';
# this is the standard `combined` log format, with the addition of $host
# so that we have the virtualHost in the log.
# KEEP IN SYNC WITH GOACCESS
# goaccess calls this VCOMBINED:
# - <https://gist.github.com/jyap808/10570005>
services.nginx.commonHttpConfig = ''
log_format vcombined '$host:$server_port $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referrer" "$http_user_agent"';
access_log /var/log/nginx/private.log vcombined;
'';
# sets gzip_comp_level = 5
services.nginx.recommendedGzipSettings = true;
# enables OCSP stapling (so clients don't need contact the OCSP server -- i do instead)
# - doesn't seem to, actually: <https://www.ssllabs.com/ssltest/analyze.html?d=uninsane.org>
# caches TLS sessions for 10m
services.nginx.recommendedTlsSettings = true;
# enables sendfile, tcp_nopush, tcp_nodelay, keepalive_timeout 65
services.nginx.recommendedOptimisation = true;
# web blog/personal site
services.nginx.virtualHosts."uninsane.org" = publog {
root = "${pkgs.uninsane-dot-org}/share/uninsane-dot-org";
# a lot of places hardcode https://uninsane.org,
# and then when we mix http + non-https, we get CORS violations
# and things don't look right. so force SSL.
forceSSL = true;
enableACME = true;
# inherit kTLS;
# for OCSP stapling
sslTrustedCertificate = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
# uninsane.org/share/foo => /var/lib/uninsane/root/share/foo.
# yes, nginx does not strip the prefix when evaluating against the root.
locations."/share".root = "/var/lib/uninsane/root";
# allow matrix users to discover that @user:uninsane.org is reachable via matrix.uninsane.org
locations."= /.well-known/matrix/server".extraConfig =
let
# use 443 instead of the default 8448 port to unite
# the client-server and server-server port for simplicity
server = { "m.server" = "matrix.uninsane.org:443"; };
in ''
add_header Content-Type application/json;
return 200 '${builtins.toJSON server}';
'';
locations."= /.well-known/matrix/client".extraConfig =
let
client = {
"m.homeserver" = { "base_url" = "https://matrix.uninsane.org"; };
"m.identity_server" = { "base_url" = "https://vector.im"; };
};
# ACAO required to allow element-web on any URL to request this json file
in ''
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
return 200 '${builtins.toJSON client}';
'';
# static URLs might not be aware of .well-known (e.g. registration confirmation URLs),
# so hack around that.
locations."/_matrix" = {
proxyPass = "http://127.0.0.1:8008";
};
locations."/_synapse" = {
proxyPass = "http://127.0.0.1:8008";
};
# allow ActivityPub clients to discover how to reach @user@uninsane.org
# TODO: waiting on https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3361/
# locations."/.well-known/nodeinfo" = {
# proxyPass = "http://127.0.0.1:4000";
# extraConfig = pleromaExtraConfig;
# };
};
# serve any site not listed above, if it's static.
# because we define it dynamically, SSL isn't trivial. support only http
# documented <https://nginx.org/en/docs/http/ngx_http_core_module.html#server_name>
services.nginx.virtualHosts."~^(?<domain>.+)$" = {
default = true;
addSSL = true;
enableACME = false;
sslCertificate = "/var/www/certs/wildcard/cert.pem";
sslCertificateKey = "/var/www/certs/wildcard/key.pem";
# sslCertificate = "/var/lib/acme/.minica/cert.pem";
# sslCertificateKey = "/var/lib/acme/.minica/key.pem";
# serverName = null;
locations."/" = {
# somehow this doesn't escape -- i get error 400 if i:
# curl 'http://..' --resolve '..:80:127.0.0.1'
root = "/var/www/sites/$domain";
# tryFiles = "$domain/$uri $domain/$uri/ =404";
};
};
security.acme.acceptTerms = true;
security.acme.defaults.email = "admin.acme@uninsane.org";
users.users.acme.uid = config.sane.allocations.acme-uid;
users.groups.acme.gid = config.sane.allocations.acme-gid;
sane.impermanence.dirs = [
# TODO: mode?
{ user = "acme"; group = "acme"; directory = "/var/lib/acme"; }
{ user = "colin"; group = "users"; directory = "/var/www/sites"; }
];
# let's encrypt default chain looks like:
# - End-entity certificate ← R3 ← ISRG Root X1 ← DST Root CA X3
# - <https://community.letsencrypt.org/t/production-chain-changes/150739>
# DST Root CA X3 expired in 2021 (?)
# the alternative chain is:
# - End-entity certificate ← R3 ← ISRG Root X1 (self-signed)
# using this alternative chain grants more compatibility for services like ejabberd
# but might decrease compatibility with very old clients that don't get updates (e.g. old android, iphone <= 4).
# security.acme.defaults.extraLegoFlags = [
security.acme.certs."uninsane.org" = rec {
# ISRG Root X1 results in lets encrypt sending the same chain as default,
# just without the final ISRG Root X1 ← DST Root CA X3 link.
# i.e. we could alternative clip the last item and achieve the exact same thing.
extraLegoRunFlags = [
"--preferred-chain" "ISRG Root X1"
];
extraLegoRenewFlags = extraLegoRunFlags;
};
# TODO: alternatively, we could clip the last cert IF it's expired,
# optionally outputting that to a new cert file.
# security.acme.defaults.postRun = "";
# create a self-signed SSL certificate for use with literally any domain.
# browsers will reject this, but proxies and local testing tools can be configured
# to accept it.
system.activationScripts.generate-x509-self-signed.text = ''
mkdir -p /var/www/certs/wildcard
test -f /var/www/certs/wildcard/key.pem || ${pkgs.openssl}/bin/openssl \
req -x509 -newkey rsa:4096 \
-keyout /var/www/certs/wildcard/key.pem \
-out /var/www/certs/wildcard/cert.pem \
-sha256 -nodes -days 3650 \
-addext 'subjectAltName=DNS:*' \
-subj '/CN=self-signed'
chmod 640 /var/www/certs/wildcard/{key,cert}.pem
chown root:nginx /var/www/certs/wildcard /var/www/certs/wildcard/{key,cert}.pem
'';
}

View File

@@ -0,0 +1,21 @@
{ config, ... }:
{
services.nginx.virtualHosts."nixcache.uninsane.org" = {
addSSL = true;
enableACME = true;
# inherit kTLS;
# serverAliases = [ "nixcache" ];
locations."/".extraConfig = ''
proxy_pass http://localhost:${toString config.services.nix-serve.port};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
'';
};
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."nixcache" = [ "native" ];
sane.services.nixserve.enable = true;
sane.services.nixserve.sopsFile = ../../../secrets/servo.yaml;
}

View File

@@ -1,10 +1,12 @@
# docs: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/pleroma.nix
# docs:
# - https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/networking/pleroma.nix
# - https://docs.pleroma.social/backend/configuration/cheatsheet/
#
# to run it in a oci-container: https://github.com/barrucadu/nixfiles/blob/master/services/pleroma.nix
{ config, pkgs, ... }:
{
sane.impermanence.service-dirs = [
sane.impermanence.dirs = [
# TODO: mode? could be more granular
{ user = "pleroma"; group = "pleroma"; directory = "/var/lib/pleroma"; }
];
@@ -48,16 +50,19 @@
redirect_on_failure: true
#base_url: "https://cache.pleroma.social"
# see for reference:
# - `force_custom_plan`: <https://docs.pleroma.social/backend/configuration/postgresql/#disable-generic-query-plans>
config :pleroma, Pleroma.Repo,
adapter: Ecto.Adapters.Postgres,
username: "pleroma",
database: "pleroma",
hostname: "localhost",
pool_size: 10,
prepare: :named,
parameters: [
plan_cache_mode: "force_custom_plan"
]
# XXX: prepare: :named is needed only for PG <= 12
# prepare: :named,
# password: "{secrets.pleroma.db_password}",
# Configure web push notifications
@@ -122,6 +127,7 @@
systemd.services.pleroma.serviceConfig = {
# postgres can be slow to service early requests, preventing pleroma from starting on the first try
Restart = "on-failure";
RestartSec = "10s";
};
# systemd.services.pleroma.serviceConfig = {
@@ -131,6 +137,50 @@
# CapabilityBoundingSet = lib.mkForce "~";
# };
# Pleroma server and web interface
# TODO: enable publog?
services.nginx.virtualHosts."fed.uninsane.org" = {
forceSSL = true; # pleroma redirects to https anyway
enableACME = true;
# inherit kTLS;
locations."/" = {
proxyPass = "http://127.0.0.1:4000";
# documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx
extraConfig = ''
# XXX colin: this block is in the nixos examples: i don't understand all of it
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'POST, PUT, DELETE, GET, PATCH, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Idempotency-Key' always;
add_header 'Access-Control-Expose-Headers' 'Link, X-RateLimit-Reset, X-RateLimit-Limit, X-RateLimit-Remaining, X-Request-Id' always;
if ($request_method = OPTIONS) {
return 204;
}
add_header X-XSS-Protection "1; mode=block";
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy same-origin;
add_header X-Download-Options noopen;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# proxy_set_header Host $http_host;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# colin: added this due to Pleroma complaining in its logs
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 16m;
'';
};
};
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."fed" = [ "native" ];
sops.secrets.pleroma_secrets = {
sopsFile = ../../../secrets/servo.yaml;
owner = config.users.users.pleroma.name;

View File

@@ -16,7 +16,7 @@ let
};
in
{
sane.impermanence.service-dirs = [
sane.impermanence.dirs = [
# TODO: mode? could be more granular
{ user = "opendkim"; group = "opendkim"; directory = "/var/lib/opendkim"; }
{ user = "root"; group = "root"; directory = "/var/lib/postfix"; }
@@ -25,6 +25,61 @@ in
# "/var/lib/dhparams" # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/dhparams.nix
# "/var/lib/dovecot"
];
networking.firewall.allowedTCPPorts = [
25 # SMTP
143 # IMAP
465 # SMTPS
587 # SMTPS/submission
993 # IMAPS
];
# exists only to manage certs for dovecot
services.nginx.virtualHosts."imap.uninsane.org" = {
enableACME = true;
};
# exists only to manage certs for Postfix
services.nginx.virtualHosts."mx.uninsane.org" = {
enableACME = true;
};
sane.services.trust-dns.zones."uninsane.org".inet = {
MX."@" = [ "10 mx.uninsane.org." ];
# XXX: RFC's specify that the MX record CANNOT BE A CNAME
A."mx" = [ "185.157.162.178" ];
CNAME."imap" = [ "native" ];
# Sender Policy Framework:
# +mx => mail passes if it originated from the MX
# +a => mail passes if it originated from the A address of this domain
# +ip4:.. => mail passes if it originated from this IP
# -all => mail fails if none of these conditions were met
TXT."@" = [ "v=spf1 a mx -all" ];
# DKIM public key:
TXT."mx._domainkey" = [
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkSyMufc2KrRx3j17e/LyB+3eYSBRuEFT8PUka8EDX04QzCwDPdkwgnj3GNDvnB5Ktb05Cf2SJ/S1OLqNsINxJRWtkVfZd/C339KNh9wrukMKRKNELL9HLUw0bczOI4gKKFqyrRE9qm+4csCMAR79Te9FCjGV/jVnrkLdPT0GtFwIDAQAB"
];
# DMARC fields <https://datatracker.ietf.org/doc/html/rfc7489>:
# p=none|quarantine|reject: what to do with failures
# sp = p but for subdomains
# rua = where to send aggregrate reports
# ruf = where to send individual failure reports
# fo=0|1|d|s controls WHEN to send failure reports
# (1=on bad alignment; d=on DKIM failure; s=on SPF failure);
# Additionally:
# adkim=r|s (is DKIM relaxed [default] or strict)
# aspf=r|s (is SPF relaxed [default] or strict)
# pct = sampling ratio for punishing failures (default 100 for 100%)
# rf = report format
# ri = report interval
TXT."_dmarc" = [
"v=DMARC1;p=quarantine;sp=reject;rua=mailto:admin+mail@uninsane.org;ruf=mailto:admin+mail@uninsane.org;fo=1:d:s"
];
};
services.postfix.enable = true;
services.postfix.hostname = "mx.uninsane.org";
services.postfix.origin = "uninsane.org";
@@ -55,7 +110,8 @@ in
services.postfix.enableSubmissions = true;
services.postfix.submissionsOptions = submissionOptions;
systemd.services.postfix.after = [ "wg0veth.service" ];
systemd.services.postfix.after = [ "wireguard-wg0.service" ];
systemd.services.postfix.partOf = [ "wireguard-wg0.service" ];
systemd.services.postfix.serviceConfig = {
# run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns";
@@ -76,7 +132,8 @@ in
# keeping this the same as the hostname seems simplest
services.opendkim.selector = "mx";
systemd.services.opendkim.after = [ "wg0veth.service" ];
systemd.services.opendkim.after = [ "wireguard-wg0.service" ];
systemd.services.opendkim.partOf = [ "wireguard-wg0.service" ];
systemd.services.opendkim.serviceConfig = {
# run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns";

View File

@@ -1,7 +1,7 @@
{ ... }:
{
sane.impermanence.service-dirs = [
sane.impermanence.dirs = [
# TODO: mode?
{ user = "postgres"; group = "postgres"; directory = "/var/lib/postgresql"; }
];
@@ -17,6 +17,11 @@
# LC_CTYPE = "C";
# '';
# TODO: perf tuning
# - for recommended values see: <https://pgtune.leopard.in.ua/>
# - for official docs (sparse), see: <https://www.postgresql.org/docs/11/config-setting.html#CONFIG-SETTING-CONFIGURATION-FILE>
# services.postgresql.settings = { ... }
# daily backups to /var/backup
services.postgresqlBackup.enable = true;

View File

@@ -0,0 +1,64 @@
# example configs:
# - <https://github.com/kittywitch/nixfiles/blob/main/services/prosody.nix>
# create users with:
# - `sudo -u prosody prosodyctl adduser colin@uninsane.org`
{ lib, ... }:
# XXX disabled: doesn't send messages to nixnet.social (only receives them).
# nixnet runs ejabberd, so revisiting that.
lib.mkIf false
{
sane.impermanence.dirs = [
{ user = "prosody"; group = "prosody"; directory = "/var/lib/prosody"; }
];
networking.firewall.allowedTCPPorts = [
5222 # XMPP client -> server
5269 # XMPP server -> server
5280 # bosh
5281 # Prosody HTTPS port (necessary?)
];
# provide access to certs
users.users.prosody.extraGroups = [ "nginx" ];
security.acme.certs."uninsane.org".extraDomainNames = [
"conference.xmpp.uninsane.org"
"upload.xmpp.uninsane.org"
];
services.prosody = {
enable = true;
admins = [ "colin@uninsane.org" ];
# allowRegistration = false;
# extraConfig = ''
# s2s_require_encryption = true
# c2s_require_encryption = true
# '';
extraModules = [ "private" "vcard" "privacy" "compression" "component" "muc" "pep" "adhoc" "lastactivity" "admin_adhoc" "blocklist"];
ssl.cert = "/var/lib/acme/uninsane.org/fullchain.pem";
ssl.key = "/var/lib/acme/uninsane.org/key.pem";
muc = [
{
domain = "conference.xmpp.uninsane.org";
}
];
uploadHttp.domain = "upload.xmpp.uninsane.org";
virtualHosts = {
localhost = {
domain = "localhost";
enabled = true;
};
"xmpp.uninsane.org" = {
domain = "uninsane.org";
enabled = true;
ssl.cert = "/var/lib/acme/uninsane.org/fullchain.pem";
ssl.key = "/var/lib/acme/uninsane.org/key.pem";
};
};
};
}

View File

@@ -1,7 +1,7 @@
{ ... }:
{ pkgs, ... }:
{
sane.impermanence.service-dirs = [
sane.impermanence.dirs = [
# TODO: mode? we need this specifically for the stats tracking in .config/
{ user = "transmission"; group = "transmission"; directory = "/var/lib/transmission"; }
];
@@ -40,11 +40,41 @@
# transmission will by default not allow the world to read its files.
services.transmission.downloadDirPermissions = "775";
systemd.services.transmission.after = ["wg0veth.service"];
systemd.services.transmission.after = [ "wireguard-wg0.service" ];
systemd.services.transmission.partOf = [ "wireguard-wg0.service" ];
systemd.services.transmission.serviceConfig = {
# run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns";
LogLevelMax = "warning";
};
# service to automatically backup torrents i add to transmission
systemd.services.backup-torrents = {
description = "archive torrents to storage not owned by transmission";
script = ''
${pkgs.rsync}/bin/rsync -arv /var/lib/transmission/.config/transmission-daemon/torrents/ /var/backup/torrents/
'';
};
systemd.timers.backup-torrents = {
wantedBy = [ "multi-user.target" ];
timerConfig = {
OnStartupSec = "11min";
OnUnitActiveSec = "240min";
};
};
# transmission web client
services.nginx.virtualHosts."bt.uninsane.org" = {
# basicAuth is literally cleartext user/pw, so FORCE this to happen over SSL
forceSSL = true;
enableACME = true;
# inherit kTLS;
locations."/" = {
# proxyPass = "http://ovpns.uninsane.org:9091";
proxyPass = "http://10.0.1.6:9091";
};
};
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."bt" = ["native"];
}

View File

@@ -0,0 +1,66 @@
{ config, pkgs, ... }:
{
sane.services.trust-dns.enable = true;
sane.services.trust-dns.listenAddrsIPv4 = [
# specify each address explicitly, instead of using "*".
# this ensures responses are sent from the address at which the request was received.
"192.168.0.5"
"10.0.1.5"
];
sane.services.trust-dns.zones."uninsane.org".TTL = 900;
# SOA record structure: <https://en.wikipedia.org/wiki/SOA_record#Structure>
# SOA MNAME RNAME (... rest)
# MNAME = Master name server for this zone. this is where update requests should be sent.
# RNAME = admin contact (encoded email address)
# Serial = YYYYMMDDNN, where N is incremented every time this file changes, to trigger secondary NS to re-fetch it.
# Refresh = how frequently secondary NS should query master
# Retry = how long secondary NS should wait until re-querying master after a failure (must be < Refresh)
# Expire = how long secondary NS should continue to reply to queries after master fails (> Refresh + Retry)
sane.services.trust-dns.zones."uninsane.org".inet = {
SOA."@" = [''
ns1.uninsane.org. admin-dns.uninsane.org. (
2022122101 ; Serial
4h ; Refresh
30m ; Retry
7d ; Expire
5m) ; Negative response TTL
''];
TXT."rev" = [ "2022122101" ];
# XXX NS records must also not be CNAME
# it's best that we keep this identical, or a superset of, what org. lists as our NS.
# so, org. can specify ns2/ns3 as being to the VPN, with no mention of ns1. we provide ns1 here.
A."ns1" = [ "%NATIVE%" ];
A."ns2" = [ "185.157.162.178" ];
A."ns3" = [ "185.157.162.178" ];
A."ovpns" = [ "185.157.162.178" ];
A."native" = [ "%NATIVE%" ];
A."@" = [ "%NATIVE%" ];
NS."@" = [
"ns1.uninsane.org."
"ns2.uninsane.org."
"ns3.uninsane.org."
];
};
sane.services.trust-dns.zones."uninsane.org".file =
"/var/lib/trust-dns/uninsane.org.zone";
systemd.services.trust-dns.preStart = let
sed = "${pkgs.gnused}/bin/sed";
zone-dir = "/var/lib/trust-dns";
zone-out = "${zone-dir}/uninsane.org.zone";
zone-template = pkgs.writeText "uninsane.org.zone.in" config.sane.services.trust-dns.generatedZones."uninsane.org";
in ''
# make WAN records available to trust-dns
mkdir -p ${zone-dir}
ip=$(cat '${config.sane.services.dyn-dns.ipPath}')
${sed} s/%NATIVE%/$ip/ ${zone-template} > ${zone-out}
'';
sane.services.dyn-dns.restartOnChange = [ "trust-dns.service" ];
}

View File

@@ -0,0 +1,33 @@
# docs: <https://nixos.wiki/wiki/MediaWiki>
{ config, lib, ... }:
# XXX: working to host wikipedia with kiwix instead of mediawiki
# mediawiki does more than i need and isn't obviously superior in any way
# except that the dumps are more frequent/up-to-date.
lib.mkIf false
{
sops.secrets."mediawiki_pw" = {
owner = config.users.users.mediawiki.name;
sopsFile = ../../../secrets/servo.yaml;
};
users.users.mediawiki.uid = config.sane.allocations.mediawiki-uid;
services.mediawiki.enable = true;
services.mediawiki.name = "Uninsane Wiki";
services.mediawiki.passwordFile = config.sops.secrets.mediawiki_pw.path;
services.mediawiki.extraConfig = ''
# Disable anonymous editing
$wgGroupPermissions['*']['edit'] = false;
'';
services.mediawiki.virtualHost.listen = [
{
ip = "127.0.0.1";
port = 8013;
ssl = false;
}
];
services.mediawiki.virtualHost.hostName = "w.uninsane.org";
services.mediawiki.virtualHost.adminAddr = "admin+mediawiki@uninsane.org";
# services.mediawiki.extensions = TODO: wikipedia sync extension?
}

View File

@@ -1,11 +0,0 @@
# trampoline from flake.nix into the specific machine definition, while doing a tiny bit of common setup
hostName: { ... }: {
imports = [
./${hostName}
];
networking.hostName = hostName;
nixpkgs.config.allowUnfree = true;
}

View File

@@ -1,69 +0,0 @@
{ ... }:
{
# root is a tmpfs so that we have an ephemeral system ("impermanence" handles the state)
fileSystems."/" = {
device = "none";
fsType = "tmpfs";
options = [
"mode=755"
"size=1G"
"defaults"
];
};
# we need a /tmp for building large nix things
fileSystems."/tmp" = {
device = "none";
fsType = "tmpfs";
options = [
"size=40G"
"mode=777"
"defaults"
];
};
fileSystems."/nix" = {
device = "/dev/disk/by-uuid/aa272cff-0fcc-498e-a4cb-0d95fb60631b";
fsType = "btrfs";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/31D3-40CB";
fsType = "vfat";
};
# fileSystems."/var/lib/pleroma" = {
# device = "/opt/pleroma";
# options = [ "bind" ];
# };
# in-memory compressed RAM (seems to be dynamically sized)
zramSwap = {
enable = true;
};
# btrfs doesn't easily support swapfiles
# swapDevices = [
# { device = "/nix/persist/swapfile"; size = 4096; }
# ];
# this can be a partition. create with:
# fdisk <dev>
# n
# <default partno>
# <start>
# <end>
# t
# <partno>
# 19 # set part type to Linux swap
# w # write changes
# mkswap -L swap <part>
swapDevices = [
{
label = "swap";
# TODO: randomEncryption.enable = true;
}
];
}

View File

@@ -1,75 +0,0 @@
# this file originates from nixos-generate-config
# but has been heavily modified
{ pkgs, ... }:
{
# i changed this becuse linux 5.10 didn't have rpi-400 device tree blob.
# nixos-22.05 linux 5.15 DOES have these now.
# it should be possible to remove this if desired, but i'm not sure how the rpi-specific kernel differs.
# see: https://github.com/raspberrypi/linux
boot.kernelPackages = pkgs.linuxPackages_rpi4;
# raspberryPi boot loader creates extlinux.conf.
# otherwise, enable the generic-extlinux-compatible loader below.
# note: THESE ARE MUTUALLY EXCLUSIVE. generic-extlinux-compatible causes uboot to not be built
boot.initrd.availableKernelModules = [
"bcm2711_thermal"
"bcm_phy_lib"
"brcmfmac"
"brcmutil"
"broadcom"
"clk_raspberrypi"
"drm" # Direct Render Manager
"enclosure" # SCSI ?
"fuse"
"mdio_bcm_unimac"
"pcie_brcmstb"
"raspberrypi_cpufreq"
"raspberrypi_hwmon"
"ses" # SCSI Enclosure Services
"uas" # USB attached storage
"uio" # userspace IO
"uio_pdrv_genirq"
"xhci_pci"
"xhci_pci_renesas"
];
# boot.initrd.compressor = "gzip"; # defaults to zstd
# ondemand power scaling keeps the cpu at low frequency when idle, and sets to max frequency
# when load is detected. (v.s. the "performance" default, which always uses the max frequency)
powerManagement.cpuFreqGovernor = "ondemand";
# XXX colin: this allows one to `systemctl halt` and then not remove power until the HDD has spun down.
# however, it doesn't work with reboot because systemd will spin the drive up again to read its reboot bin.
# a better solution would be to put the drive behind a powered USB hub (or get a SSD).
# systemd.services.diskguard = {
# description = "Safely power off spinning media";
# before = [ "shutdown.target" ];
# wantedBy = [ "sysinit.target" ];
# # old (creates dep loop, but works)
# # before = [ "systemd-remount-fs.service" "shutdown.target" ];
# # wantedBy = [ "systemd-remount-fs.service" ];
# serviceConfig = {
# Type = "oneshot";
# RemainAfterExit = true;
# ExecStart = "${pkgs.coreutils}/bin/true";
# ExecStop = with pkgs; writeScript "diskguard" ''
# #!${bash}/bin/bash
# if ${procps}/bin/pgrep nixos-rebuild ;
# then
# exit 0 # don't halt drives unless we're actually shutting down. maybe better way to do this (check script args?)
# fi
# # ${coreutils}/bin/sync
# # ${util-linux}/bin/mount -o remount,ro /nix/store
# # ${util-linux}/bin/mount -o remount,ro /
# # -S 1 retracts the spindle after 5 seconds of idle
# # -B 1 spins down the drive after <vendor specific duration>
# ${hdparm}/sbin/hdparm -S 1 -B 1 /dev/sda
# # TODO: monitor smartmonctl until disk is idle? or try hdparm -Y
# # ${coreutils}/bin/sleep 20
# # exec ${util-linux}/bin/umount --all -t ext4,vfat,ext2
# '';
# };
# };
}

View File

@@ -1,139 +0,0 @@
{ config, pkgs, ... }:
{
networking.domain = "uninsane.org";
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
# Per-interface useDHCP will be mandatory in the future, so this generated config
# replicates the default behaviour.
networking.useDHCP = false;
networking.interfaces.eth0.useDHCP = true;
# XXX colin: probably don't need this. wlan0 won't be populated unless i touch a value in networking.interfaces.wlan0
networking.wireless.enable = false;
# networking.firewall.enable = false;
networking.firewall.enable = true;
networking.firewall.allowedTCPPorts = [
25 # SMTP
80 # HTTP
143 # IMAP
443 # HTTPS
465 # SMTPS
587 # SMTPS/submission
993 # IMAPS
4001 # IPFS
];
networking.firewall.allowedUDPPorts = [
1900 7359 # DLNA: https://jellyfin.org/docs/general/networking/index.html
4001 # IPFS
];
# we need to use externally-visible nameservers in order for VPNs to be able to resolve hosts.
networking.nameservers = [
"1.1.1.1"
"9.9.9.9"
];
# OVPN CONFIG (https://www.ovpn.com):
# DOCS: https://nixos.wiki/wiki/WireGuard
networking.wireguard.enable = true;
networking.wireguard.interfaces.wg0 = {
privateKeyFile = config.sops.secrets.wg_ovpns_privkey.path;
# wg is active only in this namespace.
# run e.g. ip netns exec ovpns <some command like ping/curl/etc, it'll go through wg>
# sudo ip netns exec ovpns ping www.google.com
# note: without the namespace, you'll need to add a specific route through eth0 for the peer (185.157.162.178/32)
interfaceNamespace = "ovpns";
preSetup = "${pkgs.iproute2}/bin/ip netns add ovpns || true";
postShutdown = "${pkgs.iproute2}/bin/ip netns delete ovpns";
ips = [
"185.157.162.178/32"
];
peers = [
{
publicKey = "SkkEZDCBde22KTs/Hc7FWvDBfdOCQA4YtBEuC3n5KGs=";
endpoint = "vpn36.prd.amsterdam.ovpn.com:9930";
allowedIPs = [ "0.0.0.0/0" ];
# nixOS says this is important for keeping NATs active
persistentKeepalive = 25;
}
];
};
systemd.services.wg0veth = {
description = "veth pair to allow communication between host and wg0 netns";
after = [ "wireguard-wg0.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = with pkgs; writeScript "wg0veth-start" ''
#!${bash}/bin/bash
# create veth pair
${iproute2}/bin/ip link add ovpns-veth-a type veth peer name ovpns-veth-b
${iproute2}/bin/ip addr add 10.0.1.5/24 dev ovpns-veth-a
${iproute2}/bin/ip link set ovpns-veth-a up
# mv veth-b into the ovpns namespace
${iproute2}/bin/ip link set ovpns-veth-b netns ovpns
${iproute2}/bin/ip -n ovpns addr add 10.0.1.6/24 dev ovpns-veth-b
${iproute2}/bin/ip -n ovpns link set ovpns-veth-b up
# forward HTTP traffic, which we need for letsencrypt to work
${iproute2}/bin/ip netns exec ovpns ${socat}/bin/socat TCP4-LISTEN:80,reuseaddr,fork,su=nobody TCP4:10.0.1.5:80 &
'';
ExecStop = with pkgs; writeScript "wg0veth-stop" ''
#!${bash}/bin/bash
${iproute2}/bin/ip -n wg0 link del ovpns-veth-b
${iproute2}/bin/ip link del ovpns-veth-a
'';
};
};
sops.secrets."wg_ovpns_privkey" = {
sopsFile = ../../secrets/servo.yaml;
};
# HURRICANE ELECTRIC CONFIG:
# networking.sits = {
# hurricane = {
# remote = "216.218.226.238";
# local = "192.168.0.5";
# # local = "10.0.0.5";
# # remote = "10.0.0.1";
# # local = "10.0.0.22";
# dev = "eth0";
# ttl = 255;
# };
# };
# networking.interfaces."hurricane".ipv6 = {
# addresses = [
# # mx.uninsane.org (publically routed /64)
# {
# address = "2001:470:b:465::1";
# prefixLength = 128;
# }
# # client addr
# # {
# # address = "2001:470:a:466::2";
# # prefixLength = 64;
# # }
# ];
# routes = [
# {
# address = "::";
# prefixLength = 0;
# # via = "2001:470:a:466::1";
# }
# ];
# };
# # after configuration, we want the hurricane device to look like this:
# # hurricane: flags=209<UP,POINTOPOINT,RUNNING,NOARP> mtu 1480
# # inet6 2001:470:a:450::2 prefixlen 64 scopeid 0x0<global>
# # inet6 fe80::c0a8:16 prefixlen 64 scopeid 0x20<link>
# # sit txqueuelen 1000 (IPv6-in-IPv4)
# # test with:
# # curl --interface hurricane http://[2607:f8b0:400a:80b::2004]
# # ping 2607:f8b0:400a:80b::2004
}

View File

@@ -1,14 +0,0 @@
{ config, ... }:
{
sane.impermanence.service-dirs = [
# TODO: mode? could be more granular
{ user = "jellyfin"; group = "jellyfin"; directory = "/var/lib/jellyfin"; }
];
# users.users.jellyfin.uid = config.sane.allocations.jellyfin-uid;
# users.groups.jellyfin.gid = config.sane.allocations.jellyfin-gid;
# TODO: re-enable after migrating media dir to /var/lib/uninsane/media
# else it's too spammy
# services.jellyfin.enable = true;
}

View File

@@ -1,320 +0,0 @@
# docs: https://nixos.wiki/wiki/Nginx
{ config, pkgs, ... }:
let
# make the logs for this host "public" so that they show up in e.g. metrics
publog = vhost: vhost // {
extraConfig = (vhost.extraConfig or "") + ''
access_log /var/log/nginx/public.log vcombined;
'';
};
in
{
services.nginx.enable = true;
# this is the standard `combined` log format, with the addition of $host
# so that we have the virtualHost in the log.
# KEEP IN SYNC WITH GOACCESS
# goaccess calls this VCOMBINED:
# - <https://gist.github.com/jyap808/10570005>
services.nginx.commonHttpConfig = ''
log_format vcombined '$host:$server_port $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referrer" "$http_user_agent"';
access_log /var/log/nginx/private.log vcombined;
'';
# web blog/personal site
services.nginx.virtualHosts."uninsane.org" = publog {
root = "${pkgs.uninsane-dot-org}/share/uninsane-dot-org";
# a lot of places hardcode https://uninsane.org,
# and then when we mix http + non-https, we get CORS violations
# and things don't look right. so force SSL.
forceSSL = true;
enableACME = true;
# uninsane.org/share/foo => /var/lib/uninsane/root/share/foo.
# yes, nginx does not strip the prefix when evaluating against the root.
locations."/share".root = "/var/lib/uninsane/root";
# allow matrix users to discover that @user:uninsane.org is reachable via matrix.uninsane.org
locations."= /.well-known/matrix/server".extraConfig =
let
# use 443 instead of the default 8448 port to unite
# the client-server and server-server port for simplicity
server = { "m.server" = "matrix.uninsane.org:443"; };
in ''
add_header Content-Type application/json;
return 200 '${builtins.toJSON server}';
'';
locations."= /.well-known/matrix/client".extraConfig =
let
client = {
"m.homeserver" = { "base_url" = "https://matrix.uninsane.org"; };
"m.identity_server" = { "base_url" = "https://vector.im"; };
};
# ACAO required to allow element-web on any URL to request this json file
in ''
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
return 200 '${builtins.toJSON client}';
'';
# static URLs might not be aware of .well-known (e.g. registration confirmation URLs),
# so hack around that.
locations."/_matrix" = {
proxyPass = "http://127.0.0.1:8008";
};
locations."/_synapse" = {
proxyPass = "http://127.0.0.1:8008";
};
# allow ActivityPub clients to discover how to reach @user@uninsane.org
# TODO: waiting on https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3361/
# locations."/.well-known/nodeinfo" = {
# proxyPass = "http://127.0.0.1:4000";
# extraConfig = pleromaExtraConfig;
# };
};
# server statistics
services.nginx.virtualHosts."sink.uninsane.org" = {
addSSL = true;
enableACME = true;
root = "/var/lib/uninsane/sink";
locations."/ws" = {
proxyPass = "http://127.0.0.1:7890";
# XXX not sure how much of this is necessary
extraConfig = ''
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;
proxy_read_timeout 7d;
'';
};
};
# Pleroma server and web interface
services.nginx.virtualHosts."fed.uninsane.org" = publog {
addSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:4000";
# documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx
extraConfig = ''
# XXX colin: this block is in the nixos examples: i don't understand all of it
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'POST, PUT, DELETE, GET, PATCH, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Idempotency-Key' always;
add_header 'Access-Control-Expose-Headers' 'Link, X-RateLimit-Reset, X-RateLimit-Limit, X-RateLimit-Remaining, X-Request-Id' always;
if ($request_method = OPTIONS) {
return 204;
}
add_header X-XSS-Protection "1; mode=block";
add_header X-Permitted-Cross-Domain-Policies none;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy same-origin;
add_header X-Download-Options noopen;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# proxy_set_header Host $http_host;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# colin: added this due to Pleroma complaining in its logs
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 16m;
'';
};
};
# transmission web client
services.nginx.virtualHosts."bt.uninsane.org" = {
# basicAuth is literally cleartext user/pw, so FORCE this to happen over SSL
forceSSL = true;
enableACME = true;
locations."/" = {
# proxyPass = "http://ovpns.uninsane.org:9091";
proxyPass = "http://10.0.1.6:9091";
};
};
# jackett torrent search
services.nginx.virtualHosts."jackett.uninsane.org" = {
forceSSL = true;
enableACME = true;
locations."/" = {
# proxyPass = "http://ovpns.uninsane.org:9117";
proxyPass = "http://10.0.1.6:9117";
};
};
# matrix chat server
services.nginx.virtualHosts."matrix.uninsane.org" = publog {
addSSL = true;
enableACME = true;
# TODO colin: replace this with something helpful to the viewer
# locations."/".extraConfig = ''
# return 404;
# '';
locations."/" = {
proxyPass = "http://127.0.0.1:8008";
};
# redirect browsers to the web client.
# i don't think native matrix clients ever fetch the root.
# ideally this would be put behind some user-agent test though.
locations."= /" = {
return = "301 https://web.matrix.uninsane.org";
};
# locations."/_matrix" = {
# proxyPass = "http://127.0.0.1:8008";
# };
};
# matrix web client
# docs: https://nixos.org/manual/nixos/stable/index.html#module-services-matrix-element-web
services.nginx.virtualHosts."web.matrix.uninsane.org" = {
forceSSL = true;
enableACME = true;
root = pkgs.element-web.override {
conf = {
default_server_config."m.homeserver" = {
"base_url" = "https://matrix.uninsane.org";
"server_name" = "uninsane.org";
};
};
};
};
# hosted git (web view and for `git <cmd>` use
services.nginx.virtualHosts."git.uninsane.org" = publog {
addSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:3000";
};
};
# Jellyfin multimedia server
# this is mostly taken from the official jellfin.org docs
services.nginx.virtualHosts."jelly.uninsane.org" = {
addSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:8096";
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
'';
};
# locations."/web/" = {
# proxyPass = "http://127.0.0.1:8096/web/index.html";
# extraConfig = ''
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# proxy_set_header X-Forwarded-Protocol $scheme;
# proxy_set_header X-Forwarded-Host $http_host;
# '';
# };
locations."/socket" = {
proxyPass = "http://127.0.0.1:8096";
extraConfig = ''
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
'';
};
};
services.nginx.virtualHosts."music.uninsane.org" = {
forceSSL = true;
enableACME = true;
locations."/".proxyPass = "http://127.0.0.1:4533";
};
services.nginx.virtualHosts."rss.uninsane.org" = {
addSSL = true;
enableACME = true;
# the routing is handled by freshrss.nix
};
services.nginx.virtualHosts."ipfs.uninsane.org" = {
# don't default to ssl upgrades, since this may be dnslink'd from a different domain.
# ideally we'd disable ssl entirely, but some places assume it?
addSSL = true;
enableACME = true;
default = true;
locations."/" = {
proxyPass = "http://127.0.0.1:8080";
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Ipfs-Gateway-Prefix "";
'';
};
};
# exists only to manage certs for dovecot
services.nginx.virtualHosts."imap.uninsane.org" = {
forceSSL = true;
enableACME = true;
};
# exists only to manage certs for Postfix
services.nginx.virtualHosts."mx.uninsane.org" = {
forceSSL = true;
enableACME = true;
};
services.nginx.virtualHosts."nixcache.uninsane.org" = {
addSSL = true;
enableACME = true;
# serverAliases = [ "nixcache" ];
locations."/".extraConfig = ''
proxy_pass http://localhost:${toString config.services.nix-serve.port};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
'';
};
security.acme.acceptTerms = true;
security.acme.defaults.email = "admin.acme@uninsane.org";
users.users.acme.uid = config.sane.allocations.acme-uid;
users.groups.acme.gid = config.sane.allocations.acme-gid;
sane.impermanence.service-dirs = [
# TODO: mode?
{ user = "acme"; group = "acme"; directory = "/var/lib/acme"; }
# TODO: this is overly broad; only need media and share directories to be persisted
{ user = "colin"; group = "users"; directory = "/var/lib/uninsane"; }
];
}

View File

@@ -23,13 +23,15 @@ in
sane.allocations.greeter-uid = mkId 999;
sane.allocations.greeter-gid = mkId 999;
# new servo users
sane.allocations.freshrss-uid = mkId 2401;
sane.allocations.freshrss-gid = mkId 2401;
sane.allocations.mediawiki-uid = mkId 2402;
sane.allocations.colin-uid = mkId 1000;
sane.allocations.guest-uid = mkId 1100;
# found on all machines
# found on all hosts
sane.allocations.sshd-uid = mkId 2001; # 997
sane.allocations.sshd-gid = mkId 2001; # 997
sane.allocations.polkituser-gid = mkId 2002; # 998
@@ -39,15 +41,15 @@ in
sane.allocations.systemd-oom-uid = mkId 2005;
sane.allocations.systemd-oom-gid = mkId 2005;
# found on graphical machines
# found on graphical hosts
sane.allocations.nm-iodine-uid = mkId 2101; # desko/moby/lappy
# found on desko machine
# found on desko host
sane.allocations.usbmux-uid = mkId 2204;
sane.allocations.usbmux-gid = mkId 2204;
# originally found on moby machine
# originally found on moby host
sane.allocations.avahi-uid = mkId 2304;
sane.allocations.avahi-gid = mkId 2304;
sane.allocations.colord-uid = mkId 2305;

View File

@@ -2,12 +2,15 @@
{
imports = [
./allocations.nix
./fs.nix
./gui
./hardware
./home-manager
./packages.nix
./image.nix
./impermanence.nix
./impermanence
./nixcache.nix
./services
./universal
./sops.nix
];
}

155
modules/fs.nix Normal file
View File

@@ -0,0 +1,155 @@
{ config, lib, pkgs, utils, ... }:
with lib;
let
cfg = config.sane.fs;
# sane.fs."<path>" top-level options
fsEntry = types.submodule ({ name, ...}: let
parent = parentDir name;
has-parent = hasParent name;
parent-cfg = if has-parent then cfg."${parent}" else {};
in {
options = {
dir = mkOption {
type = mkDirEntryType (parent-cfg.dir or {
user = "root";
group = "root";
mode = "0755";
});
};
depends = mkOption {
type = types.listOf types.str;
description = "list of systemd services needed to be run before this service";
default = [];
};
service = mkOption {
type = types.str;
description = "name of the systemd service which ensures this entry";
default = "ensure-${utils.escapeSystemdPath name}";
};
};
config = {
# we put this here instead of as a `default` to ensure that users who specify additional
# dependencies still get a dep on the parent (unless they assign with `mkForce`).
depends = if has-parent then [ "${parent-cfg.service}.service" ] else [];
};
});
# sane.fs."<path>".dir sub-options
mkDirEntryType = defaults: types.submodule {
options = {
user = mkOption {
type = types.str; # TODO: use uid?
};
group = mkOption {
type = types.str;
};
mode = mkOption {
type = types.str;
};
};
config = lib.mkDefault defaults;
};
# given a fsEntry definition, output the `config` attrs it generates.
mkFsConfig = path: opt: {
systemd.services."${opt.service}" = {
description = "prepare ${path}";
script = ensure-dir-script;
scriptArgs = "${path} ${opt.dir.user} ${opt.dir.group} ${opt.dir.mode}";
serviceConfig.Type = "oneshot";
after = opt.depends;
wants = opt.depends;
# prevent systemd making this unit implicitly dependent on sysinit.target.
# see: <https://www.freedesktop.org/software/systemd/man/systemd.special.html>
unitConfig.DefaultDependencies = "no";
};
};
# systemd/shell script used to create and set perms for a specific dir
ensure-dir-script = ''
path="$1"
user="$2"
group="$3"
mode="$4"
if ! test -d "$path"
then
# if the directory *doesn't* exist, try creating it
# if we fail to create it, ensure we raced with something else and that it's actually a directory
mkdir "$path" || test -d "$path"
fi
chmod "$mode" "$path"
chown "$user:$group" "$path"
'';
# split the string path into a list of string components.
# root directory "/" becomes the empty list [].
# implicitly performs normalization so that:
# splitPath "a//b/" => ["a" "b"]
# splitPath "/a/b" => ["a" "b"]
splitPath = str: builtins.filter (seg: (builtins.isString seg) && seg != "" ) (builtins.split "/" str);
# return a string path, with leading slash but no trailing slash
joinPathAbs = comps: "/" + (builtins.concatStringsSep "/" comps);
concatPaths = paths: joinPathAbs (builtins.concatLists (builtins.map (p: splitPath p) paths));
# normalize the given path
normPath = str: joinPathAbs (splitPath str);
# return the parent directory. doesn't care about leading/trailing slashes.
# the parent of "/" is "/".
parentDir = str: normPath (builtins.dirOf (normPath str));
hasParent = str: (parentDir str) != (normPath str);
# return all ancestors of this path.
# e.g. ancestorsOf "/foo/bar/baz" => [ "/" "/foo" "/foo/bar" ]
ancestorsOf = path: if hasParent path then
ancestorsOf (parentDir path) ++ [ (parentDir path) ]
else
[ ]
;
# attrsOf fsEntry type which for every entry ensures that all ancestor entries are created.
# we do this with a custom type to ensure that users can access `config.sane.fs."/parent/path"`
# when inferred.
fsTree = let
baseType = types.attrsOf fsEntry;
# merge is called once, with all collected `sane.fs` definitions passed and we coalesce those
# into a single value `x` as if the user had wrote simply `sane.fs = x` in a single location.
# so option defaulting and such happens *after* `merge` is called.
merge = loc: defs: let
# loc is the location of the option holding this type, e.g. ["sane" "fs"].
# each def is an { value = attrsOf fsEntry instance; file = "..."; }
pathsForDef = def: attrNames def.value;
origPaths = concatLists (builtins.map pathsForDef defs);
extraPaths = concatLists (builtins.map ancestorsOf origPaths);
extraDefs = builtins.map (p: {
file = ./.;
value = {
"${p}".dir = {};
};
}) extraPaths;
in
baseType.merge loc (defs ++ extraDefs);
in
lib.mkOptionType {
inherit merge;
name = "fsTree";
description = "attrset representation of a file-system tree";
# ensure that every path is in canonical form, else we might get duplicates and subtle errors
check = tree: builtins.all (p: p == normPath p) (builtins.attrNames tree);
};
in {
options = {
sane.fs = mkOption {
# type = types.attrsOf fsEntry;
type = fsTree;
default = {};
};
};
config = let
cfgs = builtins.attrValues (builtins.mapAttrs mkFsConfig cfg);
in {
# we can't lib.mkMerge at the top-level, so do it per-attribute
systemd = lib.mkMerge (catAttrs "systemd" cfgs);
};
}

View File

@@ -8,6 +8,7 @@ in
imports = [
./gnome.nix
./phosh.nix
./plasma.nix
./plasma-mobile.nix
./sway.nix
];
@@ -21,7 +22,7 @@ in
};
config = lib.mkIf cfg.enable {
sane.home-packages.enableGuiPkgs = lib.mkDefault true;
sane.packages.enableGuiPkgs = lib.mkDefault true;
# all GUIs use network manager?
users.users.nm-iodine.uid = config.sane.allocations.nm-iodine-uid;
};

View File

@@ -69,7 +69,7 @@ in
NIXOS_OZONE_WL = "1";
};
sane.home-manager.extraPackages = with pkgs; [
sane.packages.extraUserPkgs = with pkgs; [
phosh-mobile-settings
# TODO: see about removing this if the in-built gnome-settings bluetooth manager can work
@@ -89,19 +89,16 @@ in
services.xserver.displayManager.lightdm.extraSeatDefaults = ''
user-session = phosh
'';
services.xserver.displayManager.lightdm.greeters.gtk.enable = false; # gtk greeter overrides our own?
services.xserver.displayManager.lightdm.greeter = {
enable = true;
package = pkgs.lightdm-mobile-greeter.xgreeters;
name = "lightdm-mobile-greeter";
};
# services.xserver.displayManager.lightdm.enable = true;
# # services.xserver.displayManager.lightdm.greeters.enso.enable = true; # tried (with reboot); got a mouse then died. next time was black
# # services.xserver.displayManager.lightdm.greeters.gtk.enable = true; # tried (with reboot); unusable without OSK
# # services.xserver.displayManager.lightdm.greeters.mini.enable = true; # tried (with reboot); unusable without OSK
# # services.xserver.displayManager.lightdm.greeters.pantheon.enable = true; # tried (no reboot); unusable without OSK
# services.xserver.displayManager.lightdm.greeters.slick.enable = true; # tried; unusable without OSK (a11y -> OSK doesn't work)
# # services.xserver.displayManager.lightdm.greeters.tiny.enable = true; # tried; block screen
# services.xserver.displayManager.lightdm.greeters.gtk.enable = false; # gtk greeter overrides our own?
# services.xserver.displayManager.lightdm.greeter = {
# enable = true;
# package = pkgs.lightdm-mobile-greeter.xgreeters;
# name = "lightdm-mobile-greeter";
# };
# # services.xserver.displayManager.lightdm.enable = true;
services.xserver.displayManager.lightdm.enable = true;
services.xserver.displayManager.lightdm.greeters.mobile.enable = true;
systemd.services.phosh.wantedBy = lib.mkForce []; # disable auto-start
})

28
modules/gui/plasma.nix Normal file
View File

@@ -0,0 +1,28 @@
{ lib, config, ... }:
with lib;
let
cfg = config.sane.gui.plasma;
in
{
options = {
sane.gui.plasma.enable = mkOption {
default = false;
type = types.bool;
};
};
config = mkIf cfg.enable {
sane.gui.enable = true;
# start plasma on boot
services.xserver.enable = true;
services.xserver.desktopManager.plasma5.enable = true;
services.xserver.displayManager.sddm.enable = true;
# gnome does networking stuff with networkmanager
networking.useDHCP = false;
networking.networkmanager.enable = true;
networking.wireless.enable = lib.mkForce false;
};
}

11
modules/gui/snippets.txt Normal file
View File

@@ -0,0 +1,11 @@
https://search.nixos.org/options?channel=unstable&query=
https://search.nixos.org/packages?channel=unstable&query=
https://nixos.wiki/index.php?go=Go&search=
https://github.com/nixos/nixpkgs/pulls?q=
https://nix-community.github.io/home-manager/options.html
https://w.uninsane.org/viewer#search?books.name=wikipedia_en_all_maxi_2022-05&pattern=
https://jackett.uninsane.org/UI/Dashboard#search=
https://fed.uninsane.org
https://bt.uninsane.org
https://sci-hub.se
https://news.ycombinator.com

View File

@@ -81,8 +81,29 @@ in
sane.home-manager.windowManager.sway = {
enable = true;
wrapperFeatures.gtk = true;
config = rec {
terminal = "${pkgs.kitty}/bin/kitty";
config = let
fuzzel = "${pkgs.fuzzel}/bin/fuzzel";
sed = "${pkgs.gnused}/bin/sed";
wtype = "${pkgs.wtype}/bin/wtype";
kitty = "${pkgs.kitty}/bin/kitty";
lock-cmd = "${pkgs.swaylock}/bin/swaylock --indicator-idle-visible --indicator-radius 100 --indicator-thickness 30";
vol-up-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --change-volume +5";
vol-down-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --change-volume -5";
mute-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --toggle-mute";
brightness-up-cmd = "${pkgs.brightnessctl}/bin/brightnessctl set +2%";
brightness-down-cmd = "${pkgs.brightnessctl}/bin/brightnessctl set 2%-";
screenshot-cmd = "${pkgs.sway-contrib.grimshot}/bin/grimshot copy area";
# "bookmarking"/snippets inspired by Luke Smith:
# - <https://www.youtube.com/watch?v=d_11QaTlf1I>
snip-file = ./snippets.txt;
# TODO: querying sops here breaks encapsulation
list-snips = "cat ${snip-file} ${config.sops.secrets.snippets.path}";
strip-comments = "${sed} 's/ #.*$//'";
snip-cmd = "${wtype} $(${list-snips} | ${fuzzel} -d -i -w 60 | ${strip-comments})";
# TODO: next splatmoji release should allow `-s none` to disable skin tones
emoji-cmd = "${pkgs.splatmoji}/bin/splatmoji -s medium-light type";
in rec {
terminal = kitty;
window = {
border = 3; # pixel boundary between windows
hideEdgeBorders = "smart"; # don't show border if only window on workspace
@@ -103,7 +124,7 @@ in
modifier = "Mod1";
# list of launchers: https://www.reddit.com/r/swaywm/comments/v39hxa/your_favorite_launcher/
# menu = "${pkgs.dmenu}/bin/dmenu_path";
menu = "${pkgs.fuzzel}/bin/fuzzel";
menu = fuzzel;
# menu = "${pkgs.albert}/bin/albert";
left = "h";
down = "j";
@@ -114,7 +135,9 @@ in
"${modifier}+Return" = "exec ${terminal}";
"${modifier}+Shift+q" = "kill";
"${modifier}+d" = "exec ${menu}";
"${modifier}+l" = "exec ${pkgs.swaylock}/bin/swaylock --indicator-idle-visible --indicator-radius 100 --indicator-thickness 30";
"${modifier}+s" = "exec ${snip-cmd}";
"${modifier}+l" = "exec ${lock-cmd}";
"${modifier}+slash" = "exec ${emoji-cmd}";
# "${modifier}+${left}" = "focus left";
# "${modifier}+${down}" = "focus down";
@@ -141,7 +164,7 @@ in
"${modifier}+f" = "fullscreen toggle";
"${modifier}+a" = "focus parent";
"${modifier}+s" = "layout stacking";
# "${modifier}+s" = "layout stacking";
"${modifier}+w" = "layout tabbed";
"${modifier}+e" = "layout toggle split";
@@ -185,19 +208,20 @@ in
"exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'";
"${modifier}+r" = "mode resize";
} // {
# media keys
XF86MonBrightnessDown = ''exec "${pkgs.brightnessctl}/bin/brightnessctl set 2%-"'';
XF86MonBrightnessUp = ''exec "${pkgs.brightnessctl}/bin/brightnessctl set +2%"'';
XF86MonBrightnessDown = "exec ${brightness-down-cmd}";
XF86MonBrightnessUp = "exec ${brightness-up-cmd}";
XF86AudioRaiseVolume = "exec '${pkgs.pulsemixer}/bin/pulsemixer --change-volume +5'";
XF86AudioLowerVolume = "exec '${pkgs.pulsemixer}/bin/pulsemixer --change-volume -5'";
XF86AudioMute = "exec '${pkgs.pulsemixer}/bin/pulsemixer --toggle-mute'";
# TODO: hook into a visual prompt to display volume?
XF86AudioRaiseVolume = "exec ${vol-up-cmd}";
XF86AudioLowerVolume = "exec ${vol-down-cmd}";
XF86AudioMute = "exec ${mute-cmd}";
"${modifier}+Page_Up" = "exec '${pkgs.pulsemixer}/bin/pulsemixer --change-volume +5'";
"${modifier}+Page_Down" = "exec '${pkgs.pulsemixer}/bin/pulsemixer --change-volume -5'";
"${modifier}+Page_Up" = "exec ${vol-up-cmd}";
"${modifier}+Page_Down" = "exec ${vol-down-cmd}";
"${modifier}+Print" = "exec '${pkgs.sway-contrib.grimshot}/bin/grimshot copy area'";
"${modifier}+Print" = "exec ${screenshot-cmd}";
};
# mostly defaults:
@@ -597,7 +621,7 @@ in
# }
# '';
};
sane.home-manager.extraPackages = with pkgs; [
sane.packages.extraUserPkgs = with pkgs; [
swaylock
swayidle # (unused)
wl-clipboard

View File

@@ -1,9 +1,11 @@
# Terminal UI mail client
{ config, ... }:
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
sops.secrets."aerc_accounts" = {
owner = config.users.users.colin.name;
sopsFile = ../../../secrets/universal/aerc_accounts.conf;
sopsFile = ../../secrets/universal/aerc_accounts.conf;
format = "binary";
};
home-manager.users.colin = let sysconfig = config; in { config, ... }: {

View File

@@ -9,38 +9,34 @@
with lib;
let
cfg = config.sane.home-manager;
# extract package from `extraPackages`
# extract package from `sane.packages.enabledUserPkgs`
pkg-list = pkgspec: builtins.map (e: e.pkg or e) pkgspec;
# extract `dir` from `extraPackages`
dir-list = pkgspec: builtins.concatLists (builtins.map (e: if e ? "dir" then [ e.dir ] else []) pkgspec);
private-list = pkgspec: builtins.concatLists (builtins.map (e: if e ? "private" then [ e.private ] else []) pkgspec);
# extract `dir` from `sane.packages.enabledUserPkgs`
dir-list = pkgspec: builtins.concatLists (builtins.map (e: e.dir or []) pkgspec);
private-list = pkgspec: builtins.concatLists (builtins.map (e: e.private or []) pkgspec);
feeds = import ./feeds.nix { inherit lib; };
in
{
imports = [
./aerc.nix
./discord.nix
./firefox.nix
./git.nix
./kitty.nix
./librewolf.nix
./mpv.nix
./nb.nix
./neovim.nix
./splatmoji.nix
./ssh.nix
./sublime-music.nix
./vlc.nix
./zsh.nix
./zsh
];
options = {
# packages to deploy to the user's home
sane.home-manager.extraPackages = mkOption {
default = [ ];
# each entry can be either a package, or attrs:
# { pkg = package; dir = optional string;
type = types.listOf (types.either types.package types.attrs);
sane.home-manager.enable = mkOption {
default = false;
type = types.bool;
};
# attributes to copy directly to home-manager's `wayland.windowManager` option
sane.home-manager.windowManager = mkOption {
default = {};
@@ -54,7 +50,7 @@ in
};
};
config = {
config = lib.mkIf cfg.enable {
sane.impermanence.home-dirs = [
"archive"
"dev"
@@ -65,7 +61,7 @@ in
"Music"
"Pictures"
"Videos"
] ++ (dir-list cfg.extraPackages);
] ++ (dir-list config.sane.packages.enabledUserPkgs);
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
@@ -79,7 +75,7 @@ in
manual.html.enable = false; # TODO: set to true later (build failure)
manual.manpages.enable = false; # TODO: enable after https://github.com/nix-community/home-manager/issues/3344
home.packages = pkg-list cfg.extraPackages;
home.packages = pkg-list sysconfig.sane.packages.enabledUserPkgs;
wayland.windowManager = cfg.windowManager;
home.stateVersion = "21.11";
@@ -90,7 +86,7 @@ in
initKeyring = {
after = ["writeBoundary"];
before = [];
data = "${../../../scripts/init-keyring}";
data = "${../../scripts/init-keyring}";
};
};
@@ -101,18 +97,18 @@ in
name = path;
value = { source = config.lib.file.mkOutOfStoreSymlink "/home/colin/private/${path}"; };
})
(private-list cfg.extraPackages)
(private-list sysconfig.sane.packages.enabledUserPkgs)
);
in {
# convenience
"knowledge".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/dev/knowledge";
"knowledge".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/private/knowledge";
"nixos".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/dev/nixos";
"Videos/servo".source = config.lib.file.mkOutOfStoreSymlink "/mnt/servo-media/Videos";
"Videos/servo-incomplete".source = config.lib.file.mkOutOfStoreSymlink "/mnt/servo-media/incomplete";
"Music/servo".source = config.lib.file.mkOutOfStoreSymlink "/mnt/servo-media/Music";
# used by password managers, e.g. unix `pass`
".password-store".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/dev/knowledge/secrets/accounts";
".password-store".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/knowledge/secrets/accounts";
} // privates;
# XDG defines things like ~/Desktop, ~/Downloads, etc.
@@ -134,7 +130,7 @@ in
# - `xdg-mime query filetype path/to/thing.ext`
xdg.mimeApps.enable = true;
xdg.mimeApps.defaultApplications = let
www = "librewolf.desktop";
www = sysconfig.sane.web-browser.desktop;
pdf = "org.gnome.Evince.desktop";
md = "obsidian.desktop";
thumb = "org.gnome.gThumb.desktop";
@@ -165,6 +161,18 @@ in
"audio/x-vorbis+ogg" = [ audio ];
};
# libreoffice: disable first-run stuff
xdg.configFile."libreoffice/4/user/registrymodifications.xcu".text = ''
<?xml version="1.0" encoding="UTF-8"?>
<oor:items xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<item oor:path="/org.openoffice.Office.Common/Misc"><prop oor:name="FirstRun" oor:op="fuse"><value>false</value></prop></item>
<item oor:path="/org.openoffice.Office.Common/Misc"><prop oor:name="ShowTipOfTheDay" oor:op="fuse"><value>false</value></prop></item>
</oor:items>
'';
# <item oor:path="/org.openoffice.Setup/Product"><prop oor:name="LastTimeDonateShown" oor:op="fuse"><value>1667693880</value></prop></item>
# <item oor:path="/org.openoffice.Setup/Product"><prop oor:name="LastTimeGetInvolvedShown" oor:op="fuse"><value>1667693880</value></prop></item>
xdg.configFile."gpodderFeeds.opml".text = with feeds;
feedsToOpml feeds.podcasts;

View File

@@ -61,6 +61,12 @@ in rec {
(mkPod "https://feeds.feedburner.com/dancarlin/history?format=xml" // rat // infrequent)
## 60 minutes (NB: this features more than *just* audio?)
(mkPod "https://www.cbsnews.com/latest/rss/60-minutes" // pol // infrequent)
## The Verge - Decoder
(mkPod "https://feeds.megaphone.fm/recodedecode" // tech // weekly)
## Matrix (chat) Live
(mkPod "https://feed.podbean.com/matrixlive/feed.xml" // tech // weekly)
## Michael Malice - Your Welcome
(mkPod "https://www.podcastone.com/podcast?categoryID2=2232" // pol // weekly)
];
texts = [
@@ -94,6 +100,8 @@ in rec {
(mkText "https://bitbashing.io/feed.xml" // tech // infrequent)
(mkText "https://idiomdrottning.org/feed.xml" // uncat // daily)
(mkText "https://anish.lakhwara.com/home.html" // tech // weekly)
(mkText "https://www.jefftk.com/news.rss" // tech // daily)
(mkText "https://pomeroyb.com/feed.xml" // tech // infrequent)
# (TECH; POL) COMMENTATORS
(mkSubstack "edwardsnowden" // pol // infrequent)
@@ -111,6 +119,7 @@ in rec {
(mkText "https://blog.dshr.org/rss.xml" // pol // weekly)
## Matt Levine
(mkText "https://www.bloomberg.com/opinion/authors/ARbTQlRLRjE/matthew-s-levine.rss" // pol // weekly)
(mkText "https://stpeter.im/atom.xml" // pol // weekly)
# RATIONALITY/PHILOSOPHY/ETC
(mkSubstack "samkriss" // humor // infrequent)
@@ -130,8 +139,11 @@ in rec {
## Sean Carroll
(mkText "https://www.preposterousuniverse.com/rss" // rat // infrequent)
## mostly dating topics. not advice, or humor, but looking through a social lens
(mkText "https://putanumonit.com/feed" // rat // infrequent)
# CODE
(mkText "https://github.com/Kaiteki-Fedi/Kaiteki/commits/master.atom" // tech // infrequent)
# (mkText "https://github.com/Kaiteki-Fedi/Kaiteki/commits/master.atom" // tech // infrequent)
];
images = [

View File

@@ -0,0 +1,145 @@
# common settings to toggle (at runtime, in about:config):
# > security.ssl.require_safe_negotiation
# librewolf is a forked firefox which patches firefox to allow more things
# (like default search engines) to be configurable at runtime.
# many of the settings below won't have effect without those patches.
# see: https://gitlab.com/librewolf-community/settings/-/blob/master/distribution/policies.json
{ config, lib, pkgs, ...}:
with lib;
let
cfg = config.sane.web-browser;
# allow easy switching between firefox and librewolf with `defaultSettings`, below
librewolfSettings = {
browser = pkgs.librewolf-unwrapped;
# browser = pkgs.librewolf-unwrapped.overrideAttrs (drv: {
# # this allows side-loading unsigned addons
# MOZ_REQUIRE_SIGNING = false;
# });
libName = "librewolf";
dotDir = ".librewolf";
desktop = "librewolf.desktop";
};
firefoxSettings = {
browser = pkgs.firefox-esr-unwrapped;
libName = "firefox";
dotDir = ".mozilla/firefox";
desktop = "firefox.desktop";
};
defaultSettings = firefoxSettings;
# defaultSettings = librewolfSettings;
package = pkgs.wrapFirefox cfg.browser {
# inherit the default librewolf.cfg
# it can be further customized via ~/.librewolf/librewolf.overrides.cfg
inherit (pkgs.librewolf-unwrapped) extraPrefsFiles;
inherit (cfg) libName;
extraNativeMessagingHosts = [ pkgs.browserpass ];
# extraNativeMessagingHosts = [ pkgs.gopass-native-messaging-host ];
nixExtensions = let
addon = name: extid: hash: pkgs.fetchFirefoxAddon {
inherit name hash;
url = "https://addons.mozilla.org/firefox/downloads/latest/${name}/latest.xpi";
# extid can be found by unar'ing the above xpi, and copying browser_specific_settings.gecko.id field
fixedExtid = extid;
};
localAddon = pkg: pkgs.fetchFirefoxAddon {
inherit (pkg) name;
src = "${pkg}/share/mozilla/extensions/\\{ec8030f7-c20a-464f-9b0e-13a3a9e97384\\}/${pkg.extid}.xpi";
fixedExtid = pkg.extid;
};
in [
# get names from:
# - ~/ref/nix-community/nur-combined/repos/rycee/pkgs/firefox-addons/generated-firefox-addons.nix
# `wget ...xpi`; `unar ...xpi`; `cat */manifest.json | jq '.browser_specific_settings.gecko.id'`
(addon "ublock-origin" "uBlock0@raymondhill.net" "sha256-+xc4lcdsOwXxMsr4enFsdePbIb6GHq0bFLpqvH5xXos=")
(addon "sponsorblock" "sponsorBlocker@ajay.app" "sha256-30F8oDIgshXVY7YKgnfoc1tUTHfgeFbzXISJuVJs0AM=")
(addon "bypass-paywalls-clean" "{d133e097-46d9-4ecc-9903-fa6a722a6e0e}" "sha256-7ZDkG8O1rEYdh/La0PLi9tp92JxYeQvaOFt/BmnDv3U=")
(addon "sidebery" "{3c078156-979c-498b-8990-85f7987dd929}" "sha256-YONfK/rIjlsrTgRHIt3km07Q7KnpIW89Z9r92ZSCc6w=")
(addon "ether-metamask" "webextension@metamask.io" "sha256-G+MwJDOcsaxYSUXjahHJmkWnjLeQ0Wven8DU/lGeMzA=")
(addon "ublacklist" "@ublacklist" "sha256-vHe/7EYOzcKeAbTElmt0Rb4E2rX0f3JgXThJaUmaz+M=")
(addon "i2p-in-private-browsing" "i2ppb@eyedeekay.github.io" "sha256-dJcJ3jxeAeAkRvhODeIVrCflvX+S4E0wT/PyYzQBQWs=")
# (addon "browserpass-ce" "browserpass@maximbaz.com" "sha256-sXgUBbRvMnRpeIW1MTkmTcoqtW/8RDXAkxAq1evFkpc=")
(localAddon pkgs.browserpass-extension)
];
extraPolicies = {
NoDefaultBookmarks = true;
SearchEngines = {
Default = "DuckDuckGo";
};
AppUpdateURL = "https://localhost";
DisableAppUpdate = true;
OverrideFirstRunPage = "";
OverridePostUpdatePage = "";
DisableSystemAddonUpdate = true;
DisableFirefoxStudies = true;
DisableTelemetry = true;
DisableFeedbackCommands = true;
DisablePocket = true;
DisableSetDesktopBackground = false;
# remove many default search providers
# XXX this seems to prevent the `nixExtensions` from taking effect
# Extensions.Uninstall = [
# "google@search.mozilla.org"
# "bing@search.mozilla.org"
# "amazondotcom@search.mozilla.org"
# "ebay@search.mozilla.org"
# "twitter@search.mozilla.org"
# ];
# XXX doesn't seem to have any effect...
# docs: https://github.com/mozilla/policy-templates#homepage
# Homepage = {
# HomepageURL = "https://uninsane.org/";
# StartPage = "homepage";
# };
# NewTabPage = true;
};
};
in
{
options = {
sane.web-browser = mkOption {
default = defaultSettings;
type = types.attrs;
};
};
config = lib.mkIf config.sane.home-manager.enable {
# XXX: although home-manager calls this option `firefox`, we can use other browsers and it still mostly works.
home-manager.users.colin = lib.mkIf (config.sane.gui.enable) {
programs.firefox = {
enable = true;
inherit package;
};
# uBlock filter list configuration.
# specifically, enable the GDPR cookie prompt blocker.
# data.toOverwrite.filterLists is additive (i.e. it supplements the default filters)
# this configuration method is documented here:
# - <https://github.com/gorhill/uBlock/issues/2986#issuecomment-364035002>
# the specific attribute path is found via scraping ublock code here:
# - <https://github.com/gorhill/uBlock/blob/master/src/js/storage.js>
# - <https://github.com/gorhill/uBlock/blob/master/assets/assets.json>
home.file."${cfg.dotDir}/managed-storage/uBlock0@raymondhill.net.json".text = ''
{
"name": "uBlock0@raymondhill.net",
"description": "ignored",
"type": "storage",
"data": {
"toOverwrite": "{\"filterLists\": [\"fanboy-cookiemonster\"]}"
}
}
'';
home.file."${cfg.dotDir}/${cfg.libName}.overrides.cfg".text = ''
// if we can't query the revocation status of a SSL cert because the issuer is offline,
// treat it as unrevoked.
// see: <https://librewolf.net/docs/faq/#im-getting-sec_error_ocsp_server_error-what-can-i-do>
defaultPref("security.OCSP.require", false);
'';
};
};
}

View File

@@ -1,4 +1,6 @@
{ pkgs, ... }:
{ config, lib, pkgs, ... }:
lib.mkIf config.sane.home-manager.enable
{
home-manager.users.colin.programs.git = {
enable = true;

View File

@@ -1,4 +1,6 @@
{ ... }:
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
home-manager.users.colin.programs.kitty = {
enable = true;

View File

@@ -1,4 +1,6 @@
{ ... }:
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
home-manager.users.colin.programs.mpv = {
enable = true;

View File

@@ -8,13 +8,16 @@
# it offers a primitive web-server
# and it offers some CLI query tools
{ lib, pkgs, ... }: lib.mkIf false # XXX disabled!
{ config, lib, pkgs, ... }:
# lib.mkIf config.sane.home-manager.enable
lib.mkIf false # XXX disabled!
{
sane.home-manager.extraPackages = [ pkgs.nb ];
sane.packages.extraUserPkgs = [ pkgs.nb ];
home-manager.users.colin = { config, ... }: {
# nb markdown/personal knowledge manager
home.file.".nb/knowledge".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/dev/knowledge";
home.file.".nb/knowledge".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/knowledge";
home.file.".nb/.current".text = "knowledge";
home.file.".nbrc".text = ''
# manage with `nb settings`

View File

@@ -1,4 +1,6 @@
{ pkgs, ... }:
{ config, lib, pkgs, ... }:
lib.mkIf config.sane.home-manager.enable
{
sane.impermanence.home-dirs = [ ".cache/vim-swap" ];
@@ -31,21 +33,12 @@
" autocmd Syntax tex set conceallevel=2
'';
})
# nabla renders inline math in any document, but it's buggy.
# https://github.com/jbyuki/nabla.nvim
# ({
# plugin = pkgs.nabla;
# type = "lua";
# config = ''
# require'nabla'.enable_virt()
# '';
# })
# treesitter syntax highlighting: https://nixos.wiki/wiki/Tree_sitters
# docs: https://github.com/nvim-treesitter/nvim-treesitter
# config taken from: https://github.com/i077/system/blob/master/modules/home/neovim/default.nix
# this is required for tree-sitter to even highlight
({
plugin = (nvim-treesitter.withPlugins (_: pkgs.tree-sitter.allGrammars));
plugin = nvim-treesitter.withAllGrammars;
type = "lua";
config = ''
require'nvim-treesitter.configs'.setup {

View File

@@ -0,0 +1,20 @@
# borrows from:
# - default config: <https://github.com/cspeterson/splatmoji/blob/master/splatmoji.config>
# - wayland: <https://github.com/cspeterson/splatmoji/issues/32#issuecomment-830862566>
{ pkgs, ... }:
{
home-manager.users.colin = {
xdg.configFile."splatmoji/splatmoji.config".text = ''
history_file=/home/colin/.local/state/splatmoji/history
history_length=5
# TODO: wayland equiv
paste_command=xdotool key ctrl+v
# rofi_command=${pkgs.wofi}/bin/wofi --dmenu --insensitive --cache-file /dev/null
rofi_command=${pkgs.fuzzel}/bin/fuzzel -d -i -w 60
xdotool_command=${pkgs.wtype}/bin/wtype
# TODO: wayland equiv
xsel_command=xsel -b -i
'';
};
}

View File

@@ -1,4 +1,6 @@
{ config, pkgs, ... }:
{ config, lib, pkgs, ... }:
lib.mkIf config.sane.home-manager.enable
{
home-manager.users.colin = let
host = config.networking.hostName;

View File

@@ -1,9 +1,11 @@
{ config, ... }:
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
# TODO: this should only be shipped on gui platforms
sops.secrets."sublime_music_config" = {
owner = config.users.users.colin.name;
sopsFile = ../../../secrets/universal/sublime_music_config.json.bin;
sopsFile = ../../secrets/universal/sublime_music_config.json.bin;
format = "binary";
};
home-manager.users.colin = let sysconfig = config; in { config, ... }: {

View File

@@ -1,4 +1,6 @@
{ lib, ... }:
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
home-manager.users.colin.xdg.configFile."vlc/vlcrc".text =
let

View File

@@ -0,0 +1,108 @@
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
sane.impermanence.home-dirs = [
# we don't need to full zsh dir -- just the history file --
# but zsh will sometimes backup the history file and we get fewer errors if we do proper mounts instead of symlinks.
# TODO: should be private?
".local/share/zsh"
# cache gitstatus otherwise p10k fetched it from the net EVERY BOOT
".cache/gitstatus"
];
home-manager.users.colin.programs.zsh = {
enable = true;
enableSyntaxHighlighting = true;
enableVteIntegration = true;
history.ignorePatterns = [ "rm *" ];
dotDir = ".config/zsh";
history.path = "/home/colin/.local/share/zsh/history";
# defaultKeymap = "vicmd"; # vim normal mode (cmd mode)
# powerlevel10k prompt config
# p10k.zsh is the auto-generated config, and i overwrite those defaults here, below.
initExtraBeforeCompInit = (builtins.readFile ./p10k.zsh) + ''
# powerlevel10k launches a gitstatusd daemon to accelerate git prompt queries.
# this keeps open file handles for any git repo i touch for 60 minutes (by default).
# that prevents unmounting whatever device the git repo is on -- particularly problematic for ~/private.
# i can disable gitstatusd and get slower fallback git queries:
# - either universally
# - or selectively by path
# see: <https://github.com/romkatv/powerlevel10k/issues/246>
typeset -g POWERLEVEL9K_VCS_DISABLED_DIR_PATTERN='(/home/colin/private/*|/home/colin/knowledge/*)'
# typeset -g POWERLEVEL9K_DISABLE_GITSTATUS=true
# show user@host also when logged into the current machine.
# default behavior is to show it only over ssh.
typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_CONTENT_EXPANSION='$P9K_CONTENT'
'';
initExtra = ''
# zmv is a way to do rich moves/renames, with pattern matching/substitution.
# see for an example: <https://filipe.kiss.ink/zmv-zsh-rename/>
autoload -Uz zmv
# disable `rm *` confirmations
setopt rmstarsilent
function nd() {
mkdir -p "$1";
pushd "$1";
}
'';
# prezto = oh-my-zsh fork; controls prompt, auto-completion, etc.
# see: https://github.com/sorin-ionescu/prezto
prezto = {
enable = true;
pmodules = [
# configures jobs to persist after shell exit; other basic niceties
"environment"
# auto-titles terminal (e.g. based on cwd)
"terminal"
# configures shortcuts like Ctrl+U=undo, Ctrl+L=clear
"editor"
# adds `history-stat` alias, setopts for good history defaults
"history"
# sets AUTO_CD, adds `d` alias to list directory stack, and `1`-`9` to cd that far back the stack
"directory"
# helpers for term colors and styling. used by prompts? might be unnecessary
"spectrum"
# configures aliases like `ll`, `la`, disables globbing for things like rsync
# adds aliases like `get` to fetch a file. also adds `http-serve` alias??
"utility"
# tab completion. requires `utility` module prior to loading
# TODO: enable AUTO_PARAM_SLASH
"completion"
"prompt"
# TODO: enable syntax-highlighting ?
];
prompt.theme = "powerlevel10k";
utility.safeOps = false; # disable `mv` confirmation (and supposedly `rm`, too)
# editor.keymap = "vi";
};
dirHashes = {
# convenient `cd`-isms
"3rd" = "/home/colin/dev/3rd";
"dev" = "/home/colin/dev";
"knowledge" = "/home/colin/knowledge";
"nixos" = "/home/colin/nixos";
"nixpkgs" = "/home/colin/dev/3rd/nixpkgs";
"ref" = "/home/colin/ref";
"secrets" = "/home/colin/knowledge/secrets";
"tmp" = "/home/colin/tmp";
"uninsane" = "/home/colin/dev/uninsane";
"Videos" = "/home/colin/Videos";
};
};
home-manager.users.colin.home.shellAliases = {
":q" = "exit";
# common typos
"cd.." = "cd ..";
"cd../" = "cd ../";
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,11 @@ let
in
{
options = {
sane.image.enable = mkOption {
default = true;
type = types.bool;
description = "whether to enable image targets. this doesn't mean they'll be built unless you specifically reference the target.";
};
# packages whose contents should be copied directly into the /boot partition.
# e.g. EFI loaders, u-boot bootloader, etc.
sane.image.extraBootFiles = mkOption {

View File

@@ -1,98 +0,0 @@
# borrows from:
# https://xeiaso.net/blog/paranoid-nixos-2021-07-18
# https://elis.nu/blog/2020/05/nixos-tmpfs-as-root/
# https://github.com/nix-community/impermanence
{ lib, config, impermanence, ... }:
with lib;
let
cfg = config.sane.impermanence;
# taken from sops-nix code: checks if any secrets are needed to create /etc/shadow
secretsForUsers = (lib.filterAttrs (_: v: v.neededForUsers) config.sops.secrets) != {};
in
{
options = {
sane.impermanence.enable = mkOption {
default = false;
type = types.bool;
};
sane.impermanence.home-dirs = mkOption {
default = [];
type = types.listOf (types.either types.str (types.attrsOf types.str));
};
sane.impermanence.service-dirs = mkOption {
default = [];
type = types.listOf (types.either types.str (types.attrsOf types.str));
};
};
config = let
map-dir = defaults: dir: if isString dir then
map-dir defaults { directory = "${defaults.directory}${dir}"; }
else
defaults // dir
;
map-dirs = defaults: dirs: builtins.map (map-dir defaults) dirs;
map-home-dirs = map-dirs { user = "colin"; group = "users"; mode = "0755"; directory = "/home/colin/"; };
map-sys-dirs = map-dirs { user = "root"; group = "root"; mode = "0755"; directory = ""; };
in mkIf cfg.enable {
sane.image.extraDirectories = [ "/nix/persist/var/log" ];
environment.persistence."/nix/persist" = {
directories = (map-home-dirs cfg.home-dirs) ++ (map-sys-dirs [
# TODO: this `0700` here clobbers the perms for /persist/etc, breaking boot on freshly-deployed devices
# { mode = "0700"; directory = "/etc/NetworkManager/system-connections"; }
# "/etc/nixos"
# "/etc/ssh" # persist only the specific files we want, instead
"/var/log"
"/var/backup" # for e.g. postgres dumps
# "/var/lib/AccountsService" # not sure what this is, but it's empty
"/var/lib/alsa" # preserve output levels, default devices
# "/var/lib/blueman" # files aren't human readable
"/var/lib/bluetooth" # preserve bluetooth handshakes
"/var/lib/colord" # preserve color calibrations (?)
# "/var/lib/dhclient" # empty on lappy; dunno about desko
# "/var/lib/fwupd" # not sure why this would need persistent state
# "/var/lib/geoclue" # empty on lappy
# "/var/lib/lockdown" # empty on desko; might store secrets after iOS handshake?
# "/var/lib/logrotate.status" # seems redundant with what's in /var/log?
"/var/lib/machines" # maybe not needed, but would be painful to add a VM and forget.
# "/var/lib/misc" # empty on lappy
# "/var/lib/NetworkManager" # looks to be mostly impermanent state?
# "/var/lib/NetworkManager-fortisslvpn" # empty on lappy
# "/var/lib/nixos" # has some uid/gid maps, but we enforce these to be deterministic.
# "/var/lib/PackageKit" # wtf is this?
# "/var/lib/power-profiles-daemon" # redundant with nixos declarations
# "/var/lib/private" # empty on lappy
# "/var/lib/systemd" # nothing obviously necessary
# "/var/lib/udisks2" # empty on lappy
# "/var/lib/upower" # historic charge data. unnecessary, but maybe used somewhere?
#
# servo additions:
] ++ cfg.service-dirs);
files = [ "/etc/machine-id" ];
};
# secret decoding depends on /etc/ssh keys, which are persisted
system.activationScripts.setupSecrets.deps = [ "persist-files" ];
# `setupSecretsForUsers` should depend on `persist-files`,
# but `persist-files` itself depends on `users`, to this would be circular.
# we work around that by manually mounting the ssh host key.
# strictly speaking, this makes the `setupSecrets -> persist-files` dep extraneous,
# but it's a decent safety net in case something goes wrong.
# system.activationScripts.setupSecretsForUsers.deps = [ "persist-files" ];
system.activationScripts.setupSecretsForUsers= lib.mkIf secretsForUsers {
deps = [ "persist-ssh-host-keys" ];
};
system.activationScripts.persist-ssh-host-keys = lib.mkIf secretsForUsers (
let
key_dir = "/etc/ssh/host_keys";
in ''
mkdir -p ${key_dir}
mount -o bind /nix/persist${key_dir} ${key_dir}
''
);
};
}

View File

@@ -0,0 +1,232 @@
# borrows from:
# https://xeiaso.net/blog/paranoid-nixos-2021-07-18
# https://elis.nu/blog/2020/05/nixos-tmpfs-as-root/
# https://github.com/nix-community/impermanence
{ config, lib, pkgs, utils, ... }:
with lib;
let
cfg = config.sane.impermanence;
getStore = { encryptedClearOnBoot, ... }: (
if encryptedClearOnBoot then {
device = "/mnt/impermanence/crypt/clearedonboot";
underlying = {
path = "/nix/persist/crypt/clearedonboot";
# TODO: consider moving this to /tmp, but that requires tmp be mounted first?
type = "gocryptfs";
key = "/mnt/impermanence/crypt/clearedonboot.key";
};
} else {
device = "/nix/persist";
# device = "/mnt/impermenanence/persist/plain";
# underlying = {
# path = "/nix/persist";
# type = "bind";
# };
}
);
home-dir-defaults = {
user = "colin";
group = "users";
mode = "0755";
relativeTo = "/home/colin";
};
sys-dir-defaults = {
user = "root";
group = "root";
mode = "0755";
relativeTo = "";
};
# turn a path into a name suitable for systemd
cleanName = utils.escapeSystemdPath;
# split the string path into a list of string components.
# root directory "/" becomes the empty list [].
# implicitly performs normalization so that:
# splitPath "a//b/" => ["a" "b"]
# splitPath "/a/b" => ["a" "b"]
splitPath = str: builtins.filter (seg: (builtins.isString seg) && seg != "" ) (builtins.split "/" str);
# return a string path, with leading slash but no trailing slash
joinPathAbs = comps: "/" + (builtins.concatStringsSep "/" comps);
concatPaths = paths: joinPathAbs (builtins.concatLists (builtins.map (p: splitPath p) paths));
dirOptions = defaults: types.submodule {
options = {
encryptedClearOnBoot = mkOption {
default = false;
type = types.bool;
};
directory = mkOption {
type = types.str;
};
user = mkOption {
type = types.str;
default = defaults.user;
};
group = mkOption {
type = types.str;
default = defaults.group;
};
mode = mkOption {
type = types.str;
default = defaults.mode;
};
};
};
mkDirsOption = defaults: mkOption {
default = [];
type = types.listOf (types.coercedTo types.str (d: { directory = d; }) (dirOptions defaults));
# apply = map (d: if isString d then { directory = d; } else d);
};
# expand user options with more context
ingestDirOption = defaults: opt: {
inherit (opt) user group mode;
directory = concatPaths [ defaults.relativeTo opt.directory ];
## helpful context
store = builtins.addErrorContext ''while ingestDirOption on ${opt.directory} with attrs ${builtins.concatStringsSep " " (attrNames opt)}''
(getStore opt);
};
ingestDirOptions = defaults: opts: builtins.map (ingestDirOption defaults) opts;
ingested-home-dirs = ingestDirOptions home-dir-defaults cfg.home-dirs;
ingested-sys-dirs = ingestDirOptions sys-dir-defaults cfg.dirs;
ingested-dirs = ingested-home-dirs ++ ingested-sys-dirs;
in
{
options = {
sane.impermanence.enable = mkOption {
default = false;
type = types.bool;
};
sane.impermanence.root-on-tmpfs = mkOption {
default = false;
type = types.bool;
description = "define / to be a tmpfs. make sure to mount some other device to /nix";
};
sane.impermanence.home-dirs = mkDirsOption home-dir-defaults;
sane.impermanence.dirs = mkDirsOption sys-dir-defaults;
};
imports = [
./root-on-tmpfs.nix
];
config = mkIf cfg.enable (lib.mkMerge [
{
# TODO: move to sane.fs, to auto-ensure all user dirs?
sane.fs."/home/colin".dir = {
user = "colin";
group = config.users.users.colin.group;
mode = config.users.users.colin.homeMode;
};
# without this, we get `fusermount: fuse device not found, try 'modprobe fuse' first`.
# - that only happens after a activation-via-boot -- not activation-after-rebuild-switch.
# it seems likely that systemd loads `fuse` by default. see:
# - </etc/systemd/system/sysinit.target.wants/sys-fs-fuse-connections.mount>
# - triggers: /etc/systemd/system/modprobe@.service
# - calls `modprobe`
# note: even `boot.kernelModules = ...` isn't enough: that option creates /etc/modules-load.d/, which is ingested only by systemd.
# note: `boot.initrd.availableKernelModules` ALSO isn't enough: idk why.
# TODO: might not be necessary now we're using fileSystems and systemd
boot.initrd.kernelModules = [ "fuse" ];
# TODO: convert this to a systemd unit file?
system.activationScripts.prepareEncryptedClearedOnBoot =
let
script = pkgs.writeShellApplication {
name = "prepareEncryptedClearedOnBoot";
runtimeInputs = with pkgs; [ gocryptfs ];
text = ''
backing="$1"
passfile="$2"
if ! test -e "$passfile"
then
tmpdir=$(dirname "$passfile")
mkdir -p "$backing" "$tmpdir"
# if the key doesn't exist, it's probably not mounted => delete the backing dir
rm -rf "''${backing:?}"/*
# generate key. we can "safely" keep it around for the lifetime of this boot
dd if=/dev/random bs=128 count=1 | base64 --wrap=0 > "$passfile"
# initialize the crypt store
gocryptfs -quiet -passfile "$passfile" -init "$backing"
fi
'';
};
store = getStore { encryptedClearOnBoot = true; };
in {
text = ''${script}/bin/prepareEncryptedClearedOnBoot ${store.underlying.path} ${store.underlying.key}'';
};
fileSystems = let
store = getStore { encryptedClearOnBoot = true; };
in {
"${store.device}" = {
device = store.underlying.path;
fsType = "fuse.gocryptfs";
options = [
"nodev"
"nosuid"
"allow_other"
"passfile=${store.underlying.key}"
"defaults"
];
noCheck = true;
};
};
environment.systemPackages = [ pkgs.gocryptfs ]; # fuse needs to find gocryptfs
}
(
let cfgFor = opt:
let
# systemd creates <path>.mount services for every fileSystems entry.
# <path> gets escaped as part of that: this code tries to guess that escaped name here.
# backing-mount = cleanName opt.store.device;
mount-service = cleanName opt.directory;
backing-path = concatPaths [ opt.store.device opt.directory ];
dir-service = config.sane.fs."${opt.directory}".service;
backing-service = config.sane.fs."${backing-path}".service;
in {
# create destination and backing directory, with correct perms
sane.fs."${opt.directory}".dir = {
inherit (opt) user group mode;
};
sane.fs."${backing-path}".dir = {
inherit (opt) user group mode;
};
# define the mountpoint.
fileSystems."${opt.directory}" = {
device = backing-path;
options = [
"bind"
# "x-systemd.requires=${backing-mount}.mount" # this should be implicit
"x-systemd.after=${backing-service}"
"x-systemd.after=${dir-service}"
# `wants` doesn't seem to make it to the service file here :-(
# "x-systemd.wants=${backing-service}"
# "x-systemd.wants=${dir-service}"
];
# fsType = "bind";
noCheck = true;
};
systemd.services."${backing-service}".wantedBy = [ "${mount-service}.mount" ];
systemd.services."${dir-service}".wantedBy = [ "${mount-service}.mount" ];
};
cfgs = builtins.map cfgFor ingested-dirs;
in {
fileSystems = lib.mkMerge (catAttrs "fileSystems" cfgs);
sane.fs = lib.mkMerge (catAttrs "fs" (catAttrs "sane" cfgs));
systemd = lib.mkMerge (catAttrs "systemd" cfgs);
}
)
]);
}

View File

@@ -0,0 +1,16 @@
{ config, lib, ... }:
let
cfg = config.sane.impermanence;
in
{
fileSystems."/" = lib.mkIf (cfg.enable && cfg.root-on-tmpfs) {
device = "none";
fsType = "tmpfs";
options = [
"mode=755"
"size=1G"
"defaults"
];
};
}

View File

@@ -20,22 +20,28 @@ in
default = false;
type = types.bool;
};
sane.nixcache.enable-trusted-keys = mkOption {
default = config.sane.nixcache.enable;
type = types.bool;
};
};
config = mkIf cfg.enable {
config = {
# use our own binary cache
nix.settings = {
substituters = [
# to explicitly build from a specific cache (in case others are down):
# - `nixos-rebuild ... --option substituters https://cache.nixos.org`
# - `nix build ... --substituters http://desko:5000`
nix.settings.substituters = mkIf cfg.enable [
"https://nixcache.uninsane.org"
"http://desko:5000"
"https://nix-community.cachix.org"
"https://cache.nixos.org/"
];
trusted-public-keys = [
# always trust our keys (so one can explicitly use a substituter even if it's not the default
nix.settings.trusted-public-keys = mkIf cfg.enable-trusted-keys [
"nixcache.uninsane.org:r3WILM6+QrkmsLgqVQcEdibFD7Q/4gyzD9dGT33GP70="
"desko:Q7mjjqoBMgNQ5P0e63sLur65A+D4f3Sv4QiycDIKxiI="
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
];
};
};
}

313
modules/packages.nix Normal file
View File

@@ -0,0 +1,313 @@
{ config, lib, pkgs, ... }:
with lib;
with pkgs;
let
cfg = config.sane.packages;
imagemagick = pkgs.imagemagick.override {
ghostscriptSupport = true;
};
consolePkgs = [
backblaze-b2
cdrtools
dmidecode
duplicity
efivar
flashrom
fwupd
ghostscript # TODO: imagemagick wrapper should add gs to PATH
gnupg
gocryptfs
gopass
gopass-jsonapi
ifuse
imagemagick
ipfs
libimobiledevice
libsecret # for managing user keyrings
lm_sensors # for sensors-detect
lshw
ffmpeg
memtester
networkmanager
nixpkgs-review
# nixos-generators
# nettools
nmon
oathToolkit # for oathtool
# ponymix
pulsemixer
python3
rsync
# python3Packages.eyeD3 # music tagging
sane-scripts
sequoia
snapper
sops
speedtest-cli
sqlite # to debug sqlite3 databases
ssh-to-age
sudo
# tageditor # music tagging
unar
visidata
w3m
wireguard-tools
# youtube-dl
yt-dlp
];
guiPkgs = [
# GUI only
aerc # email client
audacity
celluloid # mpv frontend
chromium
clinfo
{ pkg = dino; private = [ ".local/share/dino" ]; }
electrum
# creds/session keys, etc
{ pkg = element-desktop; private = [ ".config/Element" ]; }
# `emote` will show a first-run dialog based on what's in this directory.
# mostly, it just keeps a LRU of previously-used emotes to optimize display order.
# TODO: package [smile](https://github.com/mijorus/smile) for probably a better mobile experience.
{ pkg = emote; dir = [ ".local/share/Emote" ]; }
evince # works on phosh
# { pkg = fluffychat-moby; dir = [ ".local/share/chat.fluffy.fluffychat" ]; } # TODO: ship normal fluffychat on non-moby?
foliate
font-manager
# XXX by default fractal stores its state in ~/.local/share/<UUID>.
# after logging in, manually change ~/.local/share/keyrings/... to point it to some predictable subdir.
# then reboot (so that libsecret daemon re-loads the keyring...?)
{ pkg = fractal-latest; private = [ ".local/share/fractal" ]; }
# { pkg = fractal-next; private = [ ".local/share/fractal" ]; }
gajim # XMPP client
gimp # broken on phosh
gnome.cheese
gnome.dconf-editor
gnome-feeds # RSS reader (with claimed mobile support)
gnome.file-roller
gnome.gnome-disk-utility
gnome.gnome-maps # works on phosh
gnome.nautilus
# gnome-podcasts
gnome.gnome-system-monitor
gnome.gnome-terminal # works on phosh
gnome.gnome-weather
{ pkg = gpodder-configured; dir = [ "gPodder/Downloads" ]; }
gthumb
handbrake
inkscape
kdenlive
kid3 # audio tagging
krita
libreoffice-fresh # XXX colin: maybe don't want this on mobile
lollypop
mesa-demos
{ pkg = mpv; dir = [ ".config/mpv/watch_later" ]; }
networkmanagerapplet
# not strictly necessary, but allows caching articles; offline use, etc.
{ pkg = newsflash; dir = [ ".local/share/news-flash" ]; }
{ pkg = nheko; private = [
".config/nheko" # config file (including client token)
".cache/nheko" # media cache
".local/share/nheko" # per-account state database
]; }
# settings (electron app). TODO: can i manage these settings with home-manager?
{ pkg = obsidian; dir = [ ".config/obsidian" ]; }
pavucontrol
# picard # music tagging
playerctl
libsForQt5.plasmatube # Youtube player
soundconverter
# sublime music persists any downloaded albums here.
# it doesn't obey a conventional ~/Music/{Artist}/{Album}/{Track} notation, so no symlinking
# config (e.g. server connection details) is persisted in ~/.config/sublime-music/config.json
# possible to pass config as a CLI arg (sublime-music -c config.json)
# { pkg = sublime-music; dir = [ ".local/share/sublime-music" ]; }
{ pkg = sublime-music-mobile; dir = [ ".local/share/sublime-music" ]; }
tdesktop # broken on phosh
{ pkg = tokodon; private = [ ".cache/KDE/tokodon" ]; }
# vlc remembers play position in ~/.config/vlc/vlc-qt-interface.conf
{ pkg = vlc; dir = [ ".config/vlc" ]; }
whalebird # pleroma client. input is broken on phosh
xdg-utils # for xdg-open
xterm # broken on phosh
]
++ (if pkgs.system == "x86_64-linux" then
[
# x86_64 only
# creds, but also 200 MB of node modules, etc
(let discord = (pkgs.discord.override {
# XXX 2022-07-31: fix to allow links to open in default web-browser:
# https://github.com/NixOS/nixpkgs/issues/78961
nss = pkgs.nss_latest;
}); in { pkg = discord; private = [ ".config/discord" ]; })
# kaiteki # Pleroma client
# gnome.zenity # for kaiteki (it will use qarma, kdialog, or zenity)
# gpt2tc # XXX: unreliable mirror
logseq
losslesscut-bin
makemkv
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
{ pkg = monero-gui; dir = [ ".bitmonero" ]; }
# creds, media
{ pkg = signal-desktop; private = [ ".config/Signal" ]; }
# creds. TODO: can i manage this with home-manager?
{ pkg = spotify; dir = [ ".config/spotify" ]; }
# hardenedMalloc solves a crash at startup
(tor-browser-bundle-bin.override { useHardenedMalloc = false; })
# zcash coins. safe to delete, just slow to regenerate (10-60 minutes)
{ pkg = zecwallet-lite; private = [ ".zcash" ]; }
] else []);
# general-purpose utilities that we want any user to be able to access
# (specifically: root, in case of rescue)
systemPkgs = [
btrfs-progs
cacert.unbundled # some services require unbundled /etc/ssl/certs
cryptsetup
dig
efibootmgr
fatresize
fd
file
gawk
gptfdisk
hdparm
htop
iftop
inetutils # for telnet
iotop
iptables
jq
killall
lsof
netcat
nethogs
nmap
openssl
parted
pciutils
powertop
pstree
ripgrep
screen
smartmontools
socat
strace
tcpdump
tree
usbutils
wget
];
# useful devtools:
devPkgs = [
bison
dtc
flex
gcc
gdb
# gcc-arm-embedded
# gcc_multi
gnumake
mercurial
mix2nix
rustup
swig
];
pkgSpec = types.submodule {
options = {
pkg = mkOption {
type = types.package;
};
dir = mkOption {
type = types.listOf types.str;
default = [];
description = "list of home-relative paths to persist for this package";
};
private = mkOption {
type = types.listOf types.str;
default = [];
description = "list of home-relative paths to persist (in encrypted format) for this package";
};
};
};
in
{
options = {
# packages to deploy to the user's home
sane.packages.extraUserPkgs = mkOption {
default = [ ];
type = types.listOf (types.either types.package pkgSpec);
};
sane.packages.enableConsolePkgs = mkOption {
default = false;
type = types.bool;
};
sane.packages.enableGuiPkgs = mkOption {
default = false;
type = types.bool;
};
sane.packages.enableDevPkgs = mkOption {
description = ''
enable packages that are useful for building other software by hand.
you should prefer to keep this disabled except when prototyping, e.g. packaging new software.
'';
default = false;
type = types.bool;
};
sane.packages.enableSystemPkgs = mkOption {
default = false;
type = types.bool;
description = "enable system-wide packages";
};
sane.packages.enabledUserPkgs = mkOption {
default = cfg.extraUserPkgs
++ (if cfg.enableConsolePkgs then consolePkgs else [])
++ (if cfg.enableGuiPkgs then guiPkgs else [])
++ (if cfg.enableDevPkgs then devPkgs else [])
;
type = types.listOf (types.either types.package types.attrs);
description = "generated from other config options";
};
};
config = {
environment.systemPackages = mkIf cfg.enableSystemPkgs systemPkgs;
# XXX: this might not be necessary. try removing this and cacert.unbundled?
environment.etc."ssl/certs".source = mkIf cfg.enableSystemPkgs "${pkgs.cacert.unbundled}/etc/ssl/certs/*";
};
}

View File

@@ -27,8 +27,8 @@ let
};
in {
# map hostname -> something suitable for known_keys
hosts = builtins.mapAttrs (machine: keys: withHost machine keys.host) keys;
hosts = builtins.mapAttrs (host: keys: withHost host keys.host) keys;
# map hostname -> something suitable for authorized_keys to allow access to colin@<hostname>
users = builtins.mapAttrs (machine: keys: withUser "colin@${machine}" keys.users.colin) keys;
users = builtins.mapAttrs (host: keys: withUser "colin@${host}" keys.users.colin) keys;
}

View File

@@ -2,6 +2,9 @@
{
imports = [
./duplicity.nix
./dyn-dns.nix
./kiwix-serve.nix
./nixserve.nix
./trust-dns.nix
];
}

View File

@@ -1,5 +1,5 @@
# docs: https://search.nixos.org/options?channel=21.11&query=duplicity
{ config, lib, ... }:
{ config, lib, pkgs, ... }:
with lib;
let
@@ -15,11 +15,10 @@ in
config = mkIf cfg.enable {
# we need this mostly because of the size of duplicity's cache
sane.impermanence.service-dirs = [ "/var/lib/duplicity" ];
sane.impermanence.dirs = [ "/var/lib/duplicity" ];
services.duplicity.enable = true;
services.duplicity.targetUrl = ''"$DUPLICITY_URL"'';
services.duplicity.escapeUrl = false;
services.duplicity.targetUrl = "$DUPLICITY_URL";
# format: PASSPHRASE=<cleartext> \n DUPLICITY_URL=b2://...
# two sisters
# PASSPHRASE: remote backups will be encrypted using this passphrase (using gpg)
@@ -32,29 +31,28 @@ in
services.duplicity.secretFile = config.sops.secrets.duplicity_passphrase.path;
# NB: manually trigger with `systemctl start duplicity`
services.duplicity.frequency = "daily";
# TODO: this needs updating to handle impermanence changes
services.duplicity.exclude = [
# impermanent/inconsequential data:
"/dev"
"/proc"
"/run"
"/sys"
"/tmp"
# bind mounted (dupes):
"/var/lib"
# other mounts
"/mnt"
# data that's not worth the cost to backup:
"/nix/persist/var/lib/uninsane/media"
"/nix/persist/home/colin/tmp"
"/nix/persist/home/colin/Videos"
"/home/colin/tmp"
"/home/colin/Videos"
];
services.duplicity.extraFlags = [
# without --allow-source-mismatch, duplicity will abort if you change the hostname between backups
"--allow-source-mismatch"
# includes/exclude ordering matters, so we explicitly control it here.
# the first match decides a file's treatment. so here:
# - /nix/persist/home/colin/tmp is excluded
# - *other* /nix/persist/ files are included by default
# - anything else under `/` are excluded by default
"--exclude" "/nix/persist/home/colin/dev/home-logic/coremem/out" # this can reach > 1 TB
"--exclude" "/nix/persist/home/colin/use/iso" # might want to re-enable... but not critical
"--exclude" "/nix/persist/home/colin/.local/share/sublime-music" # music cache. better to just keep the HQ sources
"--exclude" "/nix/persist/home/colin/.local/share/Steam" # can just re-download games
"--exclude" "/nix/persist/home/colin/.bitmonero/lmdb" # monero blockchain
"--exclude" "/nix/persist/home/colin/.rustup"
"--exclude" "/nix/persist/home/colin/ref" # publicly available data: no point in duplicating it
"--exclude" "/nix/persist/home/colin/tmp"
"--exclude" "/nix/persist/home/colin/Videos"
"--exclude" "/nix/persist/var/lib/duplicity" # don't back up our own backup state!
"--include" "/nix/persist"
"--exclude" "/"
];
# set this for the FIRST backup, then remove it to enable incremental backups
@@ -70,5 +68,26 @@ in
"/dev/mmc0 5M"
];
};
# based on <nixpkgs:nixos/modules/services/backup/duplicity.nix> with changes:
# - remove the cleanup step: API key doesn't have delete perms
# - don't escape the targetUrl: it comes from an env var set in the secret file
systemd.services.duplicity.script = let
cfg = config.services.duplicity;
target = cfg.targetUrl;
extra = escapeShellArgs ([ "--archive-dir" "/var/lib/duplicity" ] ++ cfg.extraFlags);
dup = "${pkgs.duplicity}/bin/duplicity";
in lib.mkForce ''
set -x
# ${dup} cleanup ${target} --force ${extra}
# ${lib.optionalString (cfg.cleanup.maxAge != null) "${dup} remove-older-than ${lib.escapeShellArg cfg.cleanup.maxAge} ${target} --force ${extra}"}
# ${lib.optionalString (cfg.cleanup.maxFull != null) "${dup} remove-all-but-n-full ${builtins.toString cfg.cleanup.maxFull} ${target} --force ${extra}"}
# ${lib.optionalString (cfg.cleanup.maxIncr != null) "${dup} remove-all-inc-of-but-n-full ${toString cfg.cleanup.maxIncr} ${target} --force ${extra}"}
exec ${dup} ${if cfg.fullIfOlderThan == "always" then "full" else "incr"} ${lib.escapeShellArg cfg.root} ${target} ${lib.escapeShellArgs ([]
++ concatMap (p: [ "--include" p ]) cfg.include
++ concatMap (p: [ "--exclude" p ]) cfg.exclude
++ (lib.optionals (cfg.fullIfOlderThan != "never" && cfg.fullIfOlderThan != "always") [ "--full-if-older-than" cfg.fullIfOlderThan ])
)} ${extra}
'';
};
}

View File

@@ -0,0 +1,91 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.sane.services.dyn-dns;
in
{
options = {
sane.services.dyn-dns = {
enable = mkOption {
default = false;
type = types.bool;
};
ipPath = mkOption {
default = "/var/lib/uninsane/wan.txt";
type = types.str;
description = "where to store the latest WAN IPv4 address";
};
ipCmd = mkOption {
default = "${pkgs.sane-scripts}/bin/sane-ip-check-router-wan";
type = types.path;
description = "command to run to query the current WAN IP";
};
interval = mkOption {
type = types.str;
default = "10min";
description = "systemd time string for how frequently to re-check the IP";
};
restartOnChange = mkOption {
type = types.listOf types.str;
default = [];
description = "list of systemd unit files to restart when the IP changes";
};
};
};
config = mkIf cfg.enable {
systemd.services.dyn-dns = {
description = "update this host's record of its WAN IP";
serviceConfig.Type = "oneshot";
restartTriggers = [(builtins.toJSON cfg)];
after = [ "network.target" ];
wantedBy = cfg.restartOnChange;
before = cfg.restartOnChange;
script = ''
mkdir -p "$(dirname '${cfg.ipPath}')"
newIp=$(${cfg.ipCmd})
oldIp=$(cat '${cfg.ipPath}' || true)
# systemd path units are triggered on any file write action,
# regardless of content change. so only update the file if our IP *actually* changed
if [ "$newIp" != "$oldIp" ]
then
echo "$newIp" > '${cfg.ipPath}'
echo "WAN ip changed $oldIp -> $newIp"
fi
exit $(test -f '${cfg.ipPath}')
'';
};
systemd.timers.dyn-dns = {
# if anything wants dyn-dns.service, they surely want the timer too.
wantedBy = [ "dyn-dns.service" ];
timerConfig = {
OnUnitActiveSec = cfg.interval;
};
};
systemd.paths.dyn-dns-watcher = {
before = [ "dyn-dns.timer" ];
wantedBy = [ "dyn-dns.timer" ];
pathConfig = {
Unit = "dyn-dns-reactor.service";
PathChanged = [ cfg.ipPath ];
};
};
systemd.services.dyn-dns-reactor = {
description = "react to the system's WAN IP changing";
serviceConfig.Type = "oneshot";
script = if cfg.restartOnChange != [] then ''
${pkgs.systemd}/bin/systemctl restart ${toString cfg.restartOnChange}
'' else "${pkgs.coreutils}/bin/true";
};
};
}

View File

@@ -0,0 +1,55 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.sane.services.kiwix-serve;
in
{
options = {
sane.services.kiwix-serve = {
enable = mkOption {
default = false;
type = types.bool;
};
package = mkOption {
type = types.package;
default = pkgs.kiwix-tools;
defaultText = literalExpression "pkgs.kiwix-tools";
description = lib.mdDoc ''
The package that provides `bin/kiwix-serve`.
'';
};
port = mkOption {
type = types.port;
default = 80;
description = lib.mdDoc "Port number to listen on.";
};
listenAddress = mkOption {
type = types.nullOr types.str;
default = null;
description = lib.mdDoc ''
IP address to listen on. Listens on all available addresses if unspecified.
'';
};
zimPaths = mkOption {
type = types.nonEmptyListOf (types.either types.str types.path);
description = lib.mdDoc "ZIM file path(s)";
};
};
};
config = mkIf cfg.enable {
systemd.services.kiwix-serve = {
description = "Deliver ZIM file(s) articles via HTTP";
serviceConfig = let
maybeListenAddress = lib.optionals (cfg.listenAddress != null) ["-l" cfg.listenAddress];
args = maybeListenAddress ++ ["-p" cfg.port] ++ cfg.zimPaths;
in {
ExecStart = "${cfg.package}/bin/kiwix-serve ${lib.escapeShellArgs args}";
Type = "simple";
};
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
};
};
}

View File

@@ -14,8 +14,8 @@ in
type = types.bool;
};
sane.services.nixserve.sopsFile = mkOption {
default = ../../secrets/servo.yaml;
type = types.path;
description = "path to file that contains the nix_serv_privkey secret (can be in VCS)";
};
};

Some files were not shown because too many files have changed in this diff Show More