Compare commits

...

403 Commits

Author SHA1 Message Date
bc190f90bd flake update: nixpkgs 2023-01-13 -> 2023-01-15
```
• Updated input 'nixpkgs-stable':
    'github:nixos/nixpkgs/a83ed85c14fcf242653df6f4b0974b7e1c73c6c6' (2023-01-14)
  → 'github:nixos/nixpkgs/2f9fd351ec37f5d479556cd48be4ca340da59b8f' (2023-01-15)
• Updated input 'nixpkgs-unpatched':
    'github:nixos/nixpkgs/befc83905c965adfd33e5cae49acb0351f6e0404' (2023-01-13)
  → 'github:nixos/nixpkgs/6dccdc458512abce8d19f74195bb20fdb067df50' (2023-01-15)
```
2023-01-17 10:50:00 +00:00
7aac965e32 bootpart-tow-boot-rpi-aarch64: fix syntax error 2023-01-16 12:14:22 +00:00
18c98feb34 fs: fix /var/lib/private to have expected mode (0700) 2023-01-16 11:44:07 +00:00
ddb184b5ff (nixos) mx-puppet-discord: move to matrix category 2023-01-16 07:31:12 +00:00
194a6b6cf4 nixpatches: remove unused fakeHash input (just omit the hash when you need to) 2023-01-16 06:47:44 +00:00
016384aa2b nixpatches: move the list to the nixpatches flake instead of injecting it 2023-01-16 06:46:59 +00:00
b4e19c037e ejabberd: TODO: fix acme/nginx group membership 2023-01-16 05:59:52 +00:00
bd504f6c83 pin nheko package 2023-01-15 07:52:21 +00:00
bdd309eb15 flake: convert path:nixpatches -> ./nixpatches to fix poor flake input invalidation 2023-01-15 07:36:04 +00:00
eedc1170ec fix: remove kiwix-tools patch & improve nixpatches sub-flake UX 2023-01-15 04:27:42 +00:00
5a586c6e3c flake: migrate back to the more-efficient github: input scheme 2023-01-15 04:10:10 +00:00
371bcad650 flake.nix: use conventional URIs, no custom shit 2023-01-14 23:28:12 +00:00
926decbea5 persist ~/.cache/nix 2023-01-14 23:21:15 +00:00
c0f76ea8d8 flake: add flake feedback info for nix devs/readers 2023-01-14 23:20:38 +00:00
40fc37930f flake update: nixpkgs 2023-01-11 -> 2023-01-12
```
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/6a3f9996408c970b99b8b992b11bb249d1455b62' (2023-01-12)
  → 'github:NixOS/nixpkgs/e285dd0ca97c264003867c7329f0d1f4f028739c' (2023-01-13)
• Updated input 'nixpkgs-unpatched':
    'github:NixOS/nixpkgs/6c8644fc37b6e141cbfa6c7dc8d98846c4ff0c2e' (2023-01-11)
  → 'github:NixOS/nixpkgs/0f213d0fee84280d8c3a97f7469b988d6fe5fcdf' (2023-01-12)
```
2023-01-14 18:37:57 +00:00
30e7eb9ab6 sane-bt-search: convert to nix-shell and increase verbosity 2023-01-14 10:23:50 +00:00
2e03f47edc gPodder: persist the whole gPodder directory 2023-01-14 05:36:31 +00:00
4d552e3f0f gpodder-configured: remove the readFile business and use linkFarm instead 2023-01-14 05:29:38 +00:00
176a98879d gpodder: auto-unsubscribe from extra feeds at start 2023-01-14 05:25:16 +00:00
fc70889c34 Revert "import nix-script": it doesn't provide benefit over nix-shell
This reverts commit fe15cdd705.

although it *does* support generating derivation text,
import-from-derivation on the results is too clunky to actually be
usable in practice. it frequently mysteriously hangs instead.
2023-01-14 04:01:04 +00:00
49b4c57826 snippets: add nixos snippets 2023-01-14 03:38:51 +00:00
5111d095ac gpodder-configured: improve docs 2023-01-13 15:09:43 +00:00
fe15cdd705 import nix-script
this is a tool i can use like `nix-shell`, but it should be more
amenable to packaging. `nix-script --export --build-root .
./my-script.sh` gives a derivation which i should be able to
`callPackage` on.
2023-01-13 15:08:30 +00:00
638420ea0d whalebird: fix tray_icon oversight during last update 2023-01-13 10:09:07 +00:00
d55dd5ace6 whalebird: fix aarch64 build (hopefully) 2023-01-13 09:53:14 +00:00
45695aed6b whalebird: 4.6.5 -> 4.7.4 2023-01-13 09:41:05 +00:00
d6e79c4d07 feeds: remove the unused update.nix file 2023-01-13 09:41:05 +00:00
380ceaf625 mfeeds: rename update.sh -> update.py 2023-01-13 09:41:05 +00:00
942c581107 feeds: port the update.sh script to use our own feedsearch package instead of the deployed version 2023-01-13 09:41:05 +00:00
b6d94c2e08 feedsearch_crawler: add to all python3XXPackages 2023-01-13 09:41:05 +00:00
fd7acc8fc8 let host nix (i.e. nix-shell, nix-locate) know about our patched nixpkgs and overlays 2023-01-13 09:41:05 +00:00
db670fc172 package feedsearch-crawler 2023-01-13 09:41:05 +00:00
6438971c8c ssh keys: add github.com's pubkey 2023-01-13 09:41:05 +00:00
e439d398b6 flake: patch using the target system instead of the host 2023-01-13 09:05:00 +00:00
0f25cba331 moby kernel: disable config option that would break build 2023-01-13 04:40:34 +00:00
39959e912d cross: fix cross compilation by setting both local AND crossSystem 2023-01-13 04:40:34 +00:00
62e649743d moby: update megous kernel 6.1-20221128-1027 -> 6.1-20221211-1046 2023-01-13 04:40:34 +00:00
b1741a18e1 feeds: include "title" in the output OPML -- when it exists 2023-01-13 04:13:44 +00:00
a829a8e027 persist: fix permission mapping when acl is specified as toplevel attribute 2023-01-13 01:50:08 +00:00
d742ae83bd flake update: nixpkgs-unpatched: 2023-01-09 -> 2023-01-11
```
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/8c54d842d9544361aac5f5b212ba04e4089e8efe' (2023-01-08)
  → 'github:NixOS/nixpkgs/6a3f9996408c970b99b8b992b11bb249d1455b62' (2023-01-12)
• Updated input 'nixpkgs-unpatched':
    'github:NixOS/nixpkgs/aa1d74709f5dac623adb4d48fdfb27cc2c92a4d4' (2023-01-09)
  → 'github:NixOS/nixpkgs/6c8644fc37b6e141cbfa6c7dc8d98846c4ff0c2e' (2023-01-11)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/2253120d2a6147e57bafb5c689e086221df8032f' (2023-01-08)
  → 'github:Mic92/sops-nix/32187b33ac6ec9b628dcd08dd941a715e6241dda' (2023-01-12)
```
2023-01-13 00:02:32 +00:00
110ab1a794 feeds: fix snowden to not be a podcast 2023-01-11 16:20:53 +00:00
7d5a81e542 feeds: port Civboot 2023-01-11 16:11:46 +00:00
1af2a3f329 feeds: port Michael Malice 2023-01-11 16:05:25 +00:00
3fa9e910a9 feeds: port Matrix Live 2023-01-11 16:03:00 +00:00
6befc40700 feeds: migrate Decoder 2023-01-11 15:51:41 +00:00
29db2d8dc5 feeds: switch to working 60 minutes feed 2023-01-11 15:46:34 +00:00
36d8052982 feeds: disable 60 minutes 2023-01-11 15:41:25 +00:00
48115231a3 feeds: port acquired, FT 2023-01-11 15:32:42 +00:00
8b56ddd1ca feeds: port acquired 2023-01-11 15:27:28 +00:00
c1457f5bfb feeds: port 99% Invisible 2023-01-11 15:25:32 +00:00
7dfaf77a71 feeds: port Sam Harris / Waking Up 2023-01-11 15:15:03 +00:00
72dc7029e6 feeds: port Dan Carlin 2023-01-11 15:06:18 +00:00
95f3215b00 feeds: port darknet diaries and radiolab 2023-01-11 15:03:24 +00:00
baac8df8c2 feeds: fix Econtalk; port Doctorow, 80000hrs, deconstructed, intercepted, Post, The Portal 2023-01-11 14:51:17 +00:00
dc6a08a12b convert some of my feeds to db entries 2023-01-11 13:16:26 +00:00
2413e2eb5f feeds: update ACX feed to its non-forwarded origin 2023-01-11 10:59:35 +00:00
7327128493 feed-init: don't actually need to do the git actions 2023-01-11 10:52:10 +00:00
ed8059f4c4 feed init now also initializes the feed info 2023-01-11 10:49:56 +00:00
3a72295610 feeds: import xkcd, lesswrong, lexfridman 2023-01-11 10:42:05 +00:00
e6d9edf27d feeds: add a script to initialize a feed, as well 2023-01-11 10:41:39 +00:00
78782d5f7e flake: update-feeds now actually does update *all* feeds 2023-01-11 10:31:00 +00:00
91275f3723 flake: make an app which updates one feed 2023-01-11 10:22:25 +00:00
8115edea8d readme: fix some outdated info 2023-01-11 09:53:27 +00:00
4c475bbf9c flake: formatting nit 2023-01-11 09:33:59 +00:00
7040e1f07c flake: rename decl-host -> evalHost 2023-01-11 09:31:05 +00:00
aafa64942c flake: simplify the definition of packages 2023-01-11 09:29:49 +00:00
a44a99e371 flake: simplify the imgs/nixosConfigurations definition 2023-01-11 09:24:24 +00:00
a7ff90c843 flake: nixpkgs can now be built without specifying nixpkgs. as a prefix 2023-01-11 09:21:09 +00:00
d4996d6f31 flake: fix passthru overlays (fixes broken image building) 2023-01-11 09:08:46 +00:00
bd5209c655 move cross compilation out of the flake and into the host definitions 2023-01-11 08:56:06 +00:00
9588108fd5 restructure flake so that nixosConfigurations mostly just references the other flake outputs 2023-01-11 08:45:41 +00:00
942e302afb flake: fix crossFrom.aarch64-linux to actually be compiled from that system 2023-01-11 07:51:19 +00:00
2bd98e6764 flake: clean up nixpkgsFor-related functions 2023-01-11 07:50:32 +00:00
7b9910f287 reorder pkgs.cross definition for better readability 2023-01-11 07:37:01 +00:00
917afe209e try to do cross-compiling in a slightly less hacky way 2023-01-11 07:22:21 +00:00
cc5cf9b6f4 flake: format 2023-01-11 05:58:07 +00:00
57d95dd298 flake: document the weird importing 2023-01-10 17:51:04 +00:00
0b78df53be change the nixpkgs url type so that it hashes stably 2023-01-10 17:44:58 +00:00
c8dcb4ac59 flake: lift the nixpkgs patching out to its own flake
i hope it's a *little* cleaner this way, but tbh i'm not really sure.
2023-01-10 17:00:48 +00:00
241f4ae58f packages: add nano for when things go really wrong 2023-01-10 12:53:54 +00:00
965d7eedbb define a per-feed update script
it currently has to be run manually:
```
./pkgs/feeds/update.sh <...>
```

it looks like `nix-update` might not really support flakes
2023-01-10 10:53:59 +00:00
cdc881e887 feeds: write the basis for a module which reads feed metadata from disk and can (in the future) update it 2023-01-10 03:52:33 +00:00
33967554a5 servo: fix missing "lib" in nginx file 2023-01-09 13:25:56 +00:00
5af55ecdbf merge: cleanup/document 2023-01-09 11:47:39 +00:00
6ca3e7086e merge: simplify the implementation and make fully compatible with lib.mkMerge 2023-01-09 11:14:59 +00:00
ca62f1b62f rename flattenAttrsets -> joinAttrsets to disambiguate 2023-01-09 09:52:37 +00:00
eef66df36d lib: split merge out of the toplevel 2023-01-09 09:51:35 +00:00
9ca6a1c907 way overcomplicated way to merge toplevel config 2023-01-09 09:42:17 +00:00
dbb78088f4 refactor: cleanup instances where we map to attrs to be more resilient against duplicate names 2023-01-09 03:48:07 +00:00
f17ae1ca7b refactor: avoid using // where we know the sets should be disjoint 2023-01-09 03:11:14 +00:00
b2774a4004 move pubkeys out a modules/data/ directory 2023-01-09 02:40:25 +00:00
0ae548d47c flake update: nixpkgs 2023-01-04 -> 2023-01-05; sops
vim was segfaulting?? i'm hoping this fixes it, we'll see.

```
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/9813adc7f7c0edd738c6bdd8431439688bb0cb3d' (2023-01-04)
  → 'github:NixOS/nixpkgs/a518c77148585023ff56022f09c4b2c418a51ef5' (2023-01-05)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/e9ade2c8240e00a4784fac282a502efff2786bdc' (2023-01-04)
  → 'github:NixOS/nixpkgs/8c54d842d9544361aac5f5b212ba04e4089e8efe' (2023-01-08)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/b35586cc5abacd4eba9ead138b53e2a60920f781' (2023-01-01)
  → 'github:Mic92/sops-nix/2253120d2a6147e57bafb5c689e086221df8032f' (2023-01-08)
• Updated input 'sops-nix/nixpkgs-stable':
    'github:NixOS/nixpkgs/feda52be1d59f13b9aa02f064b4f14784b9a06c8' (2022-12-31)
  → 'github:NixOS/nixpkgs/9f11a2df77cb945c115ae2a65f53f38121597d73' (2023-01-07)
```
2023-01-08 23:52:40 +00:00
760505db20 snippets: add NUR package search 2023-01-08 14:16:06 +00:00
71fc1a2fd7 ssh: define system-wide knownHosts 2023-01-08 08:51:06 +00:00
a457fc1416 ssh: move sys config out of hosts/common 2023-01-08 08:43:23 +00:00
2c0b0f6947 ssh: explain why we specify host_keys the way we do instead of through sane.persist 2023-01-08 08:41:48 +00:00
f10de6c2c4 ids: improve docs 2023-01-08 06:54:29 +00:00
a6be200a82 ids: define the assertions more idiomatically 2023-01-08 06:51:25 +00:00
fb57e9aa5b cleanup the 'every user/group has an id' enforcement 2023-01-08 06:46:07 +00:00
f5acbbd830 image.nix: feed bug where enable flag wasnt actually being read 2023-01-08 05:37:25 +00:00
af77417531 feeds: add Perry Bible Fellowship comic 2023-01-08 05:30:36 +00:00
eea80b575d feeds: disable dilbert (it doesn't embed well) 2023-01-08 05:28:15 +00:00
6a209d27fd freshrss: only show text and image feeds 2023-01-08 05:27:45 +00:00
e8f778fecd feeds: convert to module 2023-01-08 05:24:56 +00:00
488036beb3 ssh: add git.uninsane.org host key back 2023-01-08 03:22:05 +00:00
00b681eca5 ssh: manager ourself instead of using home-manager 2023-01-08 03:14:47 +00:00
72d589cb2d ssh: port to modules system 2023-01-08 03:07:57 +00:00
ea5552daa7 bluetooth: accept that LinkKeys are device/host-specific and stop trying to share them across machines 2023-01-07 11:31:35 +00:00
fb7d94209c bluetooth: update key for portable speaker
i was having difficulty connecting from lappy.
i re-paired: the old LinkKey doesn't seem to work...?
this new key gave a file without `PublicAddress=true`: i don't *think*
that actually matters, though the device *does* appear to be a public
address on first glance (00: prefix, and last 2 bits aren't 11).
2023-01-07 10:18:36 +00:00
8f5b92685b install-bluetooth: just copy the keys, dont bother symlinking 2023-01-07 09:59:06 +00:00
32a4cb19fd sway: start pipewire early, to support bluetooth 2023-01-07 09:58:27 +00:00
031cfa2bcd get bluetooth working in gnome-control-center 2023-01-07 08:35:51 +00:00
e93fbea1e6 phosh: reorder the users defs 2023-01-07 08:08:49 +00:00
85a2fbc38a bluetooth: dont persist /var/lib/bluetooth 2023-01-07 08:08:29 +00:00
9e902c8eb2 preserve backlight settings across reboots 2023-01-07 05:17:43 +00:00
dc15091ea7 install-bluetooth: disable verbosity 2023-01-07 03:44:45 +00:00
c063ecd047 bluetooth keys: use sane.fs instead of activationScripts
also auto-determines the device ID, which was previously broken
2023-01-07 03:43:31 +00:00
70a43c770d net: fix a iwd error by not encoding a network name which didn't need encoding 2023-01-07 03:11:12 +00:00
cc9e2d8e15 net: simplify the iwd psk setup 2023-01-07 03:10:39 +00:00
bb41fb95fe iwd: populate net config with systemd service, not activationScript 2023-01-07 03:03:19 +00:00
d852adf806 move keyring to private store 2023-01-07 02:04:28 +00:00
5443542cba move keyring activation out of home-manager 2023-01-07 01:41:56 +00:00
81effb01a3 new script: sane-shutdown, validates host 2023-01-06 16:40:41 +00:00
83f416999f splatmoji: persist history file 2023-01-06 16:35:31 +00:00
dd34883246 move feed consumers out of home-manager 2023-01-06 16:27:05 +00:00
e47f9e38ce remove old nb module 2023-01-06 16:15:49 +00:00
0f0b728911 splatmoji: store config with sane.fs instead of home-manager 2023-01-06 16:13:51 +00:00
1839f87a4e vlc: handle the config file with sane.fs 2023-01-06 16:11:56 +00:00
53edf4e6af firefox: handle config files manually, instead of leveraging home-manager 2023-01-06 16:11:06 +00:00
fb6e0ddb34 convert some home-manager files to be manually managed 2023-01-06 15:48:51 +00:00
0a48d79174 fs: introduce some helpers to make writing symlinks easier 2023-01-06 15:38:29 +00:00
b6208e1a19 fs: allow specifying text for a symlink directly 2023-01-06 15:26:39 +00:00
e46ab4ec14 ssh: use sane.persist/sane.fs instead of home-manager to ensure keys 2023-01-06 15:05:01 +00:00
19c254c266 fs: make symlinking more resilient when something's already at the location 2023-01-06 14:51:25 +00:00
1d0cadce85 persist: configure the private store to symlink everyting by default 2023-01-06 14:44:32 +00:00
e8342b8044 persist: clean up the "byPath" conversions 2023-01-06 14:20:30 +00:00
40e642bfc3 persist: add a 'method' option to allow symlinking in favor of binding 2023-01-06 14:05:49 +00:00
f008565e22 persist: for options common to entries specified by both path and store, move to a common submodule 2023-01-06 13:58:36 +00:00
4ea2835d9d persist: handle inline acl options more cleanly 2023-01-06 13:47:59 +00:00
493d317bb1 moby: override browser-cache persistence more cleanly 2023-01-06 13:28:18 +00:00
e446bfba58 fs: fix eval error when told about a mount but not told about anything *in* that mount 2023-01-06 13:27:27 +00:00
a7bac5de18 persist: convert the sane.persist.home.<store> => mappings back to a strongly-typed module & add a byPath shorthand 2023-01-06 13:06:39 +00:00
b0950e90f4 persist: prefer mkMerge instead of manually folding attrsets 2023-01-06 12:44:29 +00:00
d8cd0e1f57 persist: fold redundant lines 2023-01-06 12:39:55 +00:00
fd7d67ee05 persist: simplify & remove dead code 2023-01-06 12:28:55 +00:00
1a712b4d47 rename sane.persist.{all -> byPath} 2023-01-06 12:19:03 +00:00
4520e1d1f5 persist: auto-map user-provided store values earlier 2023-01-06 11:56:22 +00:00
841a2a3bcb persist: change sane.persist.all to be an attrsOf that maps path to settings 2023-01-06 11:52:28 +00:00
fe816e9110 persist: lift sane.persist.dirs.{home,sys} up one level 2023-01-06 11:29:13 +00:00
426e0c3ae2 persist: lift sane.persist.dirs.all up to sane.persist.all 2023-01-06 11:24:11 +00:00
a95b91a556 refactor the dirsSubModule type so that we don't reference 'config.sane.persist' while creating options 2023-01-06 10:35:32 +00:00
837e5438c3 persist: document the dirsSubModule type better 2023-01-06 10:31:01 +00:00
8217b22c86 rename impermanence -> persist 2023-01-06 10:04:51 +00:00
0b35ce4dec Merge branch 'staging/nixpkgs-2023-01-04' 2023-01-06 10:00:37 +00:00
413f9a171b impermanence: remove /home perms hack 2023-01-06 09:59:29 +00:00
43a46af43b impermanence: cleanup backing directory creation. this should let me remove the per-store /home/<user> perms hack 2023-01-06 09:56:06 +00:00
1a0f05bfd6 flake update: nixpkgs 2022-12-31 -> 2023-01-04
```
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/8ba56d7c0d7490680f2d51ba46a141eca7c46afa' (2022-12-31)
  → 'github:NixOS/nixpkgs/9813adc7f7c0edd738c6bdd8431439688bb0cb3d' (2023-01-04)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/6a0d2701705c3cf6f42c15aa92b7885f1f8a477f' (2022-12-30)
  → 'github:NixOS/nixpkgs/e9ade2c8240e00a4784fac282a502efff2786bdc' (2023-01-04)
```
2023-01-06 08:57:39 +00:00
c18dd9636d fs: symlinking: fix recursive links (don't follow links when creating new ones) 2023-01-06 05:32:31 +00:00
0977721af5 moby: fix to preserve browser cache across boots 2023-01-04 13:27:20 +00:00
122d3cd7e4 impermanence: fix home perms in ~/private dir 2023-01-04 13:24:23 +00:00
cd5f8054c0 fs: rename "mountpt" -> "origin" to reflect that it doesnt have to be a device 2023-01-04 12:19:32 +00:00
3db388b105 servo: relocate ext device to /mnt/impermanence/ext and fixup deps 2023-01-04 12:12:30 +00:00
2ba6116f10 fs/impermanence: more precisely control unit dependencies/ordering 2023-01-04 11:22:26 +00:00
592d17b725 impermanence: crypt: simplify setup (experimental) 2023-01-04 09:28:59 +00:00
4d9c15f9b8 fs: fix file mode even if not newly created 2023-01-04 08:12:53 +00:00
abced7dd0d navidrome: don't try to chown to an invalid user 2023-01-04 08:00:04 +00:00
5c42365912 sane-stop-all-servo: add missing services 2023-01-04 07:49:21 +00:00
247ad326b2 freshrss: be conservative and use explicit octal mode bits 2023-01-04 07:14:54 +00:00
170008f345 home.files symlinks: port to sane.fs 2023-01-04 07:14:38 +00:00
2c48e61854 fs: fix mode of deployed files; simplify 2023-01-04 07:14:01 +00:00
f89f756489 fs: create symlinks at multi-user target by default 2023-01-04 06:32:53 +00:00
c0da19951b fs: fix symlink ownership/perms 2023-01-04 06:28:44 +00:00
5fb67306e4 fs: rework for dir to not be mandatory 2023-01-04 06:17:34 +00:00
5533b586d7 fs: lift depends out of dir, to toplevel 2023-01-04 04:32:20 +00:00
68c2eb7363 impermanence: clean up the deps for the crypt store 2023-01-04 04:22:17 +00:00
fd79026366 fs: fix loose mount dependency 2023-01-04 04:06:19 +00:00
a76471cb1f fs: simplify the mount configuration 2023-01-04 03:57:24 +00:00
c94b8299a6 fs: add experimental support for symlink entries 2023-01-04 02:51:07 +00:00
175bc0709f remove external impermanence library 2023-01-04 02:18:03 +00:00
7b02477486 servo: define /etc/persist via sane impermanence module 2023-01-04 02:15:43 +00:00
d7c8638fea impermanence: add a storeDescription field per store 2023-01-04 01:54:13 +00:00
9d7d1acc80 sane.impermanence.dirs.home.<store> is now auto-generated and options can vary across deployments 2023-01-04 01:45:05 +00:00
787857d27f firefox: update plugin hashes 2023-01-04 01:39:42 +00:00
9c248a8a31 impermanence: cleanup the dirs submodule 2023-01-04 01:34:19 +00:00
829680fb00 impermanence: simplify dir-acl handling by using a helper 2023-01-04 01:19:22 +00:00
a9ee26388c guest account: make home-dir writable by other users 2023-01-04 01:09:23 +00:00
2960b895b6 lib: lift acl type into sane-lib/types 2023-01-04 00:59:52 +00:00
933063115b moby: fix home-dirs for newer impermanence module 2023-01-04 00:47:48 +00:00
afe684ca2c modules: impermanence: use sane-lib.path 2023-01-03 14:55:27 +00:00
93f1411522 fs: split helpers out into sane-lib module 2023-01-03 14:20:02 +00:00
01e44c1f7f flake.nix: remove unused specialArgs 2023-01-03 14:18:57 +00:00
618e9bd2fa gocryptfs: place package in system.fsPackages instead of environment.systemPackages (it propagates anyway) 2023-01-03 12:00:49 +00:00
fbc39d0584 modules: fs: move to subdir 2023-01-03 08:27:28 +00:00
2d7b3750cd impermanence: split the /home/colin perms fix into more appropriate places 2023-01-03 08:25:43 +00:00
e6ccd2e4f7 impermanence: split plaintext store to own file (this will bypass some recursion in the next patch) 2023-01-03 08:02:03 +00:00
d4bf491e9c impermanence: improve docs 2023-01-03 07:45:19 +00:00
5a2bbcce3b move plaintext home-dirs out of home-manager module into users module 2023-01-03 07:35:42 +00:00
327e6b536f impermanence: large refactor, and experimental bind mounting of things from ~/private 2023-01-03 07:22:37 +00:00
bace7403e7 Merge branch 'staging/nixpkgs-2022-12-31' 2023-01-03 03:05:21 +00:00
57f5521ef3 grpc: unpin (seems to build OK) 2023-01-03 03:05:07 +00:00
9e32211c12 impermanence: cange "encryptedClearOnBoot" to a broader "store" argument
in the future it can support ~/private as a backing store
2023-01-03 03:04:19 +00:00
edf6bd4455 fs: add a "mount.bind" option & use it for impermanence bind-mounts 2023-01-03 02:45:23 +00:00
a9a14786f9 packages: disable fractal (unused, slow build) 2023-01-02 23:35:43 +00:00
eade5fe16e flake update: 2022-12-22 -> 2022-12-31
```
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/652e92b8064949a11bc193b90b74cb727f2a1405' (2022-12-22)
  → 'github:NixOS/nixpkgs/8ba56d7c0d7490680f2d51ba46a141eca7c46afa' (2022-12-31)
• Updated input 'nixpkgs-stable':
    'github:NixOS/nixpkgs/dac57a4eccf1442e8bf4030df6fcbb55883cb682' (2022-12-24)
  → 'github:NixOS/nixpkgs/6a0d2701705c3cf6f42c15aa92b7885f1f8a477f' (2022-12-30)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/855b8d51fc3991bd817978f0f093aa6ae0fae738' (2022-12-25)
  → 'github:Mic92/sops-nix/b35586cc5abacd4eba9ead138b53e2a60920f781' (2023-01-01)
• Updated input 'sops-nix/nixpkgs-stable':
    'github:NixOS/nixpkgs/939c05a176b8485971463c18c44f48e56a7801c9' (2022-12-24)
  → 'github:NixOS/nixpkgs/feda52be1d59f13b9aa02f064b4f14784b9a06c8' (2022-12-31)
```
2023-01-02 22:34:22 +00:00
be222c1d70 trust-dns: allow shorthand assignment of record lists 2023-01-02 13:23:52 +00:00
88a33dd5de snippets: add private links 2023-01-02 13:23:29 +00:00
875e923197 declare ~/private in fileSystems and reuse for pamMount 2023-01-02 11:34:02 +00:00
54dd643cf0 trust-dns: make a note about another DNS library we could draw from 2023-01-02 11:33:32 +00:00
3c726f148b remove some stale references to mobile-nixos 2023-01-02 10:00:20 +00:00
e225e2e704 modules/packages: directly set impermanence.home-dirs instead of working through home-manager 2023-01-02 07:45:05 +00:00
cf0bf8190e modules/packages: clean up loose typing of sane.packages 2023-01-02 07:16:16 +00:00
b8f7f68d4c packages: telegram: persist data in private storage 2023-01-02 07:06:58 +00:00
7a3aae8c97 fs: tidy 2022-12-31 12:38:50 +00:00
89e519810d impermanence: clean up the bind mounts 2022-12-31 12:31:49 +00:00
0e920230ba impermanence: fix systemd service ordering for crypt mount 2022-12-31 12:18:27 +00:00
6ffae00e17 fs: rename "service" option to "unit" option 2022-12-31 11:31:16 +00:00
be19985440 impermanence: crypt: more robust perms and ordering of backing device 2022-12-31 10:45:43 +00:00
f7e3e7294a impermanence: transform gocryptfs key generation from activation script to systemd unit 2022-12-31 10:15:08 +00:00
d745e3c1ee impermanence: remove fuse module: we don't need it now that we're mounting after activation 2022-12-31 09:13:31 +00:00
c1890ce82b impermanence: cleanup some previously verbose code 2022-12-31 09:09:51 +00:00
53a0b621d8 impermanence: use sane.fs to inherit permissions instead of specifying defaults here 2022-12-31 01:04:49 +00:00
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
196 changed files with 8230 additions and 1694 deletions

118
flake.lock generated
View File

@@ -36,29 +36,14 @@
"type": "github"
}
},
"impermanence": {
"locked": {
"lastModified": 1668668915,
"narHash": "sha256-QjY4ZZbs9shwO4LaLpvlU2bO9J1juYhO9NtV3nrbnYQ=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "5df9108b346f8a42021bf99e50de89c9caa251c3",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "impermanence",
"type": "github"
}
},
"mobile-nixos": {
"flake": false,
"locked": {
"lastModified": 1668897543,
"narHash": "sha256-1bjvy5zi/6KDzhN3ihOUEA6y5FFEOf5xvIbf65RWIh0=",
"lastModified": 1670131242,
"narHash": "sha256-T/o1/3gffr010fsqgNshs1NJJjsnUYvQnUZgm6hilsY=",
"owner": "nixos",
"repo": "mobile-nixos",
"rev": "25eec596116553112681d72ee4880107fc3957fa",
"rev": "5ee45cc1f8e43f4af14ee17ccef9156b0db8cd77",
"type": "github"
},
"original": {
@@ -68,60 +53,79 @@
}
},
"nixpkgs": {
"inputs": {
"nixpkgs": [
"nixpkgs-unpatched"
]
},
"locked": {
"lastModified": 1669542132,
"narHash": "sha256-DRlg++NJAwPh8io3ExBJdNW7Djs3plVI5jgYQ+iXAZQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a115bb9bd56831941be3776c8a94005867f316a7",
"type": "github"
"lastModified": 1,
"narHash": "sha256-5zCxdHGOS0OOP7vbgTA1iwv9GVr5JSiths7QmgUsU84=",
"path": "/nix/store/9a5k9pfawxzz1sng17si26sc9af39jr1-source/nixpatches",
"type": "path"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
}
},
"nixpkgs-22_05": {
"locked": {
"lastModified": 1669513802,
"narHash": "sha256-AmTRNi8bHgJlmaNe3r5k+IMFbbXERM/KarqveMAZmsY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6649e08812f579581bfb4cada3ba01e30485c891",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-22.05",
"repo": "nixpkgs",
"type": "github"
"path": "/nix/store/9a5k9pfawxzz1sng17si26sc9af39jr1-source/nixpatches",
"type": "path"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1669546925,
"narHash": "sha256-Gvtk9agz88tBgqmCdHl5U7gYttTkiuEd8/Rq1Im0pTg=",
"owner": "NixOS",
"lastModified": 1673800717,
"narHash": "sha256-SFHraUqLSu5cC6IxTprex/nTsI81ZQAtDvlBvGDWfnA=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "fecf05d4861f3985e8dee73f08bc82668ef75125",
"rev": "2f9fd351ec37f5d479556cd48be4ca340da59b8f",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-22.05",
"type": "indirect"
"owner": "nixos",
"ref": "nixos-22.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable_2": {
"locked": {
"lastModified": 1673740915,
"narHash": "sha256-MMH8zONfqahgHly3K8/A++X34800rajA/XgZ2DzNL/M=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7c65528c3f8462b902e09d1ccca23bb9034665c2",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-22.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-unpatched": {
"locked": {
"lastModified": 1673796341,
"narHash": "sha256-1kZi9OkukpNmOaPY7S5/+SlCDOuYnP3HkXHvNDyLQcc=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "6dccdc458512abce8d19f74195bb20fdb067df50",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"home-manager": "home-manager",
"impermanence": "impermanence",
"mobile-nixos": "mobile-nixos",
"nixpkgs": "nixpkgs",
"nixpkgs-stable": "nixpkgs-stable",
"nixpkgs-unpatched": "nixpkgs-unpatched",
"sops-nix": "sops-nix",
"uninsane": "uninsane"
"uninsane-dot-org": "uninsane-dot-org"
}
},
"sops-nix": {
@@ -129,14 +133,14 @@
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-22_05": "nixpkgs-22_05"
"nixpkgs-stable": "nixpkgs-stable_2"
},
"locked": {
"lastModified": 1669714206,
"narHash": "sha256-9aiMbzRL8REsyi9U0eZ+lT4s7HaILA1gh9n2apKzLxU=",
"lastModified": 1673752321,
"narHash": "sha256-EFfXY1ZHJq4FNaNQA9x0djtu/jiOhBbT0Xi+BT06cJw=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "8295b8139ef7baadeb90c5cad7a40c4c9297ebf7",
"rev": "e18eefd2b133a58309475298052c341c08470717",
"type": "github"
},
"original": {
@@ -145,7 +149,7 @@
"type": "github"
}
},
"uninsane": {
"uninsane-dot-org": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [

227
flake.nix
View File

@@ -1,25 +1,48 @@
# docs:
# - <https://nixos.wiki/wiki/Flakes>
# FLAKE FEEDBACK:
# - if flake inputs are meant to be human-readable, a human should be able to easily track them down given the URL.
# - this is not the case with registry URLs, like `nixpkgs/nixos-22.11`.
# - this is marginally the case with schemes like `github:nixos/nixpkgs`.
# - given the *existing* `git+https://` scheme, i propose expressing github URLs similarly:
# - `github+https://github.com/nixos/nixpkgs/tree/nixos-22.11`
# - need some way to apply local patches to inputs.
#
#
# DEVELOPMENT DOCS:
# - Flake docs: <https://nixos.wiki/wiki/Flakes>
# - Flake RFC: <https://github.com/tweag/rfcs/blob/flakes/rfcs/0049-flakes.md>
# - Discussion: <https://github.com/NixOS/rfcs/pull/49>
# - <https://serokell.io/blog/practical-nix-flakes>
{
# XXX: use the `github:` scheme instead of the more readable git+https: because it's *way* more efficient
# preferably, i would rewrite the human-readable https URLs to nix-specific github: URLs with a helper,
# but `inputs` is required to be a strict attrset: not an expression.
inputs = {
nixpkgs-stable.url = "nixpkgs/nixos-22.05";
nixpkgs.url = "nixpkgs/nixos-unstable";
# <https://github.com/nixos/nixpkgs/tree/nixos-22.11>
nixpkgs-stable.url = "github:nixos/nixpkgs?ref=nixos-22.11";
# <https://github.com/nixos/nixpkgs/tree/nixos-unstable>
nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=nixos-unstable";
nixpkgs = {
url = "./nixpatches";
inputs.nixpkgs.follows = "nixpkgs-unpatched";
};
mobile-nixos = {
# <https://github.com/nixos/mobile-nixos>
url = "github:nixos/mobile-nixos";
flake = false;
};
home-manager = {
url = "github:nix-community/home-manager/release-22.05";
# <https://github.com/nix-community/home-manager/tree/release-22.05>
url = "github:nix-community/home-manager?ref=release-22.05";
inputs.nixpkgs.follows = "nixpkgs";
};
sops-nix = {
# <https://github.com/Mic92/sops-nix>
url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
impermanence.url = "github:nix-community/impermanence";
uninsane = {
uninsane-dot-org = {
url = "git+https://git.uninsane.org/colin/uninsane";
inputs.nixpkgs.follows = "nixpkgs";
};
@@ -29,56 +52,56 @@
self,
nixpkgs,
nixpkgs-stable,
nixpkgs-unpatched,
mobile-nixos,
home-manager,
sops-nix,
impermanence,
uninsane
}: let
patchedPkgs = system: nixpkgs.legacyPackages.${system}.applyPatches {
name = "nixpkgs-patched-uninsane";
src = nixpkgs;
patches = import ./nixpatches/list.nix nixpkgs.legacyPackages.${system}.fetchpatch;
};
# 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-host = { name, local, target }:
uninsane-dot-org
}:
let
nixosSystem = import ((patchedPkgs target) + "/nixos/lib/eval-config.nix");
in (nixosSystem {
# by default the local system is the same as the target, employing emulation when they differ
system = target;
specialArgs = { inherit mobile-nixos home-manager impermanence; };
modules = [
./modules
(import ./hosts/instantiate.nix name)
home-manager.nixosModule
impermanence.nixosModule
sops-nix.nixosModules.sops
{
nixpkgs.overlays = [
(import "${mobile-nixos}/overlay/overlay.nix")
uninsane.overlay
(import ./pkgs/overlay.nix)
(next: prev: rec {
# non-emulated packages build *from* local *for* target.
# for large packages like the linux kernel which are expensive to build under emulation,
# 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;
})
];
}
];
});
nixpkgsCompiledBy = local: nixpkgs.legacyPackages."${local}";
decl-bootable-host = { name, local, target }: rec {
nixosConfiguration = decl-host { inherit name local target; };
evalHost = { name, local, target }:
let
# XXX: we'd prefer to use `nixosSystem = (nixpkgsCompiledBy target).nixos`
# but it doesn't propagate config to the underlying pkgs, meaning it doesn't let you use
# non-free packages even after setting nixpkgs.allowUnfree.
# XXX: patch using the target -- not local -- otherwise the target will
# need to emulate the host in order to rebuild!
nixosSystem = import ((nixpkgsCompiledBy target).path + "/nixos/lib/eval-config.nix");
in
(nixosSystem {
# we use pkgs built for and *by* the target, i.e. emulation, by default.
# cross compilation only happens on explicit access to `pkgs.cross`
system = target;
modules = [
(import ./hosts/instantiate.nix { localSystem = local; hostName = name; })
self.nixosModules.default
self.nixosModules.passthru
{
nixpkgs.overlays = [
self.overlays.default
self.overlays.passthru
self.overlays.pins
];
}
];
});
in {
nixosConfigurations = {
servo = evalHost { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
desko = evalHost { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
lappy = evalHost { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
moby = evalHost { 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 foo-cross and then foo incurs some rebuilding.
moby-cross = evalHost { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
rescue = evalHost { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
};
# unofficial output
# 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)
@@ -92,40 +115,76 @@
# - 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 './#<host>' switch`
img = nixosConfiguration.config.system.build.img;
};
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 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) hosts;
imgs = builtins.mapAttrs (name: value: value.img) hosts;
packages = let
allPkgsFor = sys: (customPackagesFor sys sys) // {
nixpkgs = nixpkgsFor sys sys;
uninsane = uninsane.packages."${sys}";
imgs = builtins.mapAttrs (_: host-dfn: host-dfn.config.system.build.img) self.nixosConfigurations;
overlays = rec {
default = pkgs;
pkgs = import ./overlays/pkgs.nix;
pins = import ./overlays/pins.nix; # TODO: move to `nixpatches/` input
passthru =
let
stable = next: prev: {
stable = nixpkgs-stable.legacyPackages."${prev.stdenv.hostPlatform.system}";
};
mobile = (import "${mobile-nixos}/overlay/overlay.nix");
uninsane = uninsane-dot-org.overlay;
in
next: prev:
(stable next prev) // (mobile next prev) // (uninsane next prev);
};
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";
nixosModules = rec {
default = sane;
sane = import ./modules;
passthru = { ... }: {
imports = [
home-manager.nixosModule
sops-nix.nixosModules.sops
];
};
};
# this includes both our native packages and all the nixpkgs packages.
legacyPackages =
let
allPkgsFor = sys: (nixpkgsCompiledBy sys).appendOverlays [
self.overlays.passthru self.overlays.pkgs
];
in {
x86_64-linux = allPkgsFor "x86_64-linux";
aarch64-linux = allPkgsFor "aarch64-linux";
};
# extract only our own packages from the full set
packages = builtins.mapAttrs
(_: full: full.sane // { inherit (full) sane uninsane-dot-org; })
self.legacyPackages;
apps."x86_64-linux" =
let
pkgs = self.legacyPackages."x86_64-linux";
in {
update-feeds = {
type = "app";
program = "${pkgs.feeds.passthru.updateScript}";
};
init-feed = {
type = "app";
program = "${pkgs.feeds.passthru.initFeedScript}";
};
};
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,16 @@
{ lib, pkgs, ... }:
{
# persist external pairings by default
sane.persist.sys.plaintext = [ "/var/lib/bluetooth" ];
sane.fs."/var/lib/bluetooth".generated.acl.mode = "0700";
sane.fs."/var/lib/bluetooth/.secrets.stamp" = {
wantedBeforeBy = [ "bluetooth.service" ];
# XXX: install-bluetooth uses sed, but that's part of the default systemd unit path, it seems
generated.script.script = builtins.readFile ../../scripts/install-bluetooth + ''
touch "/var/lib/bluetooth/.secrets.stamp"
'';
generated.script.scriptArgs = [ "/run/secrets/bt" ];
};
}

22
hosts/common/cross.nix Normal file
View File

@@ -0,0 +1,22 @@
{ config, ... }:
let
mkCrossFrom = localSystem: pkgs: import pkgs.path {
inherit localSystem;
crossSystem = pkgs.stdenv.hostPlatform.system;
inherit (config.nixpkgs) config overlays;
};
in
{
# the configuration of which specific package set `pkgs.cross` refers to happens elsewhere;
# here we just define them all.
nixpkgs.overlays = [
(next: prev: {
# non-emulated packages build *from* local *for* target.
# for large packages like the linux kernel which are expensive to build under emulation,
# the config can explicitly pull such packages from `pkgs.cross` to do more efficient cross-compilation.
crossFrom."x86_64-linux" = mkCrossFrom "x86_64-linux" next;
crossFrom."aarch64-linux" = mkCrossFrom "aarch64-linux" next;
})
];
}

View File

@@ -1,8 +1,13 @@
{ pkgs, ... }:
{
imports = [
./bluetooth.nix
./cross.nix
./feeds.nix
./fs.nix
./hardware
./i2p.nix
./ids.nix
./machine-id.nix
./net.nix
./secrets.nix
@@ -16,6 +21,18 @@
sane.packages.enableConsolePkgs = true;
sane.packages.enableSystemPkgs = true;
sane.persist.sys.plaintext = [
"/var/log"
"/var/backup" # for e.g. postgres dumps
# TODO: move elsewhere
"/var/lib/alsa" # preserve output levels, default devices
"/var/lib/colord" # preserve color calibrations (?)
"/var/lib/machines" # maybe not needed, but would be painful to add a VM and forget.
];
# some services which use private directories error if the parent (/var/lib/private) isn't 700.
sane.fs."/var/lib/private".dir.acl.mode = "0700";
nixpkgs.config.allowUnfree = true;
# time.timeZone = "America/Los_Angeles";
@@ -25,6 +42,11 @@
nix.extraOptions = ''
experimental-features = nix-command flakes
'';
# allow `nix-shell` (and probably nix-index?) to locate our patched and custom packages
nix.nixPath = [
"nixpkgs=${pkgs.path}"
"nixpkgs-overlays=${../..}/overlays"
];
# TODO: move this into home-manager?
fonts = {
@@ -56,19 +78,8 @@
};
# enable zsh completions
environment.pathsToLink = [ "/share/zsh" ];
environment.systemPackages = with pkgs; [
# required for pam_mount
gocryptfs
];
# link debug symbols into /run/current-system/sw/lib/debug
# hopefully picked up by gdb automatically?
environment.enableDebugInfo = true;
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;
}

186
hosts/common/feeds.nix Normal file
View File

@@ -0,0 +1,186 @@
{ lib, sane-data, ... }:
let
hourly = { freq = "hourly"; };
daily = { freq = "daily"; };
weekly = { freq = "weekly"; };
infrequent = { freq = "infrequent"; };
art = { cat = "art"; };
humor = { cat = "humor"; };
pol = { cat = "pol"; }; # or maybe just "social"
rat = { cat = "rat"; };
tech = { cat = "tech"; };
uncat = { cat = "uncat"; };
text = { format = "text"; };
mkRss = format: url: { inherit url format; } // uncat // infrequent;
# format-specific helpers
mkText = mkRss "text";
mkImg = mkRss "image";
mkPod = mkRss "podcast";
# host-specific helpers
mkSubstack = subdomain: { substack = subdomain; };
fromDb = name:
let
raw = sane-data.feeds."${name}";
in {
url = raw.url;
# not sure the exact mapping with velocity here: entries per day?
freq = lib.mkDefault (
if raw.velocity or 0 > 2 then
"hourly"
else if raw.velocity or 0 > 0.5 then
"daily"
else if raw.velocity or 0 > 0.1 then
"weekly"
else
"infrequent"
);
} // lib.optionalAttrs (raw.is_podcast or false) {
format = "podcast";
} // lib.optionalAttrs (raw.title or "" != "") {
title = lib.mkDefault raw.title;
};
podcasts = [
(fromDb "lexfridman.com/podcast" // rat)
# (mkPod "https://lexfridman.com/feed/podcast/" // rat // weekly)
## Astral Codex Ten
(fromDb "sscpodcast.libsyn.com" // rat)
## Econ Talk
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat)
## Cory Doctorow -- both podcast & text entries
(fromDb "craphound.com" // pol)
(mkPod "https://congressionaldish.libsyn.com/rss" // pol // infrequent)
## Civboot -- https://anchor.fm/civboot
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech)
(fromDb "feeds.feedburner.com/80000HoursPodcast" // rat)
(fromDb "allinchamathjason.libsyn.com" // pol)
(fromDb "acquired.libsyn.com" // tech)
# The Intercept - Deconstructed; also available: <rss.acast.com/deconstructed>
(fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol)
## The Daily
(mkPod "https://feeds.simplecast.com/54nAGcIl" // pol // daily)
# The Intercept - Intercepted; also available: <https://rss.acast.com/intercepted-with-jeremy-scahill>
(fromDb "rss.prod.firstlook.media/intercepted/podcast.rss" // pol)
(fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
## Eric Weinstein
(fromDb "rss.art19.com/the-portal" // rat)
(fromDb "darknetdiaries.com" // tech)
## Radiolab -- also available here, but ONLY OVER HTTP: <http://feeds.wnyc.org/radiolab>
(fromDb "feeds.feedburner.com/radiolab" // pol)
## Sam Harris
(fromDb "wakingup.libsyn.com" // pol)
## 99% Invisible -- also available here: <https://feeds.simplecast.com/BqbsxVfO>
(fromDb "feeds.99percentinvisible.org/99percentinvisible" // pol)
(fromDb "rss.acast.com/ft-tech-tonic" // tech)
(fromDb "feeds.feedburner.com/dancarlin/history" // rat)
(fromDb "rss.art19.com/60-minutes" // pol)
## The Verge - Decoder
(fromDb "feeds.megaphone.fm/recodedecode" // tech)
## Matrix (chat) Live
(fromDb "feed.podbean.com/matrixlive/feed.xml" // tech)
## Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232>
(fromDb "rss.art19.com/your-welcome" // pol)
];
texts = [
# AGGREGATORS (> 1 post/day)
(fromDb "lesswrong.com" // rat)
(fromDb "econlib.org" // pol)
# AGGREGATORS (< 1 post/day)
(mkText "https://palladiummag.com/feed" // uncat // weekly)
(mkText "https://profectusmag.com/feed" // uncat // weekly)
(mkText "https://semiaccurate.com/feed" // tech // weekly)
(mkText "https://linuxphoneapps.org/blog/atom.xml" // tech // infrequent)
(mkText "https://spectrum.ieee.org/rss" // tech // weekly)
## No Moods, Ads or Cutesy Fucking Icons
(mkText "https://www.rifters.com/crawl/?feed=rss2" // uncat // weekly)
# DEVELOPERS
(fromDb "uninsane.org" // tech)
(fromDb "mg.lol" // tech)
## Ken Shirriff
(fromDb "righto.com" // tech)
## Vitalik Buterin
(mkText "https://vitalik.ca/feed.xml" // tech // infrequent)
## ian (Sanctuary)
(mkText "https://sagacioussuricata.com/feed.xml" // tech // infrequent)
## Bunnie Juang
(mkText "https://www.bunniestudios.com/blog/?feed=rss2" // tech // infrequent)
(mkText "https://blog.danieljanus.pl/atom.xml" // tech // infrequent)
(mkText "https://ianthehenry.com/feed.xml" // tech // infrequent)
(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
(fromDb "edwardsnowden.substack.com" // pol // text)
(mkText "http://benjaminrosshoffman.com/feed" // pol // weekly)
## Ben Thompson
(mkText "https://www.stratechery.com/rss" // pol // weekly)
## Balaji
(mkText "https://balajis.com/rss" // pol // weekly)
(mkText "https://www.ben-evans.com/benedictevans/rss.xml" // pol // weekly)
(mkText "https://www.lynalden.com/feed" // pol // infrequent)
(mkText "https://austinvernon.site/rss.xml" // tech // infrequent)
(mkSubstack "oversharing" // pol // daily)
(mkSubstack "doomberg" // tech // weekly)
## David Rosenthal
(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)
(mkText "https://unintendedconsequenc.es/feed" // rat // infrequent)
(mkText "https://applieddivinitystudies.com/atom.xml" // rat // weekly)
(mkText "https://slimemoldtimemold.com/feed.xml" // rat // weekly)
(mkText "https://www.richardcarrier.info/feed" // rat // weekly)
(mkText "https://www.gwern.net/feed.xml" // uncat // infrequent)
## Jason Crawford
(mkText "https://rootsofprogress.org/feed.xml" // rat // weekly)
## Robin Hanson
(mkText "https://www.overcomingbias.com/feed" // rat // daily)
## Scott Alexander
(mkSubstack "astralcodexten" // rat // daily)
## Paul Christiano
(mkText "https://sideways-view.com/feed" // rat // infrequent)
## 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)
];
images = [
(mkImg "https://www.smbc-comics.com/comic/rss" // humor // daily)
(mkImg "https://xkcd.com/atom.xml" // humor // daily)
(mkImg "https://pbfcomics.com/feed" // humor // infrequent)
# (mkImg "http://dilbert.com/feed" // humor // daily)
# ART
(mkImg "https://miniature-calendar.com/feed" // art // daily)
];
in
{
sane.feeds = texts ++ images ++ podcasts;
assertions = builtins.map
(p: {
assertion = p.format or "unknown" == "podcast";
message = ''${p.url} is not a podcast: ${p.format or "unknown"}'';
})
podcasts;
}

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

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

60
hosts/common/ids.nix Normal file
View File

@@ -0,0 +1,60 @@
{ ... }:
{
# legacy servo users, some are inconvenient to migrate
sane.ids.dhcpcd.gid = 991;
sane.ids.dhcpcd.uid = 992;
sane.ids.gitea.gid = 993;
sane.ids.git.uid = 994;
sane.ids.jellyfin.gid = 994;
sane.ids.pleroma.gid = 995;
sane.ids.jellyfin.uid = 996;
sane.ids.acme.gid = 996;
sane.ids.pleroma.uid = 997;
sane.ids.acme.uid = 998;
# greetd (used by sway)
sane.ids.greeter.uid = 999;
sane.ids.greeter.gid = 999;
# new servo users
sane.ids.freshrss.uid = 2401;
sane.ids.freshrss.gid = 2401;
sane.ids.mediawiki.uid = 2402;
sane.ids.colin.uid = 1000;
sane.ids.guest.uid = 1100;
# found on all hosts
sane.ids.sshd.uid = 2001; # 997
sane.ids.sshd.gid = 2001; # 997
sane.ids.polkituser.gid = 2002; # 998
sane.ids.systemd-coredump.gid = 2003; # 996
sane.ids.nscd.uid = 2004;
sane.ids.nscd.gid = 2004;
sane.ids.systemd-oom.uid = 2005;
sane.ids.systemd-oom.gid = 2005;
# found on graphical hosts
sane.ids.nm-iodine.uid = 2101; # desko/moby/lappy
# found on desko host
# from services.usbmuxd
sane.ids.usbmux.uid = 2204;
sane.ids.usbmux.gid = 2204;
# originally found on moby host
# gnome core-shell
sane.ids.avahi.uid = 2304;
sane.ids.avahi.gid = 2304;
sane.ids.colord.uid = 2305;
sane.ids.colord.gid = 2305;
sane.ids.geoclue.uid = 2306;
sane.ids.geoclue.gid = 2306;
# gnome core-os-services
sane.ids.rtkit.uid = 2307;
sane.ids.rtkit.gid = 2307;
# phosh
sane.ids.feedbackd.gid = 2308;
}

View File

@@ -1,11 +1,16 @@
{ ... }:
{
# we wan't an /etc/machine-id which is consistent across boot so that `journalctl` will actually show us
# logs from previous boots.
# maybe there's a config option for this (since persistent machine-id is bad for reasons listed in impermanence.nix),
# but for now generate it from ssh keys.
# /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 = [ "persist-ssh-host-keys" ];
deps = [ "etc" ];
text = "sha256sum /etc/ssh/host_keys/ssh_host_ed25519_key | cut -c 1-32 > /etc/machine-id";
};
}

View File

@@ -31,49 +31,13 @@
General.RoamThreshold5G = "-52"; # default -76
};
# TODO: don't need to depend on binsh if we were to use a nix-style shebang
system.activationScripts.linkIwdKeys = let
unwrapped = ../../scripts/install-iwd;
install-iwd = pkgs.writeShellApplication {
name = "install-iwd";
runtimeInputs = with pkgs; [ coreutils gnused ];
text = ''${unwrapped} "$@"'';
};
in (lib.stringAfter
[ "setupSecrets" "binsh" ]
''
mkdir -p /var/lib/iwd
${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";
sane.fs."/var/lib/iwd/.secrets.psk.stamp" = {
wantedBeforeBy = [ "iwd.service" ];
generated.acl.mode = "0600";
# XXX: install-iwd uses sed, but that's part of the default systemd unit path, it seems
generated.script.script = builtins.readFile ../../scripts/install-iwd + ''
touch "/var/lib/iwd/.secrets.psk.stamp"
'';
generated.script.scriptArgs = [ "/run/secrets/iwd" "/var/lib/iwd" ];
};
}

View File

@@ -33,10 +33,6 @@
# 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;
# This will automatically import SSH keys as age keys
sops.age.sshKeyPaths = [
"/etc/ssh/host_keys/ssh_host_ed25519_key"
];
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";
@@ -48,6 +44,81 @@
# 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";
};
}

View File

@@ -1,21 +1,24 @@
{ ... }:
{ config, lib, sane-data, sane-lib, ... }:
{
# we place the host keys (which we want to be persisted) into their own directory so that we can
# bind mount that whole directory instead of doing it per-file.
# otherwise, this is identical to nixos defaults
sane.impermanence.service-dirs = [ "/etc/ssh/host_keys" ];
sane.ssh.pubkeys =
let
# path is a DNS-style path like [ "org" "uninsane" "root" ]
keyNameForPath = path:
let
rev = lib.reverseList path;
name = builtins.head rev;
host = lib.concatStringsSep "." (builtins.tail rev);
in
"${name}@${host}";
# we can't naively `mount /etc/ssh/host_keys` directly,
# as /etc/fstab may not be populated yet (since that file depends on e.g. activationScripts.users)
# we can't even depend on impermanence's `createPersistentStorageDirs` to create the source/target directories
# since that also depends on `users`.
system.activationScripts.persist-ssh-host-keys.text = ''
mkdir -p /etc/ssh/host_keys
mount --bind /nix/persist/etc/ssh/host_keys /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"; }
];
# [{ path :: [String], value :: String }] for the keys we want to install
globalKeys = sane-lib.flattenAttrs sane-data.keys;
localKeys = sane-lib.flattenAttrs sane-data.keys.org.uninsane.local;
in lib.mkMerge (builtins.map
({ path, value }: {
"${keyNameForPath path}" = value;
})
(globalKeys ++ localKeys)
);
}

View File

@@ -1,13 +1,10 @@
{ config, pkgs, lib, ... }:
{ config, pkgs, lib, sane-lib, ... }:
# installer docs: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/installation-device.nix
with lib;
let
cfg = config.sane.users;
# see nixpkgs/nixos/modules/services/networking/dhcpcd.nix
hasDHCP = config.networking.dhcpcd.enable &&
(config.networking.useDHCP || any (i: i.useDHCP == true) (attrValues config.networking.interfaces));
fs = sane-lib.fs;
in
{
options = {
@@ -27,7 +24,8 @@ in
# sets group to "users" (?)
isNormalUser = true;
home = "/home/colin";
uid = config.sane.allocations.colin-uid;
createHome = true;
homeMode = "0700";
# 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.
subUidRanges = [
@@ -50,36 +48,66 @@ in
passwordFile = lib.mkIf (config.sops.secrets ? "colin-passwd") config.sops.secrets.colin-passwd.path;
shell = pkgs.zsh;
openssh.authorizedKeys.keys = builtins.attrValues (import ../../modules/pubkeys.nix).users;
pamMount = {
# mount encrypted stuff at login
# requires that login password == fs encryption password
# fstype = "fuse";
# path = "${pkgs.gocryptfs}/bin/gocryptfs#/nix/persist/home/colin/private";
fstype = "fuse.gocryptfs";
path = "/nix/persist/home/colin/private";
mountpoint = "/home/colin/private";
options="nodev,nosuid,quiet,allow_other";
# mount encrypted stuff at login
# 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 = let
priv = config.fileSystems."/home/colin/private";
in {
fstype = priv.fsType;
path = priv.device;
mountpoint = priv.mountPoint;
options = builtins.concatStringsSep "," priv.options;
};
};
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"
security.pam.mount.enable = true;
# ensure ~ perms are known to sane.fs module.
# TODO: this is generic enough to be lifted up into sane.fs itself.
sane.fs."/home/colin".dir.acl = {
user = "colin";
group = config.users.users.colin.group;
mode = config.users.users.colin.homeMode;
};
sane.persist.home.plaintext = [
"archive"
"dev"
# TODO: records should be private
"records"
"ref"
"tmp"
"use"
"Music"
"Pictures"
"Videos"
".cache/nix"
".cargo"
".rustup"
".local/share/keyrings"
];
sane.impermanence.service-dirs = mkIf cfg.guest.enable [
{ user = "guest"; group = "users"; directory = "/home/guest"; }
# convenience
sane.fs."/home/colin/knowledge" = fs.wantedSymlinkTo "/home/colin/private/knowledge";
sane.fs."/home/colin/nixos" = fs.wantedSymlinkTo "/home/colin/dev/nixos";
sane.fs."/home/colin/Videos/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Videos";
sane.fs."/home/colin/Videos/servo-incomplete" = fs.wantedSymlinkTo "/mnt/servo-media/incomplete";
sane.fs."/home/colin/Music/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Music";
# used by password managers, e.g. unix `pass`
sane.fs."/home/colin/.password-store" = fs.wantedSymlinkTo "/home/colin/knowledge/secrets/accounts";
sane.persist.sys.plaintext = mkIf cfg.guest.enable [
# intentionally allow other users to write to the guest folder
{ directory = "/home/guest"; user = "guest"; group = "users"; mode = "0775"; }
];
users.users.guest = mkIf cfg.guest.enable {
isNormalUser = true;
home = "/home/guest";
uid = config.sane.allocations.guest-uid;
subUidRanges = [
{ startUid=200000; count=1; }
];
@@ -91,13 +119,6 @@ in
];
};
users.users.dhcpcd = mkIf hasDHCP {
uid = config.sane.allocations.dhcpcd-uid;
};
users.groups.dhcpcd = mkIf hasDHCP {
gid = config.sane.allocations.dhcpcd-gid;
};
security.sudo = {
enable = true;
wheelNeedsPassword = false;
@@ -108,31 +129,5 @@ in
permitRootLogin = "no";
passwordAuthentication = false;
};
# affix some UIDs which were historically auto-generated
users.users.sshd.uid = config.sane.allocations.sshd-uid;
users.groups.polkituser.gid = config.sane.allocations.polkituser-gid;
users.groups.sshd.gid = config.sane.allocations.sshd-gid;
users.groups.systemd-coredump.gid = config.sane.allocations.systemd-coredump-gid;
users.users.nscd.uid = config.sane.allocations.nscd-uid;
users.groups.nscd.gid = config.sane.allocations.nscd-gid;
users.users.systemd-oom.uid = config.sane.allocations.systemd-oom-uid;
users.groups.systemd-oom.gid = config.sane.allocations.systemd-oom-gid;
# guarantee determinism in uid/gid generation for users:
assertions = let
uidAssertions = builtins.attrValues (builtins.mapAttrs (name: user: {
assertion = user.uid != null;
message = "non-deterministic uid detected for: ${name}";
}) config.users.users);
gidAssertions = builtins.attrValues (builtins.mapAttrs (name: group: {
assertion = group.gid != null;
message = "non-deterministic gid detected for: ${name}";
}) config.users.groups);
autoSubAssertions = builtins.attrValues (builtins.mapAttrs (name: user: {
assertion = !user.autoSubUidGidRange;
message = "non-deterministic subUids/Guids detected for: ${name}";
}) config.users.users);
in uidAssertions ++ gidAssertions ++ autoSubAssertions;
};
}

View File

@@ -1,58 +1,66 @@
{ config, ... }:
{ config, lib, ... }:
{
networking.wg-quick.interfaces.ovpnd-us = {
# 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"
];
dns = [
"46.227.67.134"
"192.165.9.158"
})
# 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"
];
peers = [
{
allowedIPs = [
"0.0.0.0/0"
"::/0"
];
endpoint = "vpn31.prd.losangeles.ovpn.com:9929";
publicKey = "VW6bEWMOlOneta1bf6YFE25N/oMGh1E1UFBCfyggd0k=";
}
})
(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"
];
privateKeyFile = config.sops.secrets.wg_ovpnd_us_privkey.path;
# to start: `systemctl start wg-quick-ovpnd-us`
autostart = false;
};
networking.wg-quick.interfaces.ovpnd-ukr = {
})
(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"
];
dns = [
"46.227.67.134"
"192.165.9.158"
];
peers = [
{
allowedIPs = [
"0.0.0.0/0"
"::/0"
];
endpoint = "vpn96.prd.kyiv.ovpn.com:9929";
publicKey = "CjZcXDxaaKpW8b5As1EcNbI6+42A6BjWahwXDCwfVFg=";
}
];
privateKeyFile = config.sops.secrets.wg_ovpnd_ukr_privkey.path;
# to start: `systemctl start wg-quick-ovpnd-ukr`
autostart = false;
};
sops.secrets."wg_ovpnd_us_privkey" = {
sopsFile = ../../secrets/universal.yaml;
};
sops.secrets."wg_ovpnd_ukr_privkey" = {
sopsFile = ../../secrets/universal.yaml;
};
}
})
]

View File

@@ -10,21 +10,22 @@
sane.services.duplicity.enable = true;
sane.services.nixserve.enable = true;
sane.services.nixserve.sopsFile = ../../secrets/desko.yaml;
sane.impermanence.enable = true;
sane.persist.enable = true;
boot.loader.efi.canTouchEfiVariables = false;
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
# needed to use libimobiledevice/ifuse, for iphone sync
services.usbmuxd.enable = true;
users.users.usbmux.uid = config.sane.allocations.usbmux-uid;
users.groups.usbmux.gid = config.sane.allocations.usbmux-gid;
sops.secrets.colin-passwd = {
sopsFile = ../../secrets/desko.yaml;
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
@@ -49,7 +50,7 @@
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
};
sane.impermanence.home-dirs = [
sane.persist.home.plaintext = [
".steam"
".local/share/Steam"
];

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.persist.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" = {

View File

@@ -1,10 +1,23 @@
# trampoline from flake.nix into the specific host definition, while doing a tiny bit of common setup
hostName: { ... }: {
{ hostName, localSystem }:
{ ... }:
{
imports = [
./${hostName}
./common
];
networking.hostName = hostName;
nixpkgs.overlays = [
(next: prev: {
# for local != target we by default just emulate the target while building.
# provide a `pkgs.cross.<pkg>` alias that consumers can use instead of `pkgs.<foo>`
# to explicitly opt into non-emulated cross compilation for any specific package.
# this is most beneficial for large packages with few pre-requisites -- like Linux.
cross = next.crossFrom."${localSystem}";
})
];
}

View File

@@ -8,7 +8,7 @@
# sane.users.guest.enable = true;
sane.gui.sway.enable = true;
sane.impermanence.enable = true;
sane.persist.enable = true;
sane.nixcache.enable = true;
boot.loader.efi.canTouchEfiVariables = false;
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];

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.persist.root-on-tmpfs = true;
# we need a /tmp of default size (half RAM) for building large nix things
fileSystems."/tmp" = {
device = "none";

View File

@@ -1,4 +1,4 @@
{ config, pkgs, lib, mobile-nixos, ... }:
{ config, pkgs, lib, ... }:
{
imports = [
./firmware.nix
@@ -24,8 +24,9 @@
};
# usability compromises
sane.impermanence.home-dirs = [
config.sane.web-browser.dotDir
sane.web-browser.persistCache = "private";
sane.web-browser.persistData = "private";
sane.persist.home.plaintext = [
".config/pulse" # persist pulseaudio volume
];
@@ -35,12 +36,14 @@
];
sane.nixcache.enable = true;
sane.impermanence.enable = true;
sane.persist.enable = true;
sane.gui.phosh.enable = true;
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.persist.root-on-tmpfs = true;
fileSystems."/nix" = {
device = "/dev/disk/by-uuid/1f1271f8-53ce-4081-8a29-60a4a6b5d6f9";
fsType = "btrfs";

View File

@@ -125,6 +125,9 @@ in
# aarch64-unknown-linux-gnu-gcc: error: unrecognized command line option '-mfpu=neon'
# make[3]: *** [../scripts/Makefile.build:289: drivers/video/fbdev/sun5i-eink-neon.o] Error 1
FB_SUN5I_EINK = no;
# used by the pinephone pro, but fails to compile with:
# ../drivers/media/i2c/ov8858.c:1834:27: error: implicit declaration of function 'compat_ptr'
VIDEO_OV8858 = no;
})
))
];

View File

@@ -8,9 +8,6 @@
boot.loader.efi.canTouchEfiVariables = false;
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
users.users.dhcpcd.uid = config.sane.allocations.dhcpcd-uid;
users.groups.dhcpcd.gid = config.sane.allocations.dhcpcd-gid;
# docs: https://nixos.org/manual/nixos/stable/options.html#opt-system.stateVersion
system.stateVersion = "21.05";
}

View File

@@ -13,10 +13,9 @@
pkgs.matrix-synapse
pkgs.freshrss
];
sane.impermanence.enable = true;
sane.persist.enable = true;
sane.services.dyn-dns.enable = true;
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade
sane.services.nixserve.enable = true;
sane.services.nixserve.sopsFile = ../../secrets/servo.yaml;
boot.loader.efi.canTouchEfiVariables = false;
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];

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.persist.root-on-tmpfs = true;
# we need a /tmp for building large nix things
fileSystems."/tmp" = {
device = "none";
@@ -36,7 +27,7 @@
};
# slow, external storage (for archiving, etc)
fileSystems."/nix/persist/ext" = {
fileSystems."/mnt/persist/ext" = {
device = "/dev/disk/by-uuid/aa272cff-0fcc-498e-a4cb-0d95fb60631b";
fsType = "btrfs";
options = [
@@ -45,27 +36,31 @@
];
};
sane.impermanence.service-dirs = [
sane.persist.stores."ext" = {
origin = "/mnt/persist/ext/persist";
storeDescription = "external HDD storage";
};
sane.fs."/mnt/persist/ext".mount = {};
sane.persist.sys.plaintext = [
# 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";
})
];
};
# make sure large media is stored to the HDD
sane.persist.sys.ext = [
{
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 = {

View File

@@ -13,83 +13,155 @@
# networking.firewall.enable = false;
networking.firewall.enable = true;
# TODO: split these into the submodules
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
# 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"
];
# 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"
];
# 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 = {
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
# 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";
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
'';
};
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
'';
};
};
# 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;

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,6 +1,7 @@
{ ... }:
{
imports = [
./ddns-afraid.nix
./ddns-he.nix
./ejabberd.nix
./freshrss.nix
@@ -9,13 +10,17 @@
./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

@@ -1,84 +1,395 @@
# 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>
{ lib, ... }:
#
# compliance tests:
# - <https://compliance.conversations.im/server/uninsane.org/#xep0352>
{ config, lib, pkgs, ... }:
# XXX disabled: fails to start because of `mnesia_tm` dependency
# XXX: avatar support works in MUCs but not DMs
# lib.mkIf false
{
sane.impermanence.service-dirs = [
sane.persist.sys.plaintext = [
{ user = "ejabberd"; group = "ejabberd"; directory = "/var/lib/ejabberd"; }
];
networking.firewall.allowedTCPPorts = [
5222 # XMPP client -> server
5269 # XMPP server -> server
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
# TODO: this should just be `acme`. then we also add nginx to the `acme` group.
# why is /var/lib/acme/* owned by `nginx` group??
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 = builtins.toFile "ejabberd.yaml" ''
hosts:
- uninsane.org
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
# none | emergency | alert | critical | error | warning | notice | info | debug
loglevel: debug
# loglevel: info
# loglevel: notice
acme:
auto: false
certfiles:
- /var/lib/acme/uninsane.org/fullchain.pem
- /var/lib/acme/uninsane.org/key.pem
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
pam_userinfotype: jid
# docs: <https://docs.ejabberd.im/admin/configuration/basic/#shaper-rules>
shaper_rules:
max_s2s_connections: 3
max_user_offline_messages: 5000
c2s_shaper:
fast: all
s2s_shaper:
med: all
acl:
admin:
user:
- "colin@uninsane.org"
local:
user_regexp: ""
loopback:
ip:
- 127.0.0.0/8
- ::1/128
# 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
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
# see: <https://docs.ejabberd.im/admin/configuration/listen/>
# TODO: host web admin panel
s2s_use_starttls: true
listen:
-
port: 5222
module: ejabberd_c2s
shaper: c2s_shaper
starttls: true
-
port: 5269
module: ejabberd_s2s_in
shaper: s2s_shaper
-
port: 5280
module: ejabberd_http
request_handlers:
/admin: ejabberd_web_admin
/api: mod_http_api
/bosh: mod_bosh
/upload: mod_http_upload
/ws: ejabberd_http_ws
# 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

@@ -9,19 +9,17 @@
# $ sudo -u freshrss -g freshrss FRESHRSS_DATA_PATH=/var/lib/freshrss ./result/cli/export-opml-for-user.php --user admin
# ```
{ config, lib, pkgs, ... }:
{ config, lib, pkgs, sane-lib, ... }:
{
sops.secrets.freshrss_passwd = {
sopsFile = ../../../secrets/servo.yaml;
owner = config.users.users.freshrss.name;
mode = "400";
mode = "0400";
};
sane.impermanence.service-dirs = [
sane.persist.sys.plaintext = [
{ user = "freshrss"; group = "freshrss"; directory = "/var/lib/freshrss"; }
];
users.users.freshrss.uid = config.sane.allocations.freshrss-uid;
users.groups.freshrss.gid = config.sane.allocations.freshrss-gid;
services.freshrss.enable = true;
services.freshrss.baseUrl = "https://rss.uninsane.org";
services.freshrss.virtualHost = "rss.uninsane.org";
@@ -29,9 +27,11 @@
systemd.services.freshrss-import-feeds =
let
feeds = sane-lib.feeds;
fresh = config.systemd.services.freshrss-config;
feeds = import ../../../modules/home-manager/feeds.nix { inherit lib; };
opml = pkgs.writeText "sane-freshrss.opml" (feeds.feedsToOpml feeds.all);
all-feeds = config.sane.feeds;
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
opml = pkgs.writeText "sane-freshrss.opml" (feeds.feedsToOpml wanted-feeds);
in {
inherit (fresh) wantedBy environment;
serviceConfig = {
@@ -49,4 +49,13 @@
# 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,11 +1,10 @@
{ config, pkgs, lib, ... }:
{
sane.impermanence.service-dirs = [
sane.persist.sys.plaintext = [
# TODO: mode? could be more granular
{ user = "git"; group = "gitea"; directory = "/var/lib/gitea"; }
];
users.groups.gitea.gid = config.sane.allocations.gitea-gid;
services.gitea.enable = true;
services.gitea.user = "git"; # default is 'gitea'
services.gitea.database.type = "postgres";
@@ -72,4 +71,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

@@ -25,6 +25,7 @@
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
Type = "simple";
Restart = "on-failure";
RestartSec = "10s";
# hardening
WorkingDirectory = "/tmp";
@@ -42,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

@@ -10,10 +10,32 @@
lib.mkIf false # i don't actively use ipfs anymore
{
sane.impermanence.service-dirs = [
sane.persist.sys.plaintext = [
# 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.settings = {

View File

@@ -1,18 +1,32 @@
{ ... }:
{
sane.impermanence.service-dirs = [
sane.persist.sys.plaintext = [
# 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

@@ -1,14 +1,67 @@
{ config, ... }:
{ config, lib, ... }:
# TODO: re-enable after migrating media dir to /var/lib/uninsane/media
# else it's too spammy
lib.mkIf false
{
sane.impermanence.service-dirs = [
networking.firewall.allowedUDPPorts = [
1900 7359 # DLNA: https://jellyfin.org/docs/general/networking/index.html
];
sane.persist.sys.plaintext = [
# 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;
# 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";
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.persist.sys.plaintext = [
{ 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.persist.sys.plaintext = [
{ 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.persist.sys.plaintext = [
# TODO: mode?
# user and group are both "matrix-appservice-irc"
{ user = "993"; group = "992"; directory = "/var/lib/matrix-appservice-irc"; }

View File

@@ -1,8 +1,11 @@
{ ... }:
{
sane.impermanence.service-dirs = [
{ user = "navidrome"; group = "navidrome"; directory = "/var/lib/private/navidrome"; }
sane.persist.sys.plaintext = [
# TODO: we don't have a static user allocated for navidrome!
# the chown would happen too early for us to set static perms
"/var/lib/private/navidrome"
# { user = "navidrome"; group = "navidrome"; directory = "/var/lib/private/navidrome"; }
];
services.navidrome.enable = true;
services.navidrome.settings = {
@@ -14,4 +17,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

@@ -1,17 +1,20 @@
# docs: https://nixos.wiki/wiki/Nginx
{ config, pkgs, ... }:
{ config, lib, pkgs, ... }:
let
# make the logs for this host "public" so that they show up in e.g. metrics
publog = vhost: vhost // {
publog = vhost: lib.attrsets.unionOfDisjoint vhost {
extraConfig = (vhost.extraConfig or "") + ''
access_log /var/log/nginx/public.log vcombined;
'';
};
kTLS = true; # in-kernel TLS for better perf
# 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.
@@ -45,7 +48,7 @@ in
# and things don't look right. so force SSL.
forceSSL = true;
enableACME = true;
inherit kTLS;
# inherit kTLS;
# for OCSP stapling
sslTrustedCertificate = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
@@ -93,246 +96,6 @@ in
# };
};
# 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;
'';
};
};
# Pleroma server and web interface
services.nginx.virtualHosts."fed.uninsane.org" = publog {
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;
'';
};
};
# 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";
};
};
# 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";
};
};
# matrix chat server
services.nginx.virtualHosts."matrix.uninsane.org" = publog {
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";
};
};
};
};
# hosted git (web view and for `git <cmd>` use
services.nginx.virtualHosts."git.uninsane.org" = publog {
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";
};
};
# 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;
'';
};
};
services.nginx.virtualHosts."music.uninsane.org" = {
forceSSL = true;
enableACME = true;
inherit kTLS;
locations."/".proxyPass = "http://127.0.0.1:4533";
};
services.nginx.virtualHosts."rss.uninsane.org" = {
addSSL = true;
enableACME = true;
inherit kTLS;
# 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;
inherit kTLS;
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;
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;
'';
};
# serve any site not listed above, if it's static.
# because we define it dynamically, SSL isn't trivial. support only http
@@ -357,14 +120,34 @@ in
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 = [
sane.persist.sys.plaintext = [
# 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.

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

@@ -6,12 +6,10 @@
{ config, pkgs, ... }:
{
sane.impermanence.service-dirs = [
sane.persist.sys.plaintext = [
# TODO: mode? could be more granular
{ user = "pleroma"; group = "pleroma"; directory = "/var/lib/pleroma"; }
];
users.users.pleroma.uid = config.sane.allocations.pleroma-uid;
users.groups.pleroma.gid = config.sane.allocations.pleroma-gid;
services.pleroma.enable = true;
services.pleroma.secretConfigFile = config.sops.secrets.pleroma_secrets.path;
services.pleroma.configs = [
@@ -127,6 +125,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 = {
@@ -136,6 +135,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.persist.sys.plaintext = [
# 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.persist.sys.plaintext = [
# TODO: mode?
{ user = "postgres"; group = "postgres"; directory = "/var/lib/postgresql"; }
];

View File

@@ -1,3 +1,5 @@
# example configs:
# - <https://github.com/kittywitch/nixfiles/blob/main/services/prosody.nix>
# create users with:
# - `sudo -u prosody prosodyctl adduser colin@uninsane.org`
@@ -7,13 +9,13 @@
# nixnet runs ejabberd, so revisiting that.
lib.mkIf false
{
sane.impermanence.service-dirs = [
sane.persist.sys.plaintext = [
{ user = "prosody"; group = "prosody"; directory = "/var/lib/prosody"; }
];
networking.firewall.allowedTCPPorts = [
5222 # XMPP client -> server
5269 # XMPP server -> server
5280 # Prosody HTTP port (necessary?)
5280 # bosh
5281 # Prosody HTTPS port (necessary?)
];
@@ -34,7 +36,7 @@ lib.mkIf false
# c2s_require_encryption = true
# '';
# extraModules = [ "private" "vcard" "privacy" "compression" "component" "muc" "pep" "adhoc" "lastactivity" "admin_adhoc" "blocklist"];
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";
@@ -51,7 +53,7 @@ lib.mkIf false
domain = "localhost";
enabled = true;
};
"uninsane.org" = {
"xmpp.uninsane.org" = {
domain = "uninsane.org";
enabled = true;
ssl.cert = "/var/lib/acme/uninsane.org/fullchain.pem";

View File

@@ -1,7 +1,7 @@
{ ... }:
{ pkgs, ... }:
{
sane.impermanence.service-dirs = [
sane.persist.sys.plaintext = [
# 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,31 @@
# 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;
};
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

@@ -12,7 +12,6 @@
home = "/var/lib/gitea";
useDefaultShell = true;
group = "gitea";
uid = config.sane.allocations.git-uid;
isSystemUser = true;
# sendmail access (not 100% sure if this is necessary)
extraGroups = [ "postdrop" ];

View File

@@ -1,61 +0,0 @@
{ lib, ... }:
with lib;
let
mkId = id: mkOption {
default = id;
type = types.int;
};
in
{
options = {
# legacy servo users, some are inconvenient to migrate
sane.allocations.dhcpcd-gid = mkId 991;
sane.allocations.dhcpcd-uid = mkId 992;
sane.allocations.gitea-gid = mkId 993;
sane.allocations.git-uid = mkId 994;
sane.allocations.jellyfin-gid = mkId 994;
sane.allocations.pleroma-gid = mkId 995;
sane.allocations.jellyfin-uid = mkId 996;
sane.allocations.acme-gid = mkId 996;
sane.allocations.pleroma-uid = mkId 997;
sane.allocations.acme-uid = mkId 998;
sane.allocations.greeter-uid = mkId 999;
sane.allocations.greeter-gid = mkId 999;
sane.allocations.freshrss-uid = mkId 2401;
sane.allocations.freshrss-gid = mkId 2401;
sane.allocations.colin-uid = mkId 1000;
sane.allocations.guest-uid = mkId 1100;
# 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
sane.allocations.systemd-coredump-gid = mkId 2003; # 996
sane.allocations.nscd-uid = mkId 2004;
sane.allocations.nscd-gid = mkId 2004;
sane.allocations.systemd-oom-uid = mkId 2005;
sane.allocations.systemd-oom-gid = mkId 2005;
# found on graphical hosts
sane.allocations.nm-iodine-uid = mkId 2101; # desko/moby/lappy
# found on desko host
sane.allocations.usbmux-uid = mkId 2204;
sane.allocations.usbmux-gid = mkId 2204;
# originally found on moby host
sane.allocations.avahi-uid = mkId 2304;
sane.allocations.avahi-gid = mkId 2304;
sane.allocations.colord-uid = mkId 2305;
sane.allocations.colord-gid = mkId 2305;
sane.allocations.geoclue-uid = mkId 2306;
sane.allocations.geoclue-gid = mkId 2306;
sane.allocations.rtkit-uid = mkId 2307;
sane.allocations.rtkit-gid = mkId 2307;
sane.allocations.feedbackd-gid = mkId 2308;
};
}

12
modules/data/default.nix Normal file
View File

@@ -0,0 +1,12 @@
# this directory contains data of a factual nature.
# for example, public ssh keys, GPG keys, DNS-type name mappings.
#
# don't put things like fully-specific ~/.config files in here,
# even if they're "relatively unopinionated".
moduleArgs:
{
feeds = import ./feeds moduleArgs;
keys = import ./keys.nix;
}

View File

@@ -0,0 +1,51 @@
{ lib, ... }:
let
inherit (builtins) concatLists concatStringsSep foldl' fromJSON map readDir readFile;
inherit (lib) hasSuffix listToAttrs mapAttrsToList removeSuffix splitString;
# given a path to a .json file relative to sources, construct the best feed object we can.
# the .json file could be empty, in which case we make assumptions about the feed based
# on its fs path.
# Type: feedFromSourcePath :: String -> { name = String; value = feed; }
feedFromSourcePath = json-path:
assert hasSuffix "/default.json" json-path;
let
canonical-name = removeSuffix "/default.json" json-path;
default-url = "https://${canonical-name}";
feed-details = { url = default-url; } // (tryImportJson (./sources/${json-path}));
in { name = canonical-name; value = mkFeed feed-details; };
# TODO: for now, feeds are just ordinary Attrs.
# in the future, we'd like to set them up with an update script.
mkFeed = { url, ... }@details: details;
# return an AttrSet representing the json at the provided path,
# or {} if the path is empty.
tryImportJson = path:
let
as-str = readFile path;
in
if as-str == "" then
{}
else
fromJSON as-str;
sources = enumerateFilePaths ./sources;
# like `lib.listFilesRecursive` but does not mangle paths.
# Type: enumerateFilePaths :: path -> [String]
enumerateFilePaths = base:
concatLists (
mapAttrsToList
(name: type:
if type == "directory" then
# enumerate this directory and then prefix each result with the directory's name
map (e: "${name}/${e}") (enumerateFilePaths (base + "/${name}"))
else
[ name ]
)
(readDir base)
);
in
listToAttrs (map feedFromSourcePath sources)

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 1369733,
"content_type": "application/rss+xml; charset=utf-8",
"description": "Every company has a story. Learn the playbooks that built the worlds greatest companies — and how you can apply them as a founder, operator, or investor.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 173,
"last_seen": "2023-01-11T15:26:37.515527+00:00",
"last_updated": "2022-12-19T07:22:28+00:00",
"score": 18,
"self_url": "https://acquired.libsyn.com/rss",
"site_name": null,
"site_url": null,
"title": "Acquired",
"url": "https://acquired.libsyn.com/rss",
"velocity": 0.066,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 1030773,
"content_type": "application/rss+xml; charset=utf-8",
"description": "Industry veterans, degenerate gamblers & besties Chamath Palihapitiya, Jason Calacanis, David Sacks & David Friedberg cover all things economic, tech, political, social & poker.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 124,
"last_seen": "2023-01-11T12:44:53.606606+00:00",
"last_updated": "2023-01-06T10:51:00+00:00",
"score": 18,
"self_url": "https://allinchamathjason.libsyn.com/rss",
"site_name": "All-In with Chamath, Jason, Sacks & Friedberg",
"site_url": "https://allinchamathjason.libsyn.com",
"title": "All-In with Chamath, Jason, Sacks & Friedberg",
"url": "https://allinchamathjason.libsyn.com/rss",
"velocity": 0.12,
"version": "rss20"
}

View File

@@ -0,0 +1,23 @@
{
"bozo": 0,
"content_length": 13316,
"content_type": "application/rss+xml; charset=utf-8",
"description": "A podcast around the idea of creating a Civilizational Bootstrapper, a set of tools and technology that can be used to replicate the foundations of civilization along with itself.",
"favicon": null,
"hubs": [
"https://pubsubhubbub.appspot.com/"
],
"is_podcast": true,
"is_push": true,
"item_count": 6,
"last_seen": "2023-01-11T16:11:01.720399+00:00",
"last_updated": "2022-04-13T19:37:17+00:00",
"score": 22,
"self_url": "https://anchor.fm/s/34c7232c/podcast/rss",
"site_name": "Anchor",
"site_url": "https://anchor.fm",
"title": "Civboot",
"url": "https://anchor.fm/s/34c7232c/podcast/rss",
"velocity": 0.009,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 12669,
"content_type": "application/rss+xml; charset=utf-8",
"description": "The territory is a map of the map.",
"favicon": "http://benjaminrosshoffman.com/favicon.ico",
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 10,
"last_seen": "2023-01-11T12:32:52.176940+00:00",
"last_updated": "2023-01-09T04:33:31+00:00",
"score": -15,
"self_url": "http://benjaminrosshoffman.com/comments/feed/",
"site_name": "Compass Rose",
"site_url": "http://benjaminrosshoffman.com",
"title": "Comments for Compass Rose",
"url": "http://benjaminrosshoffman.com/comments/feed/",
"velocity": 0.312,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 56666,
"content_type": "application/rss+xml; charset=utf-8",
"description": "Cory Doctorow's Literary Works",
"favicon": "https://craphound.com/favicon.ico",
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 20,
"last_seen": "2023-01-11T12:55:10.545856+00:00",
"last_updated": "2022-12-12T14:46:35+00:00",
"score": 12,
"self_url": "https://craphound.com/feed/",
"site_name": "Cory Doctorow's craphound.com | Cory Doctorow's Literary Works",
"site_url": "https://craphound.com",
"title": "Cory Doctorow's craphound.com",
"url": "https://craphound.com/feed/",
"velocity": 0.069,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 227480,
"content_type": "application/xml; charset=utf-8",
"description": "True stories from the dark side of the Internet",
"favicon": "https://darknetdiaries.com/imgs/favicon.png",
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 131,
"last_seen": "2023-01-11T14:49:53.136566+00:00",
"last_updated": "2022-12-27T08:00:00+00:00",
"score": 20,
"self_url": "https://darknetdiaries.com/feedfree.xml",
"site_name": "Darknet Diaries True stories from the dark side of the Internet.",
"site_url": "https://darknetdiaries.com",
"title": "Darknet Diaries (ad free)",
"url": "https://darknetdiaries.com/feedfree.xml",
"velocity": 0.067,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 66775,
"content_type": "application/rss+xml; charset=utf-8",
"description": "The Library of Economics and Liberty",
"favicon": null,
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 10,
"last_seen": "2023-01-11T10:46:38.526754+00:00",
"last_updated": "2023-01-10T05:21:31+00:00",
"score": 14,
"self_url": "https://www.econlib.org/feed/",
"site_name": "Econlib",
"site_url": "https://www.econlib.org",
"title": "Econlib",
"url": "https://www.econlib.org/feed/",
"velocity": 2.549,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 27185,
"content_type": "application/rss+xml; charset=utf-8",
"description": "The Library of Economics and Liberty",
"favicon": null,
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 10,
"last_seen": "2023-01-11T13:05:47.318206+00:00",
"last_updated": "2023-01-09T11:30:25+00:00",
"score": 14,
"self_url": "https://www.econtalk.org/feed/",
"site_name": null,
"site_url": null,
"title": "EconTalk Podcast Econlib",
"url": "https://www.econtalk.org/feed",
"velocity": 0.143,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 429348,
"content_type": "application/rss+xml; charset=utf-8",
"description": "The world's most famous whistleblower writes from exile on the intersection of technology, humanity, and power.",
"favicon": "https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/2a7d3aa2-3c2f-4196-ab7c-31541be1272e/favicon.ico",
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 16,
"last_seen": "2023-01-11T12:32:02.320483+00:00",
"last_updated": "2022-09-20T13:03:59+00:00",
"score": 14,
"self_url": "https://edwardsnowden.substack.com/feed",
"site_name": "Continuing Ed — with Edward Snowden",
"site_url": "https://edwardsnowden.substack.com",
"title": "Continuing Ed — with Edward Snowden",
"url": "https://edwardsnowden.substack.com/feed",
"velocity": 0.032,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 281377,
"content_type": "text/xml; charset=utf-8",
"description": "Matrix Live, now as an audio podcast",
"favicon": "https://feed.podbean.com/favicon.ico",
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 100,
"last_seen": "2023-01-11T15:54:24.440541+00:00",
"last_updated": "2023-01-06T16:45:00+00:00",
"score": 18,
"self_url": "https://feed.podbean.com/matrixlive/feed.xml",
"site_name": null,
"site_url": "https://feed.podbean.com",
"title": "Matrix Live",
"url": "https://feed.podbean.com/matrixlive/feed.xml",
"velocity": 0.12,
"version": "rss20"
}

View File

@@ -0,0 +1,23 @@
{
"bozo": 0,
"content_length": 1600578,
"content_type": "application/xml; charset=utf-8",
"description": "Design is everywhere in our lives, perhaps most importantly in the places where we've just stopped noticing. 99% Invisible is a weekly exploration of the process and power of design and architecture. From award winning producer Roman Mars. Learn more at 99percentinvisible.org.",
"favicon": null,
"hubs": [
"https://simplecast.superfeedr.com/"
],
"is_podcast": true,
"is_push": true,
"item_count": 577,
"last_seen": "2023-01-11T15:25:01.536556+00:00",
"last_updated": "2023-01-10T23:46:05+00:00",
"score": 4,
"self_url": "https://feeds.simplecast.com/BqbsxVfO",
"site_name": null,
"site_url": null,
"title": "99% Invisible",
"url": "https://feeds.simplecast.com/BqbsxVfO",
"velocity": 0.128,
"version": "rss20"
}

View File

@@ -0,0 +1,23 @@
{
"bozo": 0,
"content_length": 1505641,
"content_type": "text/xml; charset=utf-8",
"description": "<p>Unusually in-depth conversations about the world's most pressing problems and what you can do to solve them.<br /></p>",
"favicon": null,
"hubs": [
"https://pubsubhubbub.appspot.com/"
],
"is_podcast": true,
"is_push": true,
"item_count": 181,
"last_seen": "2023-01-11T13:29:43.501516+00:00",
"last_updated": "2023-01-09T22:57:00+00:00",
"score": 14,
"self_url": "https://feeds.backtracks.fm/feeds/80000hours/80000-hours-podcast-with-rob-wiblin/feed.xml",
"site_name": null,
"site_url": null,
"title": "80,000 Hours Podcast with Rob Wiblin",
"url": "https://feeds.feedburner.com/80000HoursPodcast",
"velocity": 0.087,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 23712,
"content_type": "text/xml; charset=utf-8",
"description": "This isn't academic history (and Carlin isn't a historian) but the podcast's unique blend of high drama, masterful narration and Twilight Zone-style twists has entertained millions of listeners.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 13,
"last_seen": "2023-01-11T15:05:34.359948+00:00",
"last_updated": "2022-03-06T19:08:44+00:00",
"score": 2,
"self_url": "https://feeds.feedburner.com/dancarlin/history?format=xml",
"site_name": null,
"site_url": null,
"title": "Dan Carlin's Hardcore History",
"url": "https://feeds.feedburner.com/dancarlin/history",
"velocity": 0.005,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 62633,
"content_type": "text/xml; charset=utf-8",
"description": "Articles, speeches, stories and novels by an award-winning science fiction writer, read aloud in small regular chunks",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 20,
"last_seen": "2023-01-11T12:57:50.103797+00:00",
"last_updated": "2022-12-12T14:46:35+00:00",
"score": 4,
"self_url": "https://craphound.com/category/podcast/feed/",
"site_name": null,
"site_url": null,
"title": "Podcast Cory Doctorow's craphound.com",
"url": "https://feeds.feedburner.com/doctorow_podcast",
"velocity": 0.068,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 1315558,
"content_type": "text/xml; charset=utf-8",
"description": "Radiolab",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 150,
"last_seen": "2023-01-11T15:01:17.273650+00:00",
"last_updated": "2023-01-06T15:00:00+00:00",
"score": 4,
"self_url": "https://www.wnycstudios.org/feeds/series/podcasts",
"site_name": null,
"site_url": null,
"title": "Radiolab",
"url": "https://feeds.feedburner.com/radiolab",
"velocity": 0.139,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 2976783,
"content_type": "application/xml; charset=utf-8",
"description": "A business show about big ideas — and other problems.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 660,
"last_seen": "2023-01-11T15:51:13.652417+00:00",
"last_updated": "2023-01-10T10:00:00+00:00",
"score": 14,
"self_url": "https://feeds.megaphone.fm/recodedecode",
"site_name": null,
"site_url": null,
"title": "Decoder with Nilay Patel",
"url": "https://feeds.megaphone.fm/recodedecode",
"velocity": 0.24,
"version": "rss20"
}

View File

@@ -0,0 +1,23 @@
{
"bozo": 0,
"content_length": 2940192,
"content_type": "application/xml; charset=utf-8",
"description": "EconTalk: Conversations for the Curious is an award-winning weekly podcast hosted by Russ Roberts of Shalem College in Jerusalem and Stanford's Hoover Institution. The eclectic guest list includes authors, doctors, psychologists, historians, philosophers, economists, and more. Learn how the health care system really works, the serenity that comes from humility, the challenge of interpreting data, how potato chips are made, what it's like to run an upscale Manhattan restaurant, what caused the 2008 financial crisis, the nature of consciousness, and more. EconTalk has been taking the Monday out of Mondays since 2006. All 800+ episodes are available in the archive. Go to EconTalk.org for transcripts, related resources, and comments.",
"favicon": null,
"hubs": [
"https://simplecast.superfeedr.com/"
],
"is_podcast": true,
"is_push": true,
"item_count": 875,
"last_seen": "2023-01-11T14:31:49.308489+00:00",
"last_updated": "2023-01-09T11:30:00+00:00",
"score": 24,
"self_url": "https://feeds.simplecast.com/wgl4xEgL",
"site_name": null,
"site_url": null,
"title": "EconTalk",
"url": "https://feeds.simplecast.com/wgl4xEgL",
"velocity": 0.142,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 337440,
"content_type": "application/rss+xml; charset=utf-8",
"description": "A community blog devoted to refining the art of rationality",
"favicon": "https://res.cloudinary.com/lesswrong-2-0/image/upload/v1497915096/favicon_lncumn.ico",
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 10,
"last_seen": "2023-01-11T10:39:58.575828+00:00",
"last_updated": "2023-01-11T09:58:49+00:00",
"score": 32,
"self_url": "https://www.lesswrong.com/feed.xml?view=rss&karmaThreshold=2",
"site_name": "LessWrong",
"site_url": "https://www.lesswrong.com",
"title": "LessWrong",
"url": "https://www.lesswrong.com/feed.xml",
"velocity": 12.052,
"version": "rss20"
}

View File

@@ -0,0 +1,23 @@
{
"bozo": 0,
"content_length": 841679,
"content_type": "application/rss+xml; charset=utf-8",
"description": "Conversations about AI, science, technology, history, philosophy and the nature of intelligence, consciousness, love, and power.",
"favicon": "https://lexfridman.com/wordpress/wp-content/uploads/2017/06/cropped-lex-favicon-4-1-32x32.png",
"hubs": [
"https://pubsubhubbub.appspot.com/"
],
"is_podcast": true,
"is_push": true,
"item_count": 300,
"last_seen": "2023-01-11T12:40:59.343327+00:00",
"last_updated": "2022-12-29T17:35:50+00:00",
"score": 20,
"self_url": "https://lexfridman.com/feed/podcast/",
"site_name": "Lex Fridman",
"site_url": "https://lexfridman.com",
"title": "Lex Fridman Podcast",
"url": "https://lexfridman.com/feed/podcast/",
"velocity": 0.265,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 83074,
"content_type": "text/xml; charset=utf-8",
"description": "projects & research",
"favicon": null,
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 14,
"last_seen": "2023-01-11T12:28:34.383284+00:00",
"last_updated": "2021-07-29T05:10:05+00:00",
"score": 14,
"self_url": "https://mg.lol/blog/rss/",
"site_name": null,
"site_url": "https://mg.lol",
"title": "MG",
"url": "https://mg.lol/blog/rss/",
"velocity": 0.004,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 3568150,
"content_type": "application/rss+xml; charset=utf-8",
"description": "Post Reports",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 1070,
"last_seen": "2023-01-11T14:37:23.650030+00:00",
"last_updated": "2023-01-10T21:40:40+00:00",
"score": 14,
"self_url": "https://podcast.posttv.com/itunes/post-reports.xml",
"site_name": null,
"site_url": null,
"title": "Post Reports",
"url": "https://podcast.posttv.com/itunes/post-reports.xml",
"velocity": 0.711,
"version": "rss20"
}

View File

@@ -0,0 +1,23 @@
{
"bozo": 0,
"content_length": 862917,
"content_type": "application/atom+xml; charset=utf-8",
"description": "Computer history, restoring vintage computers, IC reverse engineering, and whatever",
"favicon": "https://www.blogger.com/about/favicon/favicon.ico",
"hubs": [
"http://pubsubhubbub.appspot.com/"
],
"is_podcast": false,
"is_push": true,
"item_count": 25,
"last_seen": "2023-01-11T12:29:19.820378+00:00",
"last_updated": "2023-01-10T18:21:20.265000+00:00",
"score": -2,
"self_url": "https://www.blogger.com/feeds/6264947694886887540/posts/default",
"site_name": "Blogger.com - Create a unique and beautiful blog easily.",
"site_url": "https://www.blogger.com",
"title": "Ken Shirriff's blog",
"url": "https://www.blogger.com/feeds/6264947694886887540/posts/default",
"velocity": 0.12,
"version": "atom10"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 550915,
"content_type": "application/xml; charset=utf-8",
"description": "The show that looks at the way technology is changing our economies, societies and daily lives.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 160,
"last_seen": "2023-01-11T15:31:40.303733+00:00",
"last_updated": "2022-11-22T05:00:36+00:00",
"score": 10,
"self_url": "https://feeds.acast.com/public/shows/125ef5a6-6c61-4024-b70e-3487a971a26c",
"site_name": null,
"site_url": null,
"title": "FT Tech Tonic",
"url": "https://feeds.acast.com/public/shows/125ef5a6-6c61-4024-b70e-3487a971a26c",
"velocity": 0.072,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 1041745,
"content_type": "application/rss+xml; charset=utf-8",
"description": "<p>Get the best reporting and storytelling on television from 60 Minutes - on your schedule. Now you can listen to the show in its entirety every week. 60 Minutes is the most successful broadcast in television history with more than 80 Emmys under its belt. 60 Minutes offers unbiased reporting on politics, in-depth investigations and important adventures from around the world- like no one else. </p>",
"favicon": "https://rss.art19.com/favicon.ico",
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 374,
"last_seen": "2023-01-11T15:45:07.189940+00:00",
"last_updated": "2023-01-09T03:00:00+00:00",
"score": 18,
"self_url": "https://rss.art19.com/60-minutes",
"site_name": null,
"site_url": "https://rss.art19.com",
"title": "60 Minutes",
"url": "https://rss.art19.com/60-minutes",
"velocity": 0.082,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 235911,
"content_type": "application/xml; charset=utf-8",
"description": "<p>The Portal is an exploration into discovery, including conversations with thought leaders. Host Eric Weinstein, Managing Director of Thiel Capital, brings his unique expertise and diverse roster of guests for a wide range of discussions, including science, culture, business, and capitalism. The show will feature people whose lives demonstrate that portals into what we would normally consider impossible, are indeed possible.&nbsp;&nbsp;Guests include presidential candidate Andrew Yang, NY Times bestselling author Sam Harris, and retired Navy Seal and creator of the hit business podcast Jocko Willink.</p>",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 44,
"last_seen": "2023-01-11T14:47:44.995855+00:00",
"last_updated": "2020-12-02T07:50:55+00:00",
"score": -12,
"self_url": "https://www.omnycontent.com/d/playlist/9b7dacdf-a925-4f95-84dc-ac46003451ff/1713c520-edb6-43a3-b1b9-acb8002fdae7/58e33a0c-f86b-41c5-a11c-acb8002fdaf5/podcast.rss",
"site_name": null,
"site_url": null,
"title": "The Portal",
"url": "https://www.omnycontent.com/d/playlist/9b7dacdf-a925-4f95-84dc-ac46003451ff/1713c520-edb6-43a3-b1b9-acb8002fdae7/58e33a0c-f86b-41c5-a11c-acb8002fdaf5/podcast.rss",
"velocity": 0.082,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 1462485,
"content_type": "text/xml; charset=utf-8",
"description": "Michael Malice brings his unique perspective and plenty of sick burns as he discusses everything from north Korea to American politics and culture with a bevy of guests.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 238,
"last_seen": "2023-01-11T15:58:45.264936+00:00",
"last_updated": "2023-01-04T10:40:00+00:00",
"score": -10,
"self_url": "http://origin.podcastone.com/podcast?categoryID2=2232",
"site_name": null,
"site_url": null,
"title": "\"YOUR WELCOME\" with Michael Malice",
"url": "https://www.podcastone.com/podcast?categoryID2=2232",
"velocity": 0.141,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 809084,
"content_type": "application/xml+rss; charset=utf-8",
"description": "A show that cuts through all the political drivel and media misinformation to give you a straight take on one big news story of the week.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 217,
"last_seen": "2023-01-11T13:40:50.240217+00:00",
"last_updated": "2023-01-06T10:37:50+00:00",
"score": 16,
"self_url": "https://feeds.acast.com/public/shows/1d1223a2-9d05-473b-9e79-c2b65b71d676",
"site_name": null,
"site_url": null,
"title": "Deconstructed",
"url": "https://rss.prod.firstlook.media/deconstructed/podcast.rss",
"velocity": 0.122,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 1034995,
"content_type": "application/xml+rss; charset=utf-8",
"description": "The people behind The Intercepts fearless reporting and incisive commentary discuss the crucial issues of our time.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 243,
"last_seen": "2023-01-11T14:04:41.283509+00:00",
"last_updated": "2022-12-21T10:30:43+00:00",
"score": 16,
"self_url": "https://feeds.acast.com/public/shows/f5b64019-68c3-57d4-b70b-043e63e5cbf6",
"site_name": null,
"site_url": null,
"title": "Intercepted",
"url": "https://rss.prod.firstlook.media/intercepted/podcast.rss",
"velocity": 0.112,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 3905927,
"content_type": "application/rss+xml; charset=utf-8",
"description": "The official audio version of Astral Codex Ten, with an archive of posts from Slate Star Codex. It's just me reading Scott Alexander's blog posts.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 739,
"last_seen": "2023-01-11T11:05:40.604126+00:00",
"last_updated": "2023-01-11T05:13:00+00:00",
"score": 18,
"self_url": "https://sscpodcast.libsyn.com/rss",
"site_name": "Astral Codex Ten Podcast",
"site_url": "https://sscpodcast.libsyn.com",
"title": "Astral Codex Ten Podcast",
"url": "https://sscpodcast.libsyn.com/rss",
"velocity": 0.384,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 1,
"content_length": 178687,
"content_type": "text/xml; charset=utf-8",
"description": null,
"favicon": null,
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 6,
"last_seen": "2023-01-11T10:51:13.435393+00:00",
"last_updated": "2022-10-13T00:00:00+00:00",
"score": -4,
"self_url": "https://uninsane.org/atom.xml",
"site_name": "Perfectly Sane",
"site_url": "https://uninsane.org",
"title": "Perfectly Sane",
"url": "https://uninsane.org/atom.xml",
"velocity": 0.025,
"version": "atom10"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 825822,
"content_type": "application/rss+xml; charset=utf-8",
"description": "Join neuroscientist, philosopher, and best-selling author Sam Harris as he explores questions about the human mind, society, and current events.",
"favicon": null,
"hubs": [],
"is_podcast": true,
"is_push": false,
"item_count": 326,
"last_seen": "2023-01-11T15:13:28.154435+00:00",
"last_updated": "2023-01-05T18:36:25+00:00",
"score": 18,
"self_url": "https://wakingup.libsyn.com/rss",
"site_name": "Making Sense with Sam Harris",
"site_url": "https://wakingup.libsyn.com",
"title": "Making Sense with Sam Harris",
"url": "https://wakingup.libsyn.com/rss",
"velocity": 0.096,
"version": "rss20"
}

View File

@@ -0,0 +1,21 @@
{
"bozo": 0,
"content_length": 2302,
"content_type": "text/xml; charset=utf-8",
"description": null,
"favicon": "https://xkcd.com/s/919f27.ico",
"hubs": [],
"is_podcast": false,
"is_push": false,
"item_count": 4,
"last_seen": "2023-01-11T10:29:36.530001+00:00",
"last_updated": "2023-01-09T00:00:00+00:00",
"score": 16,
"self_url": null,
"site_name": "xkcd",
"site_url": "https://xkcd.com",
"title": "xkcd.com",
"url": "https://xkcd.com/atom.xml",
"velocity": 0.429,
"version": "atom10"
}

30
modules/data/keys.nix Normal file
View File

@@ -0,0 +1,30 @@
# hierarchical, DNS-like mapping from <name> => ssh host/user for that name.
# host keys are represented as user keys, just with the user specified as "root".
{
org.uninsane = rec {
root = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOfdSmFkrVT6DhpgvFeQKm3Fh9VKZ9DbLYOPOJWYQ0E8";
git.root = root;
local = {
# machine aliases i specify on my lan; not actually asserted as DNS
desko.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPU5GlsSfbaarMvDA20bxpSZGWviEzXGD8gtrIowc1pX";
desko.root = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFw9NoRaYrM6LbDd3aFBc4yyBlxGQn8HjeHd/dZ3CfHk";
lappy.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu";
lappy.root = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc";
moby.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrR+gePnl0nV/vy7I5BzrGeyVL+9eOuXHU1yNE3uCwU";
moby.root = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO1N/IT3nQYUD+dBlU1sTEEVMxfOyMkrrDeyHcYgnJvw";
servo.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPS1qFzKurAdB9blkWomq8gI1g0T3sTs9LsmFOj5VtqX";
servo.root = root;
};
};
com.github = rec {
# documented here: <https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints>
# Github actually uses multiple keys -- one per format
root = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl";
};
}

View File

@@ -1,14 +1,23 @@
{ ... }:
{ lib, utils, ... }:
{
imports = [
./allocations.nix
./feeds.nix
./fs
./gui
./home-manager
./ids.nix
./packages.nix
./image.nix
./impermanence.nix
./nixcache.nix
./persist
./services
./sops.nix
./ssh.nix
];
_module.args = {
sane-lib = import ./lib { inherit lib utils; };
sane-data = import ./data { inherit lib; };
};
}

55
modules/feeds.nix Normal file
View File

@@ -0,0 +1,55 @@
{ lib, sane-data, ... }:
with lib;
let
feed = types.submodule ({ config, ... }: {
options = {
freq = mkOption {
type = types.enum [ "hourly" "daily" "weekly" "infrequent" ];
default = "infrequent";
};
cat = mkOption {
type = types.enum [ "art" "humor" "pol" "rat" "tech" "uncat" ];
default = "uncat";
};
format = mkOption {
type = types.enum [ "text" "image" "podcast" ];
default = "text";
};
title = mkOption {
type = types.nullOr types.str;
default = null;
};
url = mkOption {
type = types.str;
description = ''
url to a RSS feed
'';
};
substack = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
if the feed is a substack domain, just enter the subdomain here and the url/format field can be populated automatically
'';
};
};
config = lib.mkIf (config.substack != null) {
url = "https://${config.substack}.substack.com/feed";
format = "text";
};
});
in
{
# we don't explicitly generate anything from the feeds here.
# instead, config.sane.feeds is used by a variety of services at their definition site.
options = {
sane.feeds = mkOption {
type = types.listOf feed;
default = [];
description = ''
RSS feeds indexed by a human-readable name.
'';
};
};
}

357
modules/fs/default.nix Normal file
View File

@@ -0,0 +1,357 @@
{ config, lib, pkgs, utils, sane-lib, ... }:
with lib;
let
path-lib = sane-lib.path;
sane-types = sane-lib.types;
cfg = config.sane.fs;
mountNameFor = path: "${utils.escapeSystemdPath path}.mount";
serviceNameFor = path: "ensure-${utils.escapeSystemdPath path}";
# sane.fs."<path>" top-level options
fsEntry = types.submodule ({ name, config, ...}: let
parent = path-lib.parent name;
has-parent = path-lib.hasParent name;
parent-cfg = if has-parent then cfg."${parent}" else {};
parent-acl = if has-parent then parent-cfg.generated.acl else {};
in {
options = {
dir = mkOption {
type = types.nullOr dirEntry;
default = null;
};
symlink = mkOption {
type = types.nullOr (symlinkEntryFor name);
default = null;
};
generated = mkOption {
type = generatedEntry;
default = {};
};
mount = mkOption {
type = types.nullOr (mountEntryFor name);
default = null;
};
wantedBy = mkOption {
type = types.listOf types.str;
default = [];
description = ''
list of units or targets which, when activated, should trigger this fs entry to be created.
'';
};
wantedBeforeBy = mkOption {
type = types.listOf types.str;
default = [];
description = ''
list of units or targets which, when activated, should first start and wait for this fs entry to be created.
if this unit fails, it will not block the targets in this list.
'';
};
unit = mkOption {
type = types.str;
description = "name of the systemd unit which ensures this entry";
};
};
config = let
default-acl = {
user = lib.mkDefault (parent-acl.user or "root");
group = lib.mkDefault (parent-acl.group or "root");
mode = lib.mkDefault (parent-acl.mode or "0755");
};
in {
# 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`).
generated.depends = if has-parent then [ parent-cfg.unit ] else [];
# populate generated items from `dir` or `symlink` shorthands
generated.acl = lib.mkMerge [
default-acl
(lib.mkIf (config.dir != null)
(sane-lib.filterNonNull config.dir.acl))
(lib.mkIf (config.symlink != null)
(sane-lib.filterNonNull config.symlink.acl))
];
# actually generate the item
generated.script = lib.mkMerge [
(lib.mkIf (config.dir != null) (ensureDirScript name config.dir))
(lib.mkIf (config.symlink != null) (ensureSymlinkScript name config.symlink))
];
# make the unit file which generates the underlying thing available so that `mount` can use it.
generated.unit = (serviceNameFor name) + ".service";
# if we were asked to mount, make sure we create the dir that we mount over
dir = lib.mkIf (config.mount != null) {};
# if defaulted, this module is responsible for finalizing the entry.
# the user could override this if, say, they finalize some aspect of the entry
# with a custom service.
unit = lib.mkDefault (
if config.mount != null then
config.mount.unit
else
config.generated.unit
);
};
});
# options which can be set in dir/symlink generated items,
# with intention that they just propagate down
propagatedGenerateMod = {
options = {
acl = mkOption {
type = sane-types.aclOverride;
default = {};
};
};
};
# sane.fs."<path>".dir sub-options
# takes no special options
dirEntry = types.submodule propagatedGenerateMod;
symlinkEntryFor = path: types.submodule ({ config, ...}: {
options = {
inherit (propagatedGenerateMod.options) acl;
target = mkOption {
type = types.coercedTo types.package toString types.str;
description = "fs path to link to";
};
text = mkOption {
type = types.nullOr types.str;
default = null;
description = "create a file in the /nix/store with the provided text and use that as the target";
};
};
config = {
target = lib.mkIf (config.text != null) (
pkgs.writeText (path-lib.leaf path) config.text
);
};
});
generatedEntry = types.submodule {
options = {
acl = mkOption {
type = sane-types.acl;
};
depends = mkOption {
type = types.listOf types.str;
description = ''
list of systemd units needed to be run before this item can be generated.
'';
default = [];
};
script.script = mkOption {
type = types.lines;
};
script.scriptArgs = mkOption {
type = types.listOf types.str;
default = [];
};
unit = mkOption {
type = types.str;
description = "name of the systemd unit which ensures this directory";
};
};
};
# sane.fs."<path>".mount sub-options
mountEntryFor = path: types.submodule {
options = {
bind = mkOption {
type = types.nullOr types.str;
description = "fs path to bind-mount from";
default = null;
};
depends = mkOption {
type = types.listOf types.str;
description = ''
list of systemd units needed to be run before this entry can be mounted
'';
default = [];
};
unit = mkOption {
type = types.str;
description = "name of the systemd unit which mounts this path";
default = mountNameFor path;
};
};
};
mkGeneratedConfig = path: opt: let
gen-opt = opt.generated;
wrapper = generateWrapperScript path gen-opt;
in {
systemd.services."${serviceNameFor path}" = {
description = "prepare ${path}";
serviceConfig.Type = "oneshot";
script = wrapper.script;
scriptArgs = builtins.concatStringsSep " " wrapper.scriptArgs;
after = gen-opt.depends;
wants = gen-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";
before = opt.wantedBeforeBy;
wantedBy = opt.wantedBy ++ opt.wantedBeforeBy;
};
};
# given a mountEntry definition, evaluate its toplevel `config` output.
mkMountConfig = path: opt: (let
device = config.fileSystems."${path}".device;
underlying = cfg."${device}";
isBind = opt.mount.bind != null;
ifBind = lib.mkIf isBind;
# before mounting:
# - create the target directory
# - prepare the source directory -- assuming it's not an external device
# - satisfy any user-specified prerequisites ("depends")
requires = [ opt.generated.unit ]
++ (if lib.hasPrefix "/dev/disk/" device then [] else [ underlying.unit ])
++ opt.mount.depends;
in {
fileSystems."${path}" = {
device = ifBind opt.mount.bind;
options = (if isBind then ["bind"] else [])
++ [
# disable defaults: don't require this to be mount as part of local-fs.target
# we'll handle that stuff precisely.
"noauto"
"nofail"
# x-systemd options documented here:
# - <https://www.freedesktop.org/software/systemd/man/systemd.mount.html>
]
++ (builtins.map (unit: "x-systemd.requires=${unit}") requires)
++ (builtins.map (unit: "x-systemd.before=${unit}") opt.wantedBeforeBy)
++ (builtins.map (unit: "x-systemd.wanted-by=${unit}") (opt.wantedBy ++ opt.wantedBeforeBy));
noCheck = ifBind true;
};
});
mkFsConfig = path: opt: lib.mkMerge [
(mkGeneratedConfig path opt)
(lib.mkIf (opt.mount != null) (mkMountConfig path opt))
];
generateWrapperScript = path: gen-opt: {
script = ''
fspath="$1"
acluser="$2"
aclgroup="$3"
aclmode="$4"
shift 4
# ensure any things created by the user script have the desired mode.
# chmod doesn't work on symlinks, so we *have* to use this umask approach.
decmask=$(( 0777 - "$aclmode" ))
octmask=$(printf "%o" "$decmask")
umask "$octmask"
# try to chmod/chown the result even if the user script errors
_status=0
trap "_status=\$?" ERR
${gen-opt.script.script}
# claim ownership of the new thing (DON'T traverse symlinks)
chown --no-dereference "$acluser:$aclgroup" "$fspath"
# AS LONG AS IT'S NOT A SYMLINK, try to fix perms in case the entity existed before this script was called
if ! test -L "$fspath"
then
chmod "$aclmode" "$fspath"
fi
exit "$_status"
'';
scriptArgs = [ path gen-opt.acl.user gen-opt.acl.group gen-opt.acl.mode ] ++ gen-opt.script.scriptArgs;
};
# systemd/shell script used to create and set perms for a specific dir
ensureDirScript = path: dir-cfg: {
script = ''
dirpath="$1"
if ! test -d "$dirpath"
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 "$dirpath" || test -d "$dirpath"
fi
'';
scriptArgs = [ path ];
};
# systemd/shell script used to create a symlink
ensureSymlinkScript = path: link-cfg: {
script = ''
lnfrom="$1"
lnto="$2"
# ln is clever when there's something else at the place we want to create the link
# only create the link if nothing's there or what is there is another link,
# otherwise you'll get links at unexpected fs locations
! test -e "$lnfrom" || test -L "$lnfrom" && ln -sf --no-dereference "$lnto" "$lnfrom"
'';
scriptArgs = [ path link-cfg.target ];
};
# return all ancestors of this path.
# e.g. ancestorsOf "/foo/bar/baz" => [ "/" "/foo" "/foo/bar" ]
ancestorsOf = path: lib.init (path-lib.walk "/" path);
# 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 == path-lib.norm p) (builtins.attrNames tree);
};
in {
options = {
sane.fs = mkOption {
# type = types.attrsOf fsEntry;
type = fsTree;
default = {};
};
};
config =
let
configs = lib.mapAttrsToList mkFsConfig cfg;
take = f: {
systemd.services = f.systemd.services;
fileSystems = f.fileSystems;
};
in take (sane-lib.mkTypedMerge take configs);
}

View File

@@ -23,7 +23,9 @@ in
config = lib.mkIf cfg.enable {
sane.packages.enableGuiPkgs = lib.mkDefault true;
# all GUIs use network manager?
users.users.nm-iodine.uid = config.sane.allocations.nm-iodine-uid;
# preserve backlight brightness across power cycles
# see `man systemd-backlight`
sane.persist.sys.plaintext = [ "/var/lib/systemd/backlight" ];
};
}

View File

@@ -15,15 +15,6 @@ in
config = mkIf cfg.enable {
sane.gui.enable = true;
users.users.avahi.uid = config.sane.allocations.avahi-uid;
users.groups.avahi.gid = config.sane.allocations.avahi-gid;
users.users.colord.uid = config.sane.allocations.colord-uid;
users.groups.colord.gid = config.sane.allocations.colord-gid;
users.users.geoclue.uid = config.sane.allocations.geoclue-uid;
users.groups.geoclue.gid = config.sane.allocations.geoclue-gid;
users.users.rtkit.uid = config.sane.allocations.rtkit-uid;
users.groups.rtkit.gid = config.sane.allocations.rtkit-gid;
# start gnome/gdm on boot
services.xserver.enable = true;
services.xserver.desktopManager.gnome.enable = true;

View File

@@ -24,16 +24,6 @@ in
{
sane.gui.enable = true;
users.users.avahi.uid = config.sane.allocations.avahi-uid;
users.users.colord.uid = config.sane.allocations.colord-uid;
users.users.geoclue.uid = config.sane.allocations.geoclue-uid;
users.users.rtkit.uid = config.sane.allocations.rtkit-uid;
users.groups.avahi.gid = config.sane.allocations.avahi-gid;
users.groups.colord.gid = config.sane.allocations.colord-gid;
users.groups.feedbackd.gid = config.sane.allocations.feedbackd-gid;
users.groups.geoclue.gid = config.sane.allocations.geoclue-gid;
users.groups.rtkit.gid = config.sane.allocations.rtkit-gid;
# docs: https://github.com/NixOS/nixpkgs/blob/nixos-22.05/nixos/modules/services/x11/desktop-managers/phosh.nix
services.xserver.desktopManager.phosh = {
enable = true;

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

@@ -0,0 +1,13 @@
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://nixos.org/manual/nix/stable/language/builtins.html
https://github.com/nixos/nixpkgs/pulls?q=
https://nur.nix-community.org/
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

@@ -22,14 +22,15 @@ in
};
config = mkIf cfg.enable {
sane.gui.enable = true;
users.users.greeter.uid = config.sane.allocations.greeter-uid;
users.groups.greeter.gid = config.sane.allocations.greeter-gid;
programs.sway = {
# we configure sway with home-manager, but this enable gets us e.g. opengl and fonts
enable = true;
};
# alternatively, could use SDDM
# instead of using `services.greetd`, can instead use SDDM by swapping in these lines.
# services.xserver.displayManager.sddm.enable = true;
# services.xserver.enable = true;
services.greetd = let
swayConfig-greeter = pkgs.writeText "greetd-sway-config" ''
# `-l` activates layer-shell mode.
@@ -71,18 +72,50 @@ in
pulse.enable = true;
};
hardware.bluetooth.enable = true;
services.blueman.enable = true;
networking.useDHCP = false;
networking.networkmanager.enable = true;
networking.wireless.enable = lib.mkForce false;
hardware.bluetooth.enable = true;
services.blueman.enable = true;
# gsd provides Rfkill, which is required for the bluetooth pane in gnome-control-center to work
services.gnome.gnome-settings-daemon.enable = true;
# start the components of gsd we need at login
systemd.user.targets."org.gnome.SettingsDaemon.Rfkill".wantedBy = [ "graphical-session.target" ];
# go ahead and `systemctl --user cat gnome-session-initialized.target`. i dare you.
# the only way i can figure out how to get Rfkill to actually load is to just disable all the shit it depends on.
# it doesn't actually seem to need ANY of them in the first place T_T
systemd.user.targets."gnome-session-initialized".enable = false;
# bluez can't connect to audio devices unless pipewire is running.
# a system service can't depend on a user service, so just launch it at graphical-session
systemd.user.services."pipewire".wantedBy = [ "graphical-session.target" ];
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 +136,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 +147,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 +176,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 +220,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:

View File

@@ -1,5 +1,5 @@
# Terminal UI mail client
{ config, lib, ... }:
{ config, lib, sane-lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
@@ -8,9 +8,5 @@ lib.mkIf config.sane.home-manager.enable
sopsFile = ../../secrets/universal/aerc_accounts.conf;
format = "binary";
};
home-manager.users.colin = let sysconfig = config; in { config, ... }: {
# aerc TUI mail client
xdg.configFile."aerc/accounts.conf".source =
config.lib.file.mkOutOfStoreSymlink sysconfig.sops.secrets.aerc_accounts.path;
};
sane.fs."/home/colin/.config/aerc/accounts.conf" = sane-lib.fs.wantedSymlinkTo config.sops.secrets.aerc_accounts.path;
}

View File

@@ -9,27 +9,26 @@
with lib;
let
cfg = config.sane.home-manager;
# extract package from `sane.packages.enabledUserPkgs`
pkg-list = pkgspec: builtins.map (e: e.pkg or e) pkgspec;
# extract `dir` from `sane.packages.enabledUserPkgs`
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);
feeds = import ./feeds.nix { inherit lib; };
# extract `pkg` from `sane.packages.enabledUserPkgs`
pkg-list = pkgspec: builtins.map (e: e.pkg) pkgspec;
in
{
imports = [
./aerc.nix
./discord.nix
./firefox.nix
./gfeeds.nix
./git.nix
./gpodder.nix
./keyring.nix
./kitty.nix
./mpv.nix
./nb.nix
./neovim.nix
./newsflash.nix
./splatmoji.nix
./ssh.nix
./sublime-music.nix
./vlc.nix
./zsh.nix
./zsh
];
options = {
@@ -51,18 +50,6 @@ in
};
config = lib.mkIf cfg.enable {
sane.impermanence.home-dirs = [
"archive"
"dev"
"records"
"ref"
"tmp"
"use"
"Music"
"Pictures"
"Videos"
] ++ (dir-list config.sane.packages.enabledUserPkgs);
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
@@ -82,35 +69,6 @@ in
home.username = "colin";
home.homeDirectory = "/home/colin";
home.activation = {
initKeyring = {
after = ["writeBoundary"];
before = [];
data = "${../../scripts/init-keyring}";
};
};
home.file = let
privates = builtins.listToAttrs (
builtins.map (path: {
name = path;
value = { source = config.lib.file.mkOutOfStoreSymlink "/home/colin/private/${path}"; };
})
(private-list sysconfig.sane.packages.enabledUserPkgs)
);
in {
# convenience
"knowledge".source = config.lib.file.mkOutOfStoreSymlink "/home/colin/dev/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";
} // privates;
# XDG defines things like ~/Desktop, ~/Downloads, etc.
# these clutter the home, so i mostly don't use them.
xdg.userDirs = {
@@ -130,7 +88,7 @@ in
# - `xdg-mime query filetype path/to/thing.ext`
xdg.mimeApps.enable = true;
xdg.mimeApps.defaultApplications = let
www = sysconfig.sane.web-browser.desktop;
www = sysconfig.sane.web-browser.browser.desktop;
pdf = "org.gnome.Evince.desktop";
md = "obsidian.desktop";
thumb = "org.gnome.gThumb.desktop";
@@ -173,54 +131,14 @@ in
# <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;
# news-flash RSS viewer
xdg.configFile."newsflashFeeds.opml".text = with feeds;
feedsToOpml (feeds.texts ++ feeds.images);
# gnome feeds RSS viewer
xdg.configFile."org.gabmus.gfeeds.json".text =
let
myFeeds = feeds.texts ++ feeds.images;
in builtins.toJSON {
# feed format is a map from URL to a dict,
# with dict["tags"] a list of string tags.
feeds = builtins.foldl' (acc: feed: acc // {
"${feed.url}".tags = [ feed.cat feed.freq ];
}) {} myFeeds;
dark_reader = false;
new_first = true;
# windowsize = {
# width = 350;
# height = 650;
# };
max_article_age_days = 90;
enable_js = false;
max_refresh_threads = 3;
# saved_items = {};
# read_items = [];
show_read_items = true;
full_article_title = true;
# views: "webview", "reader", "rsscont"
default_view = "rsscont";
open_links_externally = true;
full_feed_name = false;
refresh_on_startup = true;
tags = lib.lists.unique (
(builtins.catAttrs "cat" myFeeds) ++ (builtins.catAttrs "freq" myFeeds)
);
open_youtube_externally = false;
media_player = "vlc"; # default: mpv
};
programs = {
home-manager.enable = true; # this lets home-manager manage dot-files in user dirs, i think
# "command not found" will cause the command to be searched in nixpkgs
nix-index.enable = true;
} // cfg.programs;
programs = lib.mkMerge [
{
home-manager.enable = true; # this lets home-manager manage dot-files in user dirs, i think
# "command not found" will cause the command to be searched in nixpkgs
nix-index.enable = true;
}
cfg.programs
];
};
};
}

View File

@@ -1,12 +0,0 @@
{ config, lib, ... }:
lib.mkIf config.sane.home-manager.enable
{
# TODO: this should only be enabled on gui devices
# make Discord usable even when client is "outdated"
home-manager.users.colin.xdg.configFile."discord/settings.json".text = ''
{
"SKIP_HOST_UPDATE": true
}
'';
}

View File

@@ -1,187 +0,0 @@
{ lib }:
let
hourly = { freq = "hourly"; };
daily = { freq = "daily"; };
weekly = { freq = "weekly"; };
infrequent = { freq = "infrequent"; };
art = { cat = "art"; };
humor = { cat = "humor"; };
pol = { cat = "pol"; }; # or maybe just "social"
rat = { cat = "rat"; };
tech = { cat = "tech"; };
uncat = { cat = "uncat"; };
text = { format = "text"; };
image = { format = "image"; };
podcast = { format = "podcast"; };
mkRss = format: url: { inherit url format; } // uncat // infrequent;
# format-specific helpers
mkText = mkRss text;
mkImg = mkRss image;
mkPod = mkRss podcast;
# host-specific helpers
mkSubstack = subdomain: mkText "https://${subdomain}.substack.com/feed";
# merge the attrs `new` into each value of the attrs `addTo`
addAttrs = new: addTo: builtins.mapAttrs (k: v: v // new) addTo;
# for each value in `attrs`, add a value to the child attrs which holds its key within the parent attrs.
withInverseMapping = key: attrs: builtins.mapAttrs (k: v: v // { "${key}" = k; }) attrs;
in rec {
podcasts = [
(mkPod "https://lexfridman.com/feed/podcast/" // rat // weekly)
## Astral Codex Ten
(mkPod "http://feeds.libsyn.com/108018/rss" // rat // daily)
## Econ Talk
(mkPod "https://feeds.simplecast.com/wgl4xEgL" // rat // daily)
## Cory Doctorow
(mkPod "https://feeds.feedburner.com/doctorow_podcast" // pol // infrequent)
(mkPod "https://congressionaldish.libsyn.com/rss" // pol // infrequent)
## Civboot
(mkPod "https://anchor.fm/s/34c7232c/podcast/rss" // tech // infrequent)
(mkPod "https://feeds.feedburner.com/80000HoursPodcast" // rat // weekly)
(mkPod "https://allinchamathjason.libsyn.com/rss" // pol // weekly)
(mkPod "https://acquired.libsyn.com/rss" // tech // infrequent)
(mkPod "https://rss.acast.com/deconstructed" // pol // infrequent)
## The Daily
(mkPod "https://feeds.simplecast.com/54nAGcIl" // pol // daily)
(mkPod "https://rss.acast.com/intercepted-with-jeremy-scahill" // pol // weekly)
(mkPod "https://podcast.posttv.com/itunes/post-reports.xml" // pol // weekly)
## Eric Weinstein
(mkPod "https://rss.art19.com/the-portal" // rat // infrequent)
(mkPod "https://feeds.megaphone.fm/darknetdiaries" // tech // infrequent)
(mkPod "http://feeds.wnyc.org/radiolab" // pol // infrequent)
(mkPod "https://wakingup.libsyn.com/rss" // pol // infrequent)
## 99% Invisible
(mkPod "https://feeds.simplecast.com/BqbsxVfO" // pol // infrequent)
(mkPod "https://rss.acast.com/ft-tech-tonic" // tech // infrequent)
(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)
];
texts = [
# AGGREGATORS (> 1 post/day)
(mkText "https://www.lesswrong.com/feed.xml" // rat // hourly)
(mkText "http://www.econlib.org/index.xml" // pol // hourly)
# AGGREGATORS (< 1 post/day)
(mkText "https://palladiummag.com/feed" // uncat // weekly)
(mkText "https://profectusmag.com/feed" // uncat // weekly)
(mkText "https://semiaccurate.com/feed" // tech // weekly)
(mkText "https://linuxphoneapps.org/blog/atom.xml" // tech // infrequent)
(mkText "https://spectrum.ieee.org/rss" // tech // weekly)
## No Moods, Ads or Cutesy Fucking Icons
(mkText "https://www.rifters.com/crawl/?feed=rss2" // uncat // weekly)
# DEVELOPERS
(mkText "https://uninsane.org/atom.xml" // infrequent // tech)
(mkText "https://mg.lol/blog/rss/" // infrequent // tech)
## Ken Shirriff
(mkText "https://www.righto.com/feeds/posts/default" // tech // infrequent)
## Vitalik Buterin
(mkText "https://vitalik.ca/feed.xml" // tech // infrequent)
## ian (Sanctuary)
(mkText "https://sagacioussuricata.com/feed.xml" // tech // infrequent)
## Bunnie Juang
(mkText "https://www.bunniestudios.com/blog/?feed=rss2" // tech // infrequent)
(mkText "https://blog.danieljanus.pl/atom.xml" // tech // infrequent)
(mkText "https://ianthehenry.com/feed.xml" // tech // infrequent)
(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)
(mkText "http://benjaminrosshoffman.com/feed" // pol // weekly)
## Ben Thompson
(mkText "https://www.stratechery.com/rss" // pol // weekly)
## Balaji
(mkText "https://balajis.com/rss" // pol // weekly)
(mkText "https://www.ben-evans.com/benedictevans/rss.xml" // pol // weekly)
(mkText "https://www.lynalden.com/feed" // pol // infrequent)
(mkText "https://austinvernon.site/rss.xml" // tech // infrequent)
(mkSubstack "oversharing" // pol // daily)
(mkSubstack "doomberg" // tech // weekly)
## David Rosenthal
(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)
(mkText "https://unintendedconsequenc.es/feed" // rat // infrequent)
(mkText "https://applieddivinitystudies.com/atom.xml" // rat // weekly)
(mkText "https://slimemoldtimemold.com/feed.xml" // rat // weekly)
(mkText "https://www.richardcarrier.info/feed" // rat // weekly)
(mkText "https://www.gwern.net/feed.xml" // uncat // infrequent)
## Jason Crawford
(mkText "https://rootsofprogress.org/feed.xml" // rat // weekly)
## Robin Hanson
(mkText "https://www.overcomingbias.com/feed" // rat // daily)
## Scott Alexander
(mkSubstack "astralcodexten" // rat // daily)
## Paul Christiano
(mkText "https://sideways-view.com/feed" // rat // infrequent)
## Sean Carroll
(mkText "https://www.preposterousuniverse.com/rss" // rat // infrequent)
# CODE
(mkText "https://github.com/Kaiteki-Fedi/Kaiteki/commits/master.atom" // tech // infrequent)
];
images = [
(mkImg "https://www.smbc-comics.com/comic/rss" // humor // daily)
(mkImg "https://xkcd.com/atom.xml" // humor // daily)
(mkImg "http://dilbert.com/feed" // humor // daily)
# ART
(mkImg "https://miniature-calendar.com/feed" // art // daily)
];
all = texts ++ images ++ podcasts;
# return only the feed items which match this category (e.g. "tech")
filterCat = cat: feeds: builtins.filter (item: item.cat == cat) feeds;
# return only the feed items which match this format (e.g. "podcast")
filterFormat = format: feeds: builtins.filter (item: item.format == format) feeds;
# transform a list of feeds into an attrs mapping cat => [ feed0 feed1 ... ]
partitionByCat = feeds: builtins.groupBy (f: f.cat) feeds;
# represents a single RSS feed.
opmlTerminal = feed: ''<outline xmlUrl="${feed.url}" type="rss"/>'';
# a list of RSS feeds.
opmlTerminals = feeds: lib.strings.concatStringsSep "\n" (builtins.map opmlTerminal feeds);
# one node which packages some flat grouping of terminals.
opmlGroup = title: feeds: ''
<outline text="${title}" title="${title}">
${opmlTerminals feeds}
</outline>
'';
# a list of groups (`groupMap` is an attrs mapping groupName => [ feed0 feed1 ... ]).
opmlGroups = groupMap: lib.strings.concatStringsSep "\n" (
builtins.attrValues (builtins.mapAttrs opmlGroup groupMap)
);
# top-level OPML file which could be consumed by something else.
opmlTopLevel = body: ''
<?xml version="1.0" encoding="utf-8"?>
<opml version="2.0">
<body>
${body}
</body>
</opml>
'';
# **primary API**: generate a OPML file from the provided feeds
feedsToOpml = feeds: opmlTopLevel (opmlGroups (partitionByCat feeds));
}

View File

@@ -6,7 +6,7 @@
# 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, ...}:
{ config, lib, pkgs, sane-lib, ...}:
with lib;
let
cfg = config.sane.web-browser;
@@ -19,22 +19,24 @@ let
# });
libName = "librewolf";
dotDir = ".librewolf";
cacheDir = ".cache/librewolf"; # TODO: is it?
desktop = "librewolf.desktop";
};
firefoxSettings = {
browser = pkgs.firefox-esr-unwrapped;
libName = "firefox";
dotDir = ".mozilla/firefox";
cacheDir = ".cache/mozilla";
desktop = "firefox.desktop";
};
defaultSettings = firefoxSettings;
# defaultSettings = librewolfSettings;
package = pkgs.wrapFirefox cfg.browser {
package = pkgs.wrapFirefox cfg.browser.browser {
# inherit the default librewolf.cfg
# it can be further customized via ~/.librewolf/librewolf.overrides.cfg
inherit (pkgs.librewolf-unwrapped) extraPrefsFiles;
inherit (cfg) libName;
inherit (cfg.browser) libName;
extraNativeMessagingHosts = [ pkgs.browserpass ];
# extraNativeMessagingHosts = [ pkgs.gopass-native-messaging-host ];
@@ -43,6 +45,7 @@ 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 {
@@ -51,11 +54,16 @@ let
fixedExtid = pkg.extid;
};
in [
(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-aDBRpcOeMyROnXjmveHKm9zsPC+LzXCG0uhAqI1EWf0=")
# 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-a/ivUmY1P6teq9x0dt4CbgHt+3kBsEMMXlOfZ5Hx7cg=")
(addon "sponsorblock" "sponsorBlocker@ajay.app" "sha256-d2K3ufvurWnYVzqLbyR//MgejybkY9exitAf9RdLNRo=")
(addon "bypass-paywalls-clean" "{d133e097-46d9-4ecc-9903-fa6a722a6e0e}" "sha256-JOj5P7c2JTTReHCRZXm4BscaGr3i+9Y4Ey/y621x8PI=")
(addon "sidebery" "{3c078156-979c-498b-8990-85f7987dd929}" "sha256-YONfK/rIjlsrTgRHIt3km07Q7KnpIW89Z9r92ZSCc6w=")
(addon "ether-metamask" "webextension@metamask.io" "sha256-G+MwJDOcsaxYSUXjahHJmkWnjLeQ0Wven8DU/lGeMzA=")
(addon "ublacklist" "@ublacklist" "sha256-RqY5iHzbL2qizth7aguyOKWPyINXmrwOlf/OsfqAS48=")
(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)
];
@@ -97,43 +105,57 @@ let
in
{
options = {
sane.web-browser = mkOption {
sane.web-browser.browser = mkOption {
default = defaultSettings;
type = types.attrs;
};
sane.web-browser.persistData = mkOption {
description = "optional store name to which persist browsing data (like history)";
type = types.nullOr types.str;
default = null;
};
sane.web-browser.persistCache = mkOption {
description = "optional store name to which persist browser cache";
type = types.nullOr types.str;
default = "cryptClearOnBoot";
};
};
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);
'';
config = lib.mkIf config.sane.home-manager.enable {
# 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>
sane.fs."/home/colin/${cfg.browser.dotDir}/managed-storage/uBlock0@raymondhill.net.json" = sane-lib.fs.wantedText ''
{
"name": "uBlock0@raymondhill.net",
"description": "ignored",
"type": "storage",
"data": {
"toOverwrite": "{\"filterLists\": [\"fanboy-cookiemonster\"]}"
}
}
'';
sane.fs."/home/colin/${cfg.browser.dotDir}/${cfg.browser.libName}.overrides.cfg" = sane-lib.fs.wantedText ''
// 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);
'';
sane.packages.extraGuiPkgs = [ package ];
# flood the cache to disk to avoid it taking up too much tmp
sane.persist.home.byPath."${cfg.browser.cacheDir}" = lib.mkIf (cfg.persistCache != null) {
store = cfg.persistCache;
};
sane.persist.home.byPath."${cfg.browser.dotDir}" = lib.mkIf (cfg.persistData != null) {
store = cfg.persistData;
};
};
}

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