Compare commits

..

533 Commits

Author SHA1 Message Date
d2f3a066fb WIP: make-sandboxed: handle /opt-style packaging, with toplevels linked into /bin, a bit better 2024-08-15 03:05:49 +00:00
50b1d82b38 nixpkgs: fix hashes 2024-08-14 23:20:31 +00:00
60a4eb0bde gnome-calls: associate with tel:, sip:, sips: URIs 2024-08-14 08:27:27 +00:00
a96e83f4e1 doc: gnome-calls: document some UI elements 2024-08-14 07:53:47 +00:00
0d685f406e uassets: 2024-08-09 -> 2024-08-13 2024-08-13 22:02:37 +00:00
a16e33d7a6 sops-nix: 2024-08-05 -> 2024-08-12 2024-08-13 22:02:27 +00:00
f38d351869 syshud: 2024-08-03 -> 2024-08-10 2024-08-13 22:01:57 +00:00
e245164da3 nixpkgs-wayland: 2024-08-12 -> 2024-08-13 2024-08-13 22:01:31 +00:00
7df8f45e97 nixpkgs: 2024-08-12 -> 2024-08-13 2024-08-13 22:00:49 +00:00
e1ba371838 cross: flatpak: fix via nixpkgs patch instead of overlay 2024-08-13 07:20:24 +00:00
467283989f todo.md: fix Epiphany to persist cookies 2024-08-13 03:41:08 +00:00
db39dc209f xdg-desktop-portal-gnome: sandbox 2024-08-13 03:34:09 +00:00
7cf860a071 nixpkgs: update passt hash 2024-08-13 03:33:48 +00:00
77a753b0d6 gnome-maps: todo: better portal integration 2024-08-13 02:50:59 +00:00
e2a4f4d63e todo.md: newsflash and gnome-maps bugs to tackle 2024-08-13 02:48:08 +00:00
31fc072bce nixpkgs-overlays: try to be a little more pure 2024-08-12 21:56:30 +00:00
144afd8171 sway: fix wlroots drmSync bug via upstream patch 2024-08-12 21:52:44 +00:00
7d97355d2a overlays/cross: remove no-longer-necessary overrides 2024-08-12 21:20:16 +00:00
7827f6c584 sway: note that the activation patch is still necessary 2024-08-12 18:28:16 +00:00
e1899495a0 nixpkgs-wayland: 0-unstable-2024-08-06 -> 0-unstable-2024-08-12 2024-08-12 18:05:32 +00:00
a56ad56a4f refactor: move ~/.cache/nix persistence to hosts/common/programs/nix.nix 2024-08-12 16:06:26 +00:00
da551b8b97 geary: grant access to more files 2024-08-12 16:04:20 +00:00
ca412d08bd nautilus: grant access to more files 2024-08-12 16:04:11 +00:00
e7a1bb6ec0 nixpkgs: 2024-08-11 -> 2024-08-12 2024-08-12 10:30:04 +00:00
74acfeadd5 programs/assorted: clarify sandbox.enable = false situation 2024-08-12 10:27:41 +00:00
e7d5a61014 libcap: split into separate capsh and captree programs, and sandbox the latter 2024-08-12 10:13:50 +00:00
6f47708624 nixpkgs patches: send a few upstream; dont apply ffado patch here because my system doesnt use it 2024-08-12 10:10:06 +00:00
fc826a3503 libcap: patch in captree locally rather than via a nixpkgs patch that would force mass rebuilds 2024-08-12 09:39:43 +00:00
ccb2b7b8b6 nixpkgs: update libcap patch to grab from the PR 2024-08-12 09:18:50 +00:00
78169d50f2 overlays/cross: remove upstreamed patches; simplify rust things 2024-08-12 09:14:42 +00:00
33a7d3536d nixpkgs: update patches 2024-08-12 09:14:00 +00:00
7899c8d033 syshud: 0-unstable-2024-07-29 -> 0-unstable-2024-08-10 2024-08-12 02:37:03 +00:00
82b662a733 nixpkgs: remove dead (upstreamed) patches 2024-08-12 02:13:07 +00:00
d4290588bf rename: trust-dns -> hickory-dns 2024-08-12 01:23:39 +00:00
bd97fb9ec9 nixpkgs: 24.05-unstable-2024-08-09 -> 24.05-unstable-2024-08-11 2024-08-12 01:08:03 +00:00
4dbff9c18f scripts/deploy: shorten "--action copy" to just "--copy" 2024-08-12 01:07:50 +00:00
bfe278c17a feeds: subscribe to Weird Little Guys 2024-08-12 00:35:34 +00:00
295e07d535 sane-tag-media: fix lingering crashes around --derive behavior 2024-08-12 00:13:42 +00:00
d39459d8b5 NetworkManager: tighten the systemd sandboxing 2024-08-11 22:54:47 +00:00
4d5e60756b modemmanager: make its capabilities more obvious 2024-08-11 22:54:41 +00:00
119afcf393 firefox: remove open-in-mpv (obsoleted by firefox-xdg-open) 2024-08-11 22:37:12 +00:00
d3d970eb3e firefox: dont require approval to open xdg-open: URIs 2024-08-11 22:32:26 +00:00
c0d5004926 firefox: add a right-click context menu to open any URI with the system handler
it still prompts the user to allow it, but i'll fix that later i guess
2024-08-11 22:26:23 +00:00
d9a876e49a fractal: association with https://matrix.to links 2024-08-11 21:45:51 +00:00
5a9dd89475 sane-vpn: fix global up/down action 2024-08-11 21:01:11 +00:00
5e71e5a067 moby: enable bluetooth 2024-08-11 06:27:07 +00:00
f0b0d15ad7 evtest: ship 2024-08-11 06:26:58 +00:00
8aebc1fe87 feeds: subscribe to Oyez supreme court oral arguments 2024-08-10 11:16:54 +00:00
764c2a3276 Revert "nixpkgs-wayland: 0-unstable-2024-08-06 -> 0-unstable-2024-08-09"
This reverts commit ce1c3ec804.

while the nixpkgs-wayland bump works fine on lappy/desko,
it causes moby to be stuck on the white screen after unlocking.
2024-08-10 04:16:31 +00:00
a2f34be9d6 avahi: fix so the dbus policy files get installed system wide, again 2024-08-10 02:59:20 +00:00
bda172bc2d avahi: harden systemd service
N.B.: i haven't tested this on moby yet (which advertizes the gps-share service) nor on servo (which maybe uses it for jellyfin, idk)
2024-08-10 02:04:57 +00:00
a91a2d8a7f gps-share: fix sandboxing 2024-08-10 01:10:31 +00:00
875d919fa8 systemd-rfkill: harden 2024-08-10 00:34:13 +00:00
a323f321b5 snapper: disable
it wasn't working to begin with
2024-08-10 00:09:58 +00:00
f986936bbd wg-home-refresh: use the sandboxed wireguard-tools 2024-08-09 23:52:31 +00:00
3d773fe375 sanebox: improve the capsh stuff a bit more 2024-08-09 23:52:16 +00:00
055ad222e3 wg-home-refresh: harden systemd service 2024-08-09 23:05:58 +00:00
3aafcb0aa8 sanebox: capshonly: be more precise about preserving e/i/p capabilities
with this, gocryptfs works AND wg works
2024-08-09 22:55:02 +00:00
c85f02ca68 scripts/sync: dont rely on /mnt/$self existing 2024-08-09 21:41:56 +00:00
eeafc34ccf hare-ev: 2024-07-11 -> 2024-08-06 2024-08-09 21:41:56 +00:00
039ffcdcd4 newsflash: sandbox 2024-08-09 21:35:33 +00:00
2a35cb5379 mime.urlAssociations: clarify regexes by using $ terminator 2024-08-09 20:57:13 +00:00
3db009bc98 mpv: associate with all web audio/video resources 2024-08-09 20:55:00 +00:00
1e840e72b3 nixpkgs: 24.05-unstable-2024-08-06 -> 24.05-unstable-2024-08-09 2024-08-09 10:34:20 +00:00
ce1c3ec804 nixpkgs-wayland: 0-unstable-2024-08-06 -> 0-unstable-2024-08-09 2024-08-09 10:34:02 +00:00
09dd69a855 uassets: 0-unstable-2024-08-06 -> 0-unstable-2024-08-09 2024-08-09 10:33:29 +00:00
cbe71868ef newsflash: deploy 2024-08-09 10:25:53 +00:00
7b043d0c87 newsflash: simplify cross compilation 2024-08-09 10:14:59 +00:00
fd0188025d newsflash: fix cross compilation 2024-08-09 09:46:40 +00:00
1c57ffa798 newsflash-nixified: init at 3.3.4 (doesn't build!)
it's doing complicated things with glib macros that i can't get to work.
2024-08-09 03:50:36 +00:00
1d205a89bc sway: fix gnome-calls to always be on workspace 1 2024-08-08 23:59:19 +00:00
5ff643aa2f foliate: fix sandboxing 2024-08-08 23:58:02 +00:00
bfdf63e641 calls: 46.3 -> 47.0-beta 2024-08-08 23:57:47 +00:00
c695f7a979 foliate: ship 2024-08-08 21:08:51 +00:00
b3b38451b5 koreader-from-src: add an update script (only updates the toplevel, at the moment) 2024-08-08 18:47:03 +00:00
1ee81db537 switch xdg-desktop-portal-gtk -> xdg-desktop-portal-gnome
the gnome file chooser is far more responsive, on moby

though thumbnailing doesnt work, which may degrade the desktop experience :-(
2024-08-08 09:43:47 +00:00
b9947c05ca xdg-desktop-portal-gnome: fix cross compilation 2024-08-08 09:05:26 +00:00
2de6491583 xdg-desktop-portal-gnome: get working as a xdp backend, on lappy
probably needs some porting to moby before it works there
2024-08-08 08:52:24 +00:00
4525df58e0 rsyslog: disable 2024-08-08 07:40:59 +00:00
9d1ffc7c43 todo.md: document some connectivity issues 2024-08-08 03:41:52 +00:00
a69af91b7b add /mnt/servo/home to my hosts 2024-08-08 00:45:33 +00:00
7b5d655c91 scripts/check-backups: show how to view the host's last-completed 2024-08-07 23:00:44 +00:00
de6ffe6b75 flare-signal: update compatibility notes 2024-08-07 22:07:56 +00:00
f8aea34e96 sanebox: bwrap: make user namespace unsharing more obvious 2024-08-07 21:23:21 +00:00
49efb94a0a seatd: restrict capabilities 2024-08-07 20:30:29 +00:00
9b1e053ead seatd: place the socket in a place that lends itself to better sandboxing 2024-08-07 19:37:20 +00:00
235dc86155 todo.md: delete completed sandboxing items 2024-08-07 01:33:31 +00:00
6dad290cd5 duplicity: purge 2024-08-07 01:33:31 +00:00
cc6ed6c0ec flare-signal: annotate my notes on it with datestamps 2024-08-07 01:23:43 +00:00
cc3aba3cc2 servo: fix postfix: dont start until after the mail dir has been mounted 2024-08-07 00:17:17 +00:00
41f08125bb scripts/check-backups: convert timestamps to hours 2024-08-06 21:50:49 +00:00
27487fe870 scripts/check-admin: script to show which (if any) services require tending to registration attempts 2024-08-06 21:40:48 +00:00
d45ea622d1 servo: disable email-based registration gating 2024-08-06 21:39:32 +00:00
247fd3f807 less: tune flags, especially for systemd/journalctl 2024-08-06 19:25:10 +00:00
816e2a7065 nixpkgs: 24.05-unstable-2024-08-04 -> 24.05-unstable-2024-08-06 2024-08-06 19:08:39 +00:00
be842d5c5e nixpkgs-wayland: 0-unstable-2024-08-03 -> 0-unstable-2024-08-06 2024-08-06 19:08:30 +00:00
fa6ec981e0 sops-nix: assets-unstable-2024-07-27 -> assets-unstable-2024-08-05 2024-08-06 19:08:16 +00:00
52b4c1542a uassets: 0-unstable-2024-08-03 -> 0-unstable-2024-08-06 2024-08-06 19:08:00 +00:00
3ff59247da uninsane-dot-org: ? -> 2024-08-06 2024-08-06 19:07:44 +00:00
d9c0855c4e fractal-nixified: 7 -> 8 2024-08-06 08:26:50 +00:00
1a67a05238 transmission/torrent-done: make files readable (speculative) 2024-08-06 08:26:16 +00:00
1cdeedd9ec servo: partially ship ollama 2024-08-06 08:24:29 +00:00
6830bb7097 servo: transmission: simplify the rsync call
i'm having perms issues _somewhere_
2024-08-06 08:14:45 +00:00
316b0bee3a landlock-sandboxer: disable the ABI mismatch warnings 2024-08-06 07:20:00 +00:00
638655ff83 mnt-servo-*-reachable.service: harden systemd service 2024-08-06 06:43:10 +00:00
5e57e78411 /mnt/servo/*: fix to not hang the mount when fs is offline
this is an unfortunate effect of the drop_privileges part of fuse3,
that the mount is active as soon as the fs implementation is launched,
instead of when it enters `fuse_main`.
2024-08-06 05:54:31 +00:00
3859619ae0 curlftpfs-sane: implement "-o exit_after_connect" 2024-08-06 05:53:45 +00:00
646c2dd85a common/fs: mount curlftpfs using fuse3 2024-08-06 04:48:47 +00:00
0655b6906c curlftpfs: implement readdir
i think now all the stuff you'd expect of a basic fs now actually works
2024-08-06 04:11:32 +00:00
3019f90f5d curlftpfs-sane: upgrade to fuse3 2024-08-06 03:00:11 +00:00
020e5f8c6e /mnt/persist/private: split waiting on the keyfile out of the mount process 2024-08-06 02:03:55 +00:00
809c3af7fa /mnt/persist/private: minor improvements to file permissions 2024-08-06 01:26:53 +00:00
93cb1bc546 /mnt/persist/private: sandbox in a way that the actual gocryptfs instance doesn't get CAP_SYS_ADMIN 2024-08-06 00:52:48 +00:00
53acab834c refactor: persist/stores/ephemeral: move to its own source directory 2024-08-05 23:05:02 +00:00
3a0610b029 /mnt/persist/ephemeral: sandbox in a way that the actual gocryptfs instance doesn't get CAP_SYS_ADMIN
instead, only fuse does, and the capability is lost during the handoff between fuse and gocryptfs
2024-08-05 23:04:14 +00:00
9cee460d7e gocryptfs: sandbox with landlock
now /mnt/persist/ephemeral implementation can't access /mnt/persist/private; /mnt/persist/private can't access /mnt/desko/home, and so on
2024-08-05 23:01:38 +00:00
e657507a76 libfuse-sane: search for mount helpers on /run/current-system/sw/bin 2024-08-05 23:00:05 +00:00
c706a19836 landlock-sandboxer: rename the binary, so that it can be included on PATH without collisions 2024-08-05 22:59:14 +00:00
566e15286b sanebox: don't assume 'readlink' is available in the environment 2024-08-05 22:56:18 +00:00
d1b4e9c923 sanebox: allow /dev/fd in the sandbox by default 2024-08-05 22:55:12 +00:00
5eca45891b sanebox: fix landlock sandboxing IAB edgecases
i don't fully understand it. but adjusting the Inh capability set breaks things like gocryptfs. i think it isn't necessary: if we set E alone, and no-new-privs, then that gets us the same guarantees.
2024-08-05 22:54:20 +00:00
722fe8f368 libcap: ship the optional 'captree' component 2024-08-05 05:30:14 +00:00
e25dd98f6c spot/spotify: disable
i don't use spotify atm
2024-08-05 00:47:59 +00:00
54e9d4a0ae sane-vpn: switch back to bwrap instead of pasta 2024-08-04 18:56:17 +00:00
9f3a13eeb8 nixpkgs: 24.05-unstable-2024-08-02 -> 24.05-unstable-2024-08-04 2024-08-04 02:19:14 +00:00
5605ffda4b nixpkgs-wayland: 0-unstable-2024-08-02 -> 0-unstable-2024-08-03 2024-08-04 02:18:57 +00:00
9165925469 syshud: 0-unstable-2024-07-29 -> 0-unstable-2024-08-03 2024-08-04 02:18:37 +00:00
f65bf2b433 uassets: 0-unstable-2024-08-02 -> 0-unstable-2024-08-03 2024-08-04 02:18:14 +00:00
0f60a86ed4 hare-ev: 0-unstable-2024-07-07 -> 0-unstable-2024-07-11 2024-08-04 01:08:37 +00:00
b488b6748d nixos/pam: replace apparmor warnings with assertions 2024-08-04 00:50:41 +00:00
ef6b7cf175 syshud: 0-unstable-2024-07-16 -> 0-unstable-2024-07-29 2024-08-04 00:39:04 +00:00
0906d76f83 libcap_ng: ship 2024-08-03 23:27:53 +00:00
90c495e74c libfuse-sane: ship 2024-08-03 22:59:34 +00:00
74662df720 persist/{private,ephemeral}: mount via fuse
gocryptfs is compatible with --drop-permissions style of mount.fuse3. only, i can't actually use that today because i need to keep permissions :o

but maybe i'll enable that in the future
2024-08-03 18:51:58 +00:00
2b3278eb7f /mnt/$host/home: layer bwrap sandboxing after the drop-privileges passoff 2024-08-03 17:11:11 +00:00
9b4e91fbd9 /mnt/$host/home: harden systemd settings 2024-08-03 16:27:42 +00:00
734627232a /mnt/$host/home: mount with drop_privileges 2024-08-03 15:13:04 +00:00
3adbbe5fa7 /mnt/$host/home: run as user instead of as root 2024-08-03 15:13:04 +00:00
b4a244df7a rsync-net: fix /nix/persist/private path 2024-08-03 14:32:44 +00:00
97268e9b26 curlftpfs-sane: rename from curlftpfs
i already patched it significantly; i plan to port to fuse3 shortly
2024-08-03 14:32:01 +00:00
bebf6bdaeb rsync-net: hardcode fewer paths 2024-08-03 11:38:43 +00:00
04fc601c9c rsync-net: fix sandboxing (dont set PrivateUsers: we lose perms in the root ns doing that) 2024-08-03 11:25:50 +00:00
ee062d61d0 sane-tag-media: rework the tag extrapolation to be less intrusive 2024-08-03 07:58:43 +00:00
0dba9987c5 sane-tag-media: remove unused "confirm" function 2024-08-03 07:19:53 +00:00
4761690b6d sane-tag-media: have --derive + --override-existing NOT override the existing tags when the derived ones apear to be simply lower-quality versions of the same on-disk data 2024-08-03 07:19:08 +00:00
604782c3a6 sane-tag-media: refactor (simplify) 2024-08-03 03:57:09 +00:00
365d33c357 sane-tag-media: empty manual tags always overwrite tags, regardless of --override-existing flag 2024-08-03 03:38:22 +00:00
a39ad8a508 sane-tag-media: rename --force flag to --override-existing 2024-08-03 03:31:16 +00:00
c49e9a4c2b sane-tag-media: implement the --ignore-existing flag 2024-08-03 03:18:07 +00:00
36491842cc sanebox: bwrap: micro-optimize to not require env 2024-08-02 22:44:27 +00:00
81ea2210c9 sanebox: allow keeping the net namespace 2024-08-02 22:44:27 +00:00
f678508b33 sanebox: add --sanebox-capsh-arg flag 2024-08-02 22:44:27 +00:00
6135be5f72 sanebox: refactor: bwrapFlags -> bwrapArgs 2024-08-02 22:44:27 +00:00
c8989ca1a8 pasta: allow running as root 2024-08-02 22:44:26 +00:00
1d665f8ecc sanebox: support "--sanebox-cap all" special case 2024-08-02 22:43:52 +00:00
7c284ad8da sane-vpn: use pasta instead of full bwrap for net namespacing 2024-08-02 22:42:56 +00:00
1c26674da7 rsync-net: temporarily use only RestrictNetworkInterfaces option and disable the internal sane-vpn logic
this is temporary, until i can fix sane-vpn to preserve linux capabilities
2024-08-02 22:10:44 +00:00
dae8481176 firefox: ship a "stub DNS" desktop file variant
though note that my stub-dns seems to be broken recently...
2024-08-02 21:41:07 +00:00
42b27f0433 sane-vpn: fix broken doc on --verbose flag 2024-08-02 21:39:29 +00:00
84be0cae5a todo.md: note another website which doesnt resolve with trust-dns 2024-08-02 21:20:31 +00:00
fbfd0afca4 common/fs: only desclare /mnt/$host mounts for hosts this machine is authorized to access 2024-08-02 20:29:22 +00:00
e586b7b449 signal-desktop-from-src: 7.16.0 -> 7.18.0 2024-08-02 10:52:44 +00:00
222c37b056 uassets: 2024-07-29 -> 2024-08-02 2024-08-02 10:52:25 +00:00
53b17ec230 nixpkgs-wayland: 2024-07-28 -> 2024-08-02 2024-08-02 10:52:07 +00:00
7697704aff nixpkgs: 2024-07-31 -> 2024-08-02 2024-08-02 10:51:44 +00:00
c490b6e6ad common/polyunfill: simplify my config by using the new security.pam.package option 2024-08-02 10:04:20 +00:00
89d678c729 nixpkgs: 2024-07-29 -> 2024-07-31 2024-08-02 10:03:48 +00:00
c64163290c gocryptfs: return to running mainline
i don't need the bug fix anymore, since i don't use pam_mount anymore
2024-08-02 09:52:20 +00:00
eaeb8380dc fs: enable @basic-api everywhere, since its required by systemd restart logic 2024-08-02 09:13:55 +00:00
05a9e8e819 common: /mnt/servo: fix systemd mount files to be aware of the timeout, again 2024-08-02 08:16:13 +00:00
cf20230d96 sane.fs: cleanup
plumb systemd.{mounts,services} instead of the less detailed 'systemd'
2024-08-02 08:01:38 +00:00
9dbb2a6266 sane.fs: take in the role of generating systemd.mounts files 2024-08-02 07:33:21 +00:00
113b107d73 persist: fix ordering so stores arent required by local-fs.target
maybe they should be, but then there's weird stuff about getty depending on sysinit.target, and that being blocked by the private store...
2024-08-02 06:20:39 +00:00
96dfe79a8c fs: persist/private: harden systemd mount file 2024-08-02 05:17:44 +00:00
6e5bde17aa cleanup: persist/private: simplify 2024-08-02 05:00:55 +00:00
3eb66c098b trust-dns: make it a dependency of "network-online.target" 2024-08-02 04:54:58 +00:00
515aab5370 cleanup: persist/private: encode the dependencies more precisely, rather than just having it all depend on default.target 2024-08-02 04:50:33 +00:00
f925dd9a20 fs: isolate /mnt/servo/* and /mnt/persist/ephemeral a bit more 2024-08-02 04:45:14 +00:00
cbe6bdf158 hosts: fs: sandbox /mnt/servo/* mounts 2024-08-02 03:17:53 +00:00
949a52dee1 activationScripts.notifyActive: be quiet about sane-deadlines/sane-sysload 2024-08-02 01:11:19 +00:00
2ee1fb17c4 sane-deadlines, sane-sysload: fix ordering to not run before the environment is configured 2024-08-02 01:04:07 +00:00
48cc718700 login: remove systemd-user-sessions integration so that we dont block on remote-fs
tested on lappy. will it work on servo, with gitea?
2024-08-02 00:52:51 +00:00
6a7dd31755 vpn: fix warning about missing /32 syntax 2024-08-02 00:37:58 +00:00
2197951e12 NetworkManager-dispatcher: cleanup an ordering cycle between it and trust-dns-localhost 2024-08-02 00:36:54 +00:00
883db3e9ba todo.md: sync 2024-08-02 00:33:35 +00:00
312b0a5554 todo.md: sandbox the remaining filesystems 2024-08-01 22:50:03 +00:00
07de46c616 todo.md: remove completed items 2024-08-01 22:48:49 +00:00
efc16a9e80 persist: harden the "ephemeral" store mount environment
there's only so much this can actually achieve. it's still quite possible for someone who knows what they're doing to do large amounts of damage
2024-08-01 22:40:55 +00:00
161f272f41 gpodder-adaptive: track youtube-dl upstreaming 2024-08-01 20:02:47 +00:00
6aa6c0020c lightning-cli: fix sandboxing 2024-08-01 19:59:23 +00:00
acd46940e4 clightning: lift the build fix into pkgs/default.nix
this lets me apply it outside the context of a nixos module
2024-08-01 19:53:05 +00:00
00a25f1533 feeds: fix complex systems URL 2024-08-01 19:52:22 +00:00
bc0a1eb1b3 feeds: sub to Complex Systems Podcast 2024-08-01 18:58:39 +00:00
cd3f483df0 sway: add "Super+B" shortcut to open the Web Browser 2024-08-01 18:55:25 +00:00
38a183cf3b sane-open: backfill missing configureKeyboardFor_uri method 2024-08-01 18:54:50 +00:00
5ed6e84cc7 sane-open: refactor 2024-08-01 18:54:04 +00:00
7c1a0fc323 sane-open: add --debug flag 2024-08-01 18:52:55 +00:00
f16066549f sane-open: fallback to URI instead of file when we cant do anything more specialized 2024-08-01 18:52:06 +00:00
659da66106 sane-open: add the ability to open URIs 2024-08-01 18:50:17 +00:00
c07eaba873 tor-browser: associate with .onion URLs 2024-08-01 18:34:38 +00:00
bb420bd45d firefox: add a desktop item for launching inside a VPN 2024-08-01 18:10:32 +00:00
3902432864 where-am-i: fix bin linking 2024-08-01 17:57:45 +00:00
33efbeda8a link manpages into all linkIntoOwnPackage users 2024-08-01 17:43:58 +00:00
8206fb0519 linkIntoOwnPackage: place man/doc into separate outputs 2024-08-01 17:11:24 +00:00
2687286489 servo: nginx: switch to mainline zlib to silence syslog warnings 2024-08-01 01:25:16 +00:00
d5e52e21f7 sane-stop-all-servo: stop ntfy and trust-dns-doof services 2024-07-31 23:40:51 +00:00
367fc24aa8 nixpkgs: full_index=1: actually apply to all PR urls -- not just nixpkgs commits 2024-07-31 20:59:07 +00:00
bf45206d1a nixpkgs: use full_index=1 when fetching patches, for stable hashes 2024-07-31 20:52:38 +00:00
397b2ae2ea nixpkgs: update hashes 2024-07-30 22:05:01 +00:00
f0ebb305ec nixpkgs: update hashes
though it's probably fetchpatch2 just being stupid again and i'll revert
2024-07-30 21:58:01 +00:00
e629d2d999 rsync-net: harden systemd service, and dodge the "pasta doesnt support root" bug 2024-07-30 21:54:25 +00:00
9b2601e450 cross: fix texinfo (used for info command) 2024-07-30 16:23:06 +00:00
a20c13fffe firefox-extensions.ublacklist: 8.9.1 -> 8.9.2 2024-07-30 15:50:04 +00:00
20a2d8dc1c uassets: 2024-07-28 -> 2024-07-29 2024-07-30 15:50:04 +00:00
297bf7e090 syshud: 2024-07-21 -> 2024-07-29 2024-07-30 15:50:04 +00:00
ed024d081e nixpkgs-wayland: 2024-07-27 -> 2024-07-28 2024-07-30 15:50:04 +00:00
4ddd4191bc nixpkgs: 2024-07-28 -> 2024-07-29 2024-07-30 15:50:04 +00:00
32ef63028b sane-reclaim-disk-space: fix quote typo 2024-07-30 15:32:35 +00:00
70bd001171 servo: bitcoind: harden systemd service 2024-07-30 13:12:27 +00:00
b53f376d70 servo: clightning: tighten sandboxing for bitcoin-cli interaction 2024-07-30 12:41:33 +00:00
621c147483 clightning: remove /var/lib/bitcond-mainnet from the service paths -- again 2024-07-30 11:17:10 +00:00
841076fd9e clightning: move /var/lib/bitcoind-mainnet from ReadWritePaths -> ReadOnlyPaths
i think i can go further, remote it altogether
2024-07-29 23:19:26 +00:00
80492e902b inotify watches: bump 1M -> 4M
i'm hoping this will reduce errors on servo seen in system services,
about exhausing "disk space" (file handle space)
2024-07-29 23:19:26 +00:00
f058fe0be6 servo: lemmy: sandbox 2024-07-29 23:19:26 +00:00
8fde3dea77 servo: pleroma: fix service hardening 2024-07-29 23:19:26 +00:00
ac9238a7f0 servo: assorted: plead with shitty AI companies to not bring my server to its knees by scraping all of the Linux source code
i thought AI was supposed to be smart
2024-07-29 19:19:32 +00:00
45412e5042 common/fs: ftp auto-remounting in a way which doesnt use .service files 2024-07-29 15:44:54 +00:00
d76d50f1c4 common/fs: /mnt/servo/* ftp auto/re-mounting in a way which does better rate limiting 2024-07-29 07:11:52 +00:00
f1c76ada43 WIP: common/fs: simpler /mnt/servo/* ftp auto/re-mounting 2024-07-29 03:44:10 +00:00
9dbd85ba08 servo: slskd: remove the hardening options until i can debug 2024-07-29 03:42:52 +00:00
2c707c3acd servo: lemmy/lemmy-ui: harden the service with a syscall filter 2024-07-29 03:42:52 +00:00
0fae963d90 servo: lemmy: harden the backend systemd service 2024-07-29 03:42:52 +00:00
90df178c35 servo: slskd: harden (partially) 2024-07-29 03:42:52 +00:00
dc053149d0 servo: lemmy/lemmy-ui: harden 2024-07-29 03:42:52 +00:00
bce81d0487 servo: pleroma: harden 2024-07-29 03:42:52 +00:00
a8eba4df4d servo: jackett: harden further 2024-07-29 03:42:52 +00:00
1bb36b74c2 scripts/check-uninsane: check that servo bitcoind is online 2024-07-29 03:42:52 +00:00
e21910a1f7 servo: disable unused i2p, monero services 2024-07-29 03:42:52 +00:00
4b30036973 servo: bitcoind: harden 2024-07-29 03:42:52 +00:00
ea5919ab6b servo: jackett: harden 2024-07-29 03:42:52 +00:00
43232ff569 kiwix-serve: harden 2024-07-29 03:42:52 +00:00
6a9fd04437 bitcoin-cli: split into own file, and fix broken path to config file when running as user 2024-07-29 03:42:52 +00:00
dc2d46b9c0 servo: cryptocurrencies: get clightning back into a state where i can see its working 2024-07-29 03:42:52 +00:00
666744bda3 bitcoin-cli,lightning-cli: ship as own package instead of shipping the whole daemon 2024-07-29 03:42:52 +00:00
ba09fbeec9 bitcoind: fix sandboxing 2024-07-29 03:42:52 +00:00
916ecc30d1 scripts/deploy: fix --reboot flag 2024-07-29 03:42:52 +00:00
1536a60a3d firefox-extensions.ether-metamask: attributions-v11.16.15 -> 11.16.16 2024-07-29 03:42:52 +00:00
b7418afede uassets: 2024-07-22 -> 2024-07-28 2024-07-29 03:42:52 +00:00
82a0bf3212 sops-nix: 2024-07-21 -> 2024-07-27 2024-07-29 03:42:52 +00:00
cb79224c7a nixpkgs-wayland: 2024-07-22 -> 2024-07-27 2024-07-29 03:42:52 +00:00
b850e25f5b nixpkgs: 2024-07-24 -> 2024-07-28 2024-07-29 03:42:52 +00:00
8f0f7ef333 cross: fix rsyslog compilation 2024-07-29 03:42:52 +00:00
0bfaead177 sane-deadlines: only show on physical login, not ssh 2024-07-29 03:42:52 +00:00
1b93dbe12c sane-sysload: show on remote login 2024-07-29 03:42:52 +00:00
72d286fbba sane-sysload: add an "{all}" formatter, and show that by default 2024-07-29 03:42:52 +00:00
033faf6f6b clightning-sane: fix --help formatting 2024-07-28 19:24:38 +00:00
eb3651ce59 refactor: assorted: python: logger.warn -> logger.warning
the former is deprecated
2024-07-28 03:41:30 +00:00
bf1f843306 doc: rsyslog: note that this isnt the traditional setup
also, may want to tune the burst settings in the future. i definitely got rate-limited
2024-07-28 03:40:53 +00:00
6cc5669772 servo: remove the root auto-login, so that my s6-rc entrypoint works
i'm sure there's a better way to do this... meh
2024-07-28 03:40:07 +00:00
cb1fbdcaf0 sane-ip-check: add a delay in the retry path 2024-07-28 03:24:02 +00:00
c83dc4d601 servo: assorted: decrease logging verbosity of matrix, lemmy, dovecot, ntfy-sh 2024-07-28 03:15:27 +00:00
36bbac539f nginx: port /var/www/sites data to private store 2024-07-28 02:38:36 +00:00
9a1cd9341f feeds: note some more podcast discovery places 2024-07-28 01:54:14 +00:00
3a6a5ffe01 rsyslog: persist logs 2024-07-28 01:54:14 +00:00
971de060d5 WIP: port /var/log persistence to private store 2024-07-28 01:54:14 +00:00
3ea57f1d6a users: disable pam mount
this was needed for the old way of mounting ~/private, but no longer
2024-07-28 01:54:14 +00:00
fa05e59863 servo: ipfs: port data to private store 2024-07-28 01:54:14 +00:00
de7ff360dc servo: postfix: port data to private store 2024-07-27 17:43:18 +00:00
7f1f9a082d flare-signal-nixified: simplify 2024-07-27 17:30:18 +00:00
6553cdc068 flare-signal-nixified: 0.10.1 -> 0.15.0 2024-07-27 16:54:12 +00:00
e44771f67d servo: postgresql: port data to private store 2024-07-27 16:51:23 +00:00
cbe17c03e4 scripts/deploy: fix usage message about --reboot flag 2024-07-27 14:48:44 +00:00
4c4d841038 servo: slskd: dont persist any data, actually (it still works) 2024-07-27 14:48:31 +00:00
060ae113a1 servo: transmission: port data to private store 2024-07-27 14:14:27 +00:00
540124d2f7 servo: slskd: port data to private store 2024-07-27 13:54:01 +00:00
9df947aa74 servo: ejabberd: port data to private store 2024-07-27 13:40:08 +00:00
66333cbbe7 servo: prosody: port data to private store 2024-07-27 13:38:34 +00:00
3353ed3b66 linux-postmarketos-allwinner: 6.9.0 -> 6.9.10 2024-07-27 13:26:18 +00:00
447923a231 servo: matrix: port data to private store 2024-07-27 12:44:49 +00:00
3179a6834b servo: gitea: port data to private store 2024-07-27 11:49:47 +00:00
70a470b81e servo: ntfy: port data to private store 2024-07-27 02:10:43 +00:00
fff7848cd6 servo: clightning: port data to private store 2024-07-27 02:07:39 +00:00
1fb6cb483b servo: tor: port to private share 2024-07-27 02:04:08 +00:00
33e72c8d34 pleroma: port to private share 2024-07-27 02:00:28 +00:00
8629e2600a jackett: port to private store 2024-07-27 01:49:12 +00:00
2e644dc020 persist/private: remove the "prefix", to allow the store to hold files not just in /home/colin
this will require a one-time manual migration on all devices
2024-07-27 00:26:57 +00:00
f4a6bc1991 pam_cap: fix ordering so that my sessions have correct capabilities again 2024-07-26 23:58:57 +00:00
19fd45211f sane-secrets-unlock: remove from ~/.profile and make it an s6 service
more reliable, in practice
2024-07-26 22:18:32 +00:00
ace03bb0e9 persist/private: actually do enable "auto", for servo where i dont auto-tty-login as colin
this doesn't seem to block the boot
2024-07-26 22:02:57 +00:00
8819142128 modules/users: use = instead of -eq for comparison to fix warning which XDG_VTNR is unset 2024-07-26 20:57:23 +00:00
d905af6cd1 ship sane-private-unlock-remote as a cron job to lappy/desko 2024-07-26 20:54:27 +00:00
0f084b19f1 sane-scripts.private-unlock-remote: init 2024-07-26 20:16:12 +00:00
91263b9dcf sane-secrets-dump: allow specifying the secret by name instead of full path 2024-07-26 20:05:51 +00:00
40e4d0f39c sane-secrets-dump: allow dumping specific fields, and in multiple formats 2024-07-26 19:56:18 +00:00
06a17e4425 moby: remove dead autologin code 2024-07-26 16:04:38 +00:00
cbca403158 hosts/common: downgrade the auto-login to lib.mkDefault
servo uses autologin as root, for the purpose of recovery. let it keep that for now
2024-07-26 16:04:13 +00:00
3b8d6c8587 refactor: s6/unl0kr/profile: put more shell init stuff directly in modules/users/default.nix when it doesnt benefit from being pluggable 2024-07-26 15:58:59 +00:00
d59380b4dd unl0kr: ensure it runs on the same tty the session was initialized on 2024-07-26 14:50:28 +00:00
f4df121e3d persist/private: s6: use systemd to explicitly start the mount, rather than assume it's already been initiated 2024-07-26 14:01:31 +00:00
3d91fa2475 systemd.networkd: disable the wait-online service
it blocks boot like a idiot
2024-07-26 14:01:31 +00:00
96f786de20 persist/private: fix so systemd actually knows when the mount has completed 2024-07-26 12:44:32 +00:00
fcbbfc4a65 fix s6 service ordering: unl0kr -> (wait for mount) -> sway
note that the systemd-aware mount never completes -- it's stuck in 'activating' forever. that's the next challenge
2024-07-26 12:18:14 +00:00
b93e9e75e6 unl0kr: use inotify in the retry logic 2024-07-26 11:31:53 +00:00
4daf5452e8 unl0kr: dont echo password to terminal 2024-07-26 09:36:06 +00:00
af905a2f58 unl0kr: split the gocryptfs unlocking into its own separate service
/mnt/persist/private can be depended on by both s6 user services and systemd system services (which will become useful for servo)

/mnt/persist/private can be unlocked by dropping the key in remotely, however that won't kill unl0kr

TODO: fix unl0kr to not also output text to the tty

TODO: ensure gocryptfs mount can handle being fed a wrong password
2024-07-26 08:08:21 +00:00
8ef5920d84 unl0kr: port to an s6 service
this has some drawbacks in its current form and will be tidied

it writes the password also to the consold. it requires 'sudo'.
2024-07-25 18:45:01 +00:00
b554d32133 fix permissions of /nix/persist/private, to be user-writable
this is important for my rsync-net backup scripts, which need to record timestamps in there
2024-07-25 18:42:45 +00:00
2203d6db59 cleanup: remove XDG_SESSION_TYPE, XDG_VTNR from global environment 2024-07-25 15:26:24 +00:00
07b55bb3ec unl0kr: dont run atop getty -- just a bare /dev/tty1
i'm not sure what agetty was ever doing here.
unl0kr itself runs fine, it launches ~/.profile, and if i interrupt ~/.profile to use a console, that works too.

the console does regularly get interrupted by systemd output,
but i've checked and the agetty method had that same program.
2024-07-25 14:48:15 +00:00
874b7aecfa persist: rename "cryptClearOnBoot" to "ephemeral" 2024-07-25 12:11:46 +00:00
cf8e9f798d persist/crypt: simplify the fileSystems definitions
turns out you can just declare your own fs type, that's cool
2024-07-25 12:11:46 +00:00
800945d951 sway: disable touchpad middle-click (i hope?) 2024-07-25 12:11:46 +00:00
4c3b0f820b feeds: unsubscribe from Vox, Post Reports (politics) 2024-07-25 08:41:13 +00:00
0756349c86 polyunfill: fix missing lvm2 2024-07-24 13:11:59 +00:00
490c587737 swaync-service-dispatcher: add up/down options 2024-07-24 11:49:15 +00:00
15df9edca1 swaync-service-dispatcher: add a usage command 2024-07-24 11:46:52 +00:00
2d73b85f92 gps-share: fix sandboxing
it's possible that the Avahi sandboxing isn't right. idk
2024-07-24 11:43:24 +00:00
70d4925483 gps-share: dont launch until after the modem is actually powered on 2024-07-24 11:15:44 +00:00
dda2ea6fcb nixpkgs: update patch hash 2024-07-24 10:00:30 +00:00
a165e568a8 mpv: tune controls for mobile (speculative) 2024-07-24 09:05:15 +00:00
a539e52abe mpv: disable visualizer; it breaks UI 2024-07-24 09:05:05 +00:00
e62df51258 todo.md: remove completed items 2024-07-24 08:29:16 +00:00
17e7c7d48b nixpkgs: update hashes 2024-07-24 08:29:08 +00:00
6f1173e45a sops-gpg-adapter: port to nix-shell 2024-07-24 08:28:13 +00:00
225c8de7a2 trust-dns: fix dyn-dns reactor (trust-dns-lan does not exist) 2024-07-24 07:18:29 +00:00
05f8dad425 nixpkgs-wayland: 2024-07-21 -> 2024-07-22 2024-07-24 06:46:27 +00:00
8b6971a164 nixpkgs: 2024-07-21 -> 2024-07-24 2024-07-24 06:38:40 +00:00
91359174f6 scripts/check-backups: be slightly more verbose -- at least until im more confident in this setup 2024-07-24 03:33:07 +00:00
b012b93d89 sane-vpn: port from bash -> python 2024-07-24 03:32:38 +00:00
34e770c5f5 sanebox: fix missing dependency on iptables/iproute2 2024-07-24 03:32:12 +00:00
0460a419c5 sane-vpn: use DHCP DNS servers when use specifies none -- instead of 1.1.1.1 2024-07-24 03:05:37 +00:00
79834aedf3 scripts/check-backups: init 2024-07-23 22:09:32 +00:00
2ca8bcda56 bonsai: 1.1.0 -> 1.2.0 2024-07-23 21:39:07 +00:00
8ced778def rsync.net backups: generate stamp files that let me verify that a backup has been attempted 2024-07-23 21:05:43 +00:00
d91ca22587 scripts/sync: add --verbose flag and support syncing multiple machines 2024-07-23 18:49:05 +00:00
a47b9d580a sane-tag-media: fix type-based filtering 2024-07-23 18:24:41 +00:00
fc8a54f39b sane-tag-media: leave a note to implement epub support in the future 2024-07-23 18:14:37 +00:00
3ae25fbe31 sane-tag-media: understand Adobe Acrobat publisher tag 2024-07-23 17:59:00 +00:00
36acc87f30 sane-tag-media: rename print-missing subcommand to show-missing, for consistency with show subcommand 2024-07-23 17:53:48 +00:00
5b7244d339 sane-tag-media: understand LibreOffice/OpenOffice publisher tag 2024-07-23 17:52:34 +00:00
9efa5bb209 sane-tag-music -> sane-tag-media, and formally support pdf 2024-07-23 17:42:25 +00:00
211486f60e pleroma: use sandboxed gawk instead of unsandboxed 2024-07-23 17:19:50 +00:00
b21002207a programs: ship exiftool 2024-07-23 17:19:50 +00:00
1fc0ae3066 nixpkgs: update contourpy patch hash 2024-07-23 17:19:50 +00:00
712cff2867 sane-tag-music: fix path-based tag derivation when path contains "." or ".." 2024-07-23 16:46:32 +00:00
a103cd819f sane-sync-music: fix flac -> opus conversion for surround sound media 2024-07-22 23:12:02 +00:00
553a2724a4 youtube-tui: docs: mention more invidious instances 2024-07-22 16:14:44 +00:00
bf0583cbda youtube-tui: update to a more reliable invidious instance 2024-07-22 16:00:51 +00:00
5a5842d26c nicotine-plus: fix so it can read its config file on first run 2024-07-22 15:51:40 +00:00
3f8f3f4e54 mpv: sponsorblock: also skip intros 2024-07-22 14:20:34 +00:00
4ad6c84d31 mpv: integrate with sponsorblock 2024-07-22 14:09:56 +00:00
8e215cba69 jackett: remove obsoleted patch
seems to work without? i guess i just didn't want to patch the service?
2024-07-22 12:10:21 +00:00
1e3b71def3 gpodder: enable yt-dlp 2024-07-22 11:36:32 +00:00
90b057af95 servo: jackett: remove unnecessary doCheck patch
i don't run jackett on arm anymore
2024-07-22 11:14:12 +00:00
4e35c09a85 jackett: apply patches only to the package as used by the service -- not all of nixpkgs 2024-07-22 11:10:30 +00:00
1e0034c66f sxmo-utils: remove 2024-07-22 11:02:58 +00:00
ae91b825e6 feeds: unsubscribe from The Daily
maybe check back in 2 years from now and see if it'll be more worthwhile news and less politics
2024-07-22 10:48:57 +00:00
3c8b3f2d04 programs: add "nix"
this allows me to get it to shup up about so-called 'non-free' packages
2024-07-22 10:46:31 +00:00
79fbdc4e15 scripts/sync: add a "sync all" option 2024-07-22 07:52:31 +00:00
284ea45648 mpv: tune the OSC menu controls 2024-07-22 07:34:56 +00:00
9c33cb44e2 nixpkgs: 2d155950622fbf78b85e7fa36e337f35316b6c39 -> b841e48094d6eaad953f36dc0831434966dc7719 2024-07-22 06:19:52 +00:00
77a9f47352 nixpkgs-wayland: 2024-07-20 -> 2024-07-21 2024-07-22 06:19:39 +00:00
04a5d38f79 syshud: 2024-07-16 -> 2024-07-21 2024-07-22 06:19:25 +00:00
452950d80b uassets: 2024-07-21 -> 2024-07-22 2024-07-22 06:19:06 +00:00
a79d9b1823 firefox-extensions.ublacklist: 8.9.0 -> 8.9.1 2024-07-22 06:18:49 +00:00
6e3a790a46 moby: enable rsync.net backups 2024-07-21 23:58:41 +00:00
7be997f597 moby: update password 2024-07-21 23:58:41 +00:00
ef1ee6c1c9 moby: document secrets 2024-07-21 23:58:41 +00:00
e196cea667 todo.md: not another trust-dns failure 2024-07-21 23:57:23 +00:00
105416990a 'sane-vpn do unmetered': route DNS to the host resolver 2024-07-21 23:56:56 +00:00
c0d1f7711a sanebox: pasta/bwrap: route DNS to the host's server if asked (via --sanebox-dns host) 2024-07-21 23:56:15 +00:00
f123be98b2 sane-vpn: specify missing sanebox dependency 2024-07-21 22:49:46 +00:00
15b0bba329 sanebox: implement --sanebox-pasta-arg, useful for debugging 2024-07-21 22:49:00 +00:00
734a4c7c31 todo.md: remove completed compass item 2024-07-21 21:51:41 +00:00
3ce2b44b7d sane-private-change-passwd: remove
use `gocrypt --passwd /nix/persist/private` instead
2024-07-21 21:48:31 +00:00
5f0eaa9771 sane-private-lock: fix mount point 2024-07-21 21:47:00 +00:00
cd7b36b761 sane-sync-music: target opus instead of mp3 when transcoding
opus supports surround sound
2024-07-21 21:46:18 +00:00
b72acef8ed pipewire: default to PIPEWIRE_DEBUG=3 2024-07-21 17:38:10 +00:00
74f2d4d174 pipewire: lift the surround sound functionality out of mpv 2024-07-21 16:54:26 +00:00
bedc9d4b2c signal-desktop-from-src: remove unnecessary --linux build flag 2024-07-21 15:02:03 +00:00
70b36fd79f signal-desktop-from-src: cleanup even more 2024-07-21 15:02:03 +00:00
7baed78b65 signal-desktop-from-src: remove extranous better-sqlite3 rebuild 2024-07-21 15:02:03 +00:00
7cca126efc signal-desktop-from-src: remove extraneous rebuild 2024-07-21 15:02:03 +00:00
433e8b8736 signal-desktop-from-src: simplify packaging -- just patch the dns fallback out 2024-07-21 15:02:03 +00:00
c026b8c40d signal-desktop-from-src: simplify build:release step 2024-07-21 15:02:03 +00:00
88df6b30ce signal-destop-from-src: 7.14.0 -> 7.16.0
upstream switched from yarn to npm, and for this kind of a package i'll seize the opportunity to use builNpmPackage instead of doing so much manually :-)
2024-07-21 15:02:03 +00:00
d324a57f06 uassets: 2024-07-19 -> 2024-07-21 2024-07-21 15:02:03 +00:00
55bed1926c sops-nix: 2024-07-14 -> 2024-07-21 2024-07-21 15:02:03 +00:00
8c9dcdb90f nipkgs-wayland: 2024-07-18 -> 2024-07-20 2024-07-21 15:02:03 +00:00
0ebcbe0ad5 nixpkgs: 2024-07-19 -> 2024-07-21 2024-07-21 15:02:03 +00:00
a9cbb2c092 servo: transmission/torrent-done: fix noisy file regexes 2024-07-21 11:25:54 +00:00
c5227c52c4 sane-sync-music: update file extensions list 2024-07-21 09:44:39 +00:00
0af5e43944 scripts/update: support gitUpdater-style updateScripts 2024-07-21 07:26:39 +00:00
cd16f8c3b6 sxmo-utils: disable auto-update via updateWithSuper attribute 2024-07-21 06:39:19 +00:00
0f7ec33dac scripts/update: cleanup 2024-07-21 06:36:21 +00:00
993c3df09e scripts/update: dont update sofacoustics package by default 2024-07-21 05:49:22 +00:00
fccb48cc2d mpv: ship the libmysofa HRTF file via $XDG_CONFIG_DIRS/share/libmysofa/default.sofa 2024-07-20 19:15:39 +00:00
64ddf15620 sofacoustics.ari: init 2024-07-20 19:13:55 +00:00
68ef56b572 mpv/ffmpeg: consolidate the different ffmpeg configs into overlays/preferences 2024-07-20 19:13:32 +00:00
99c19ceac0 nicotine-plus: use a different login than for slskd, to avoid having one kick the other off the net 2024-07-20 15:21:03 +00:00
f95f9a35fc nicotine: ship creds statically, as secrets 2024-07-20 15:16:31 +00:00
5f1ac2afac mpv: downmix surround sound to stereo using a HRTF-aware filter (sofa) 2024-07-20 13:44:33 +00:00
2ee53fd5be sofacoustics: prefix the .sofa file with the database from which it comes 2024-07-20 13:44:08 +00:00
9fb2cf4d42 sofacoustics.listen: init 2024-07-20 13:21:02 +00:00
612fa0cae8 sofacoustics.widespread: init 2024-07-20 12:39:22 +00:00
875e85c646 uassets: 2024-07-17 -> 2024-07-19 2024-07-20 03:28:38 +00:00
94ecca2967 nixpkgs-wayland: 2024-07-15 -> 2024-07-18 2024-07-20 03:28:29 +00:00
1fea424052 nixpkgs: 2024-07-17 -> 2024-07-19 2024-07-20 03:28:13 +00:00
4abd782b62 hosts/common: migrate most ~/ directories to the "private" persistence store 2024-07-19 20:16:04 +00:00
13b04d50b0 sane-backup-rsync-net: dont try to backup device files
the remote doesn't seem to support them (or maybe it's the protocol)
2024-07-19 20:14:33 +00:00
36b1178fc0 mpv: associate with imgur URLs 2024-07-19 20:13:55 +00:00
527e7029b9 hosts: migrate ~/Videos/local from plaintext -> private storage 2024-07-19 13:47:30 +00:00
18c07721d9 servo: enable rsync.net backups 2024-07-19 12:49:47 +00:00
6ac700811a lappy: enable rsync.net backups 2024-07-19 12:49:40 +00:00
cd62aa2f38 opencellid: update hashes 2024-07-19 12:44:09 +00:00
72a78c5f3e nicotine-plus: re-enable 2024-07-19 12:44:09 +00:00
db292850b0 modules/programs: fix sandbox.net = "vpn" option 2024-07-19 12:44:09 +00:00
8e6272bafd static-nix-shell: better enforce that all nix-shell deps are specified 2024-07-19 12:21:10 +00:00
90e1f4a447 desko: automated backups to rsync.net 2024-07-19 11:42:04 +00:00
31c32b9636 sane-vpn: add a way to route traffic specifically through unmetered connections 2024-07-19 07:31:54 +00:00
d6aef04a77 element-desktop: fix sandboxing of embedded audio files (esp flac files) 2024-07-19 07:27:33 +00:00
0f08f14dc0 todo.md: note another site that doesnt work for trust-dns recursive resolver 2024-07-19 04:17:29 +00:00
6d9806613c nixpkgs/patches: send contourpy fix upstream 2024-07-19 01:15:19 +00:00
c0c2aa00f3 lgtrombetta-compass: ship 2024-07-18 16:40:17 +00:00
6d5cd7b604 lgtrombetta-compass: fix cross compilation and enable strictDeps = true 2024-07-18 15:51:13 +00:00
98860ccf46 todo.md: make a note that newly-patched trust-dns still doesnt support abs.twimg.com 2024-07-18 13:54:43 +00:00
bc5805b341 lgtrombetta-compass: fix cross compilation 2024-07-18 13:54:14 +00:00
3a4d27c3bf templates: python: fix broken setup-hooks refs 2024-07-18 13:24:40 +00:00
c88ef43310 lgtrombetta-compass: init at 0.4.0
it doesn't cross compile yet, because of its dependencies (matplotlib -> contourpy)
2024-07-18 13:24:13 +00:00
326e71f7b1 sanebox: landlock: restrict net access where applicable 2024-07-18 11:54:10 +00:00
532d3c13f6 eza: sandbox with landlock instead of bwrap 2024-07-18 11:43:58 +00:00
9f26ad40f9 mimetype: sandbox (and remove unneeded mimeopen) 2024-07-18 11:43:45 +00:00
c8a99317bc syshud: 0-unstable-2024-07-15 -> 0-unstable-2024-07-16
this fixes the crash-on-start issue
2024-07-18 09:51:44 +00:00
2296e10f15 assorted: remove obsolete GSK_RENDERER=cairo patch 2024-07-18 08:45:44 +00:00
ca68434f18 komikku: fix sandboxing (missing ~/.cache.komikku) 2024-07-18 08:42:45 +00:00
a1de7a4afd users: configure XDG_SESSION_TYPE during shell setup 2024-07-18 00:15:29 +00:00
b692c0b6ce 2024-07-16 -> 2024-07-17 2024-07-17 23:57:29 +00:00
8ba1e35b9d nixpkgs: 2024-07-16 -> 2024-07-17 2024-07-17 23:57:16 +00:00
765ec610c9 schlock: update pin/hash 2024-07-17 16:24:29 +00:00
43c33fef21 schlock: patch for faster unlock (less intense password hashing) 2024-07-17 16:24:00 +00:00
9bcc7cd30b todo.md: sync 2024-07-17 16:16:23 +00:00
0b7d8310df trust-dns: patch resolver to handle more edge-case domains (api.mangadex.org., m.wikipedia.org., ...) 2024-07-17 15:28:41 +00:00
c6f07d4f55 sane-vpn: fix none option 2024-07-17 13:13:14 +00:00
94a0e77fcc sane-vpn: set the retry duration for sane-ip-check 2024-07-17 02:01:50 +00:00
91d5c20a56 sane-ip-check: make the retry loop configurable 2024-07-17 02:00:27 +00:00
9b898ce597 sane-ip-check: implement a retry loop 2024-07-17 02:00:27 +00:00
a49411c02d lftp: fix sandboxing 2024-07-17 02:00:05 +00:00
fcd13d4f6f sane-vpn: cleanup the CLI ergonomics 2024-07-17 02:00:05 +00:00
ef1be364e7 docs: sane-vpn: more usage 2024-07-17 02:00:05 +00:00
8472320629 sane-vpn: route DNS through the VPN's server 2024-07-17 02:00:05 +00:00
19acab1363 scripts/check-uninsane: remove outdated ovpns DNS test 2024-07-16 22:57:48 +00:00
98e1ae53e2 syshud: 2024-07-02 -> 2024-07-15 2024-07-16 22:55:39 +00:00
eb2321aa79 uassets: 2024-07-14 -> 2024-07-16 2024-07-16 22:55:26 +00:00
8febe70665 firefox-extensions.uassets: 8.8.3 -> 8.9.0 2024-07-16 22:55:08 +00:00
ee4ab3b40c nixpkgs-wayland: 2024-07-14 -> 2024-07-15 2024-07-16 22:54:49 +00:00
281643afb0 nixpkgs: 2024-07-15 -> 2024-07-16 2024-07-16 22:54:34 +00:00
86f1e36035 scripts/deploy: fix "exho" typo 2024-07-16 07:42:24 +00:00
929a8eadbc syshud: update config files/locations to match upstream 2024-07-16 07:38:49 +00:00
e355a4b2eb assorted: remove no-longer-needed sanebox PATH fixes 2024-07-16 07:24:56 +00:00
132798be23 sanebox: ensure sanebox is always on the PATH of sandboxed binaries 2024-07-16 07:24:42 +00:00
c72e66a901 curl: sandbox 2024-07-16 07:23:32 +00:00
40d32ec1d5 polyunfill: remove cpupower and kbd 2024-07-16 07:18:06 +00:00
1377f5c7bc servo: fix DNS; although it's getting DHCP routes via DHCP, it doesn't seem to be getting DNS?? 2024-07-16 05:16:07 +00:00
bee714311b servo: remove dead systemd networking code for the WAN IP 2024-07-16 04:13:08 +00:00
b368d4624e servo: configure so that LAN peers can reach me at my WAN IP
on the router side this requires either (a) telling the router to use the doof IP as a gateway and also declaring that route or (b) using DHCP option 121. really, one should do both -- the first for the router, and the second for peers connected via switches
2024-07-16 04:13:06 +00:00
583f7217fc docs: rofi: mention rofi-calc 2024-07-16 00:46:19 +00:00
e8b0979de6 sane-sync-from-iphone: fix perms
without fusermount3 wrapper, i have to use sudo
2024-07-15 23:40:48 +00:00
c4b4ac48fd nixpkgs: 2024-07-14 -> 2024-07-15 2024-07-15 10:53:00 +00:00
8436ba3e02 todo.md: item for fixing transmission torrent-done paths 2024-07-15 02:02:05 +00:00
8b1f91ca86 servo: transmission: fix service config so my torrent-done script doesnt crash 2024-07-15 01:35:45 +00:00
73f6907e9a nixpkgs: fix unl0kr patch
maybe i'll push the PR through just so i don't have to deal with unstable patch hashes, wtf
2024-07-15 00:30:02 +00:00
d6bfef7657 linux-megous: add missing patch to git 2024-07-15 00:22:48 +00:00
0fafd81b79 scripts/sync: sanity check that source directory exists before doing a sync (else we would delete everything in the target) 2024-07-15 00:22:29 +00:00
2ac9c2cb68 fix NUR integration (hopefully) 2024-07-15 00:17:59 +00:00
e8547cc849 nixpkgs: fix unl0kr hash ... AGAIN (i'm beginning to think it's unstable) 2024-07-15 00:17:43 +00:00
3495f04810 preferences: remove unnecessary miniupnpc patch 2024-07-14 22:35:32 +00:00
68a891f6de firefox-extensions.{metamask,i2p-in-private-browsing,ublacklist} -> latest 2024-07-14 22:10:58 +00:00
b8dbc0c1c0 uassets: 2024-07-06 -> 2024-07-14 2024-07-14 22:10:31 +00:00
6964cf8d46 nixpkgs-wayland: 2024-07-05 -> 2024-07-14 2024-07-14 22:10:18 +00:00
c959c0a74a sops-nix: 2024-07-05 -> 2024-07-14 2024-07-14 22:10:01 +00:00
7b0a4c11ec nixpkgs: 2024-07-10 -> 2024-07-14 2024-07-14 22:09:44 +00:00
a926cbee46 scripts/update: build required nix binary before updating packages 2024-07-14 22:09:19 +00:00
23d8990596 todo.md: todo: install a compass app 2024-07-14 22:08:43 +00:00
76ae404827 scripts/sync: fix moby Photos dir 2024-07-14 09:19:17 +00:00
e868e28ed9 sc-im: ship 2024-07-14 03:45:18 +00:00
2283a5b167 mpv: associate with youtube playlist URLs 2024-07-14 03:13:15 +00:00
8d0b7c5855 nixpkgs: fix unl0kr patch hash (... didnt i just do this?) 2024-07-14 03:09:53 +00:00
3fb7fe34c4 rofi: fix so apps with "Terminal=true" can launch via xdg portal 2024-07-14 02:59:26 +00:00
10687a80e4 FIXUP: add missing youtube-tui.nix file to git 2024-07-14 02:59:05 +00:00
a8bcfaed53 youtube-tui: ship 2024-07-14 02:39:38 +00:00
ab200f8988 mpv: associate with youtube embed URLs 2024-07-14 01:33:52 +00:00
b443fd46d8 sway: map caps -> esc 2024-07-13 23:53:50 +00:00
0473822172 nixpkgs: fix patch hashes 2024-07-13 23:53:43 +00:00
d0b5f586c4 nwg-panel: fix multiple instances on display change 2024-07-13 21:01:06 +00:00
f6895393d9 zsh: alias "quit" to "exit" 2024-07-13 20:37:02 +00:00
f78b49f075 scripts/sync: moby: dont compress music (i have enough space for that now) 2024-07-13 18:58:02 +00:00
aa3115d2ca sane-sync-music: limit jobs to just 1 by default 2024-07-13 08:40:19 +00:00
924a6c812c all/net: disable "predictable" interface names 2024-07-13 08:29:48 +00:00
fd50bf6422 desko: disable wifi again
specifically, ethernet DHCP renewals break because the wlan interface advertises the eth MAC (?)
2024-07-13 08:29:14 +00:00
7c0e7cbb71 wg-home: rewrite forwarding rules to avoid naming any interface 2024-07-13 08:28:02 +00:00
26004da704 wg-home: iptables: use extended switch names 2024-07-13 08:07:21 +00:00
7013b09715 scripts/sync: fix nix-shell shebang 2024-07-13 07:43:16 +00:00
3969fd484b networkmanager: 1.48.0 -> 1.48.2 (unpin) 2024-07-13 05:00:43 +00:00
eeab1d9fda sane-tag-music: strip non-breaking spaces from metadata 2024-07-13 05:00:03 +00:00
deb355d960 sane-tag-music: better romanization 2024-07-13 04:50:32 +00:00
1d4df82bde sane-tag-music: improve idempotency 2024-07-13 04:20:37 +00:00
f49e87cf99 sane-tag-music: allow clearing *any* tag manually 2024-07-13 03:43:45 +00:00
e38c2f20e8 sane-tag-music: include the artist in the filename for compilation albums 2024-07-13 02:47:09 +00:00
0e5f01f240 sane-tag-music: refactor: remove extraneous "Various Artists" check 2024-07-13 01:53:05 +00:00
e04dd6cb7d sane-tag-music: better log formatting when moving a file 2024-07-13 01:44:28 +00:00
f4b6bbfbd5 sane-tag-music: ignore "Xerox" when found in the producer field 2024-07-13 00:55:33 +00:00
2e8c58a53d sane-tag-music: allow "info.txt" as an artist-associated item 2024-07-12 20:12:27 +00:00
f6e326869f sane-tag-music: tag derivation logic is recursive/hierarchical
so Artist/Album/Track.flac will draw from Artist/Album/* and then Artist/*
2024-07-12 08:48:51 +00:00
c16f2473e5 sane-tag-music: handle multiple CLI paths by iterating a layer above 2024-07-12 08:48:51 +00:00
d85ffa8539 sane-tag-music: refactor: separate the file walking into its own abstraction
i hope this will allow more sophisticated tag derivation
2024-07-12 08:48:51 +00:00
987cd93ce3 sane-tag-music: allow deriving tags for all operations, not just fix-tags 2024-07-12 08:48:51 +00:00
e82faa5961 sane-tag-music: add a method which generalizes tags to one file from the rest of the album (e.g. the album name) 2024-07-12 08:48:51 +00:00
514cfe7b0b feeds: subscribe to "Better Offline" podcast 2024-07-12 01:20:00 +00:00
dd2eb66875 sane-tag-music: fix "producer" handling for aac files 2024-07-12 00:04:24 +00:00
6ccdbf50cd sane-tag-music: print results in real-time 2024-07-11 23:59:31 +00:00
e2cca54e08 sane-tag-music: support PDFs 2024-07-11 23:58:58 +00:00
721f45f7d4 sane-tag-music: dont abort if metadata fails to load 2024-07-11 23:33:02 +00:00
774ebd23f9 sane-tag-music: jpg/png: use XMP tags for album/producer instead of weird exif tags 2024-07-11 21:39:47 +00:00
bfdacb1941 sane-tag-music: gif: support album, albumartist, producer tags 2024-07-11 21:38:55 +00:00
beeb5d34b0 sane-tag-music: refactor: introduce a generic tag name mapping layer 2024-07-11 21:22:44 +00:00
3d3faba263 sane-tag-music: support mp4/m4a; support "producer" tag (grouping) for mp3/mp4 2024-07-11 20:05:53 +00:00
a56795ff79 sane-tag-music: fix sandboxing to support renaming 2024-07-11 19:12:55 +00:00
00d644ef07 sane-tag-music: support "artist.png" artist images 2024-07-11 03:30:42 +00:00
672de68e56 sane-tag-music: allow clearing any tag 2024-07-11 02:53:00 +00:00
e47bc4c04d sane-tag-music: dont set the VA producer tag if the VA album tag is also set 2024-07-10 17:56:10 +00:00
0b6a8eecce sane-tag-music: handle more "Various Artists" formats 2024-07-10 17:30:41 +00:00
eaaea26603 sane-tag-music: allow deleting producer by setting it empty 2024-07-10 08:31:03 +00:00
e1c80c9abc sane-tag-music: remove special-casing for Singles 2024-07-10 08:10:29 +00:00
272 changed files with 30977 additions and 17511 deletions

65
TODO.md
View File

@@ -2,18 +2,22 @@
- `rmDbusServices` may break sandboxing - `rmDbusServices` may break sandboxing
- e.g. if the package ships a systemd unit which references $out, then make-sandboxed won't properly update that unit. - e.g. if the package ships a systemd unit which references $out, then make-sandboxed won't properly update that unit.
- `rmDbusServicesInPlace` is not affected - `rmDbusServicesInPlace` is not affected
- when moby wlan is explicitly set down (via ip link set wlan0 down), /var/lib/trust-dns/dhcp-configs doesn't get reset - when moby wlan is explicitly set down (via ip link set wlan0 down), /var/lib/hickory-dns/dhcp-configs doesn't get reset
- `ip monitor` can detect those manual link state changes (NM-dispatcher it seems cannot) - `ip monitor` can detect those manual link state changes (NM-dispatcher it seems cannot)
- or try dnsmasq? - or try dnsmasq?
- trust-dns: can't recursively resolve api.mangadex.org - hickory-dns can't resolve `abs.twimg.com`
- nor `m.wikipedia.org` (`dyna.wikipedia.org`) - hickory-dns can't resolve `social.kernel.org`
- and *sometimes* apple.com fails - hickory-dns can't resolve `pe.usps.com`
- hickory-dns can't resolve `social.seattle.wa.us`
- hickory-dns can't resolve `support.mozilla.org`
- sandbox: link cache means that if i update ~/.config/... files inline, sandboxed programs still see the old version - sandbox: link cache means that if i update ~/.config/... files inline, sandboxed programs still see the old version
- mpv: continues to play past the end of some audio files
- mpv: audiocast has mpv sending its output to the builtin speakers unless manually changed - mpv: audiocast has mpv sending its output to the builtin speakers unless manually changed
- mpv: no way to exit fullscreen video on moby
- uosc hides controls on FS, and touch doesn't support unhiding
- `ssh` access doesn't grant same linux capabilities as login - `ssh` access doesn't grant same linux capabilities as login
- syshud (volume overlay): when casting with `blast`, syshud doesn't react to volume changes - syshud (volume overlay): when casting with `blast`, syshud doesn't react to volume changes
- moby: after bringing the modem up, powering it down loses *complete* net connectivity (i.e. wlan is gone as well)
- dissent: if i launch it without net connectivity, it gets stuck at the login, and never tries again
- calls: seems that it starts before net access, and then is forever disconnected (until i manually restart it)
- moby: kaslr is effectively disabled - moby: kaslr is effectively disabled
- `dmesg | grep "KASLR disabled due to lack of seed"` - `dmesg | grep "KASLR disabled due to lack of seed"`
- fix by adding `kaslrseed` to uboot script before `booti` - fix by adding `kaslrseed` to uboot script before `booti`
@@ -24,16 +28,21 @@
- `dmesg | grep 'hid_bpf: error while preloading HID BPF dispatcher: -22'` - `dmesg | grep 'hid_bpf: error while preloading HID BPF dispatcher: -22'`
- `s6` is not re-entrant - `s6` is not re-entrant
- so if the desktop crashes, the login process from `unl0kr` fails to re-launch the GUI - so if the desktop crashes, the login process from `unl0kr` fails to re-launch the GUI
- nwg-panel will sometimes create nested bars (happens maybe when i turn an external display off, then on?) - newflash on moby can't play videos
- wg-home is unreachable for a couple minutes when switching between LAN/WAN/3G - "open in browser" works though -- in mpv
- because the endpoint DNS changes. - gnome-maps can't use geoclue *and* openstreetmap at the same time
- causes calls to not transfer from WiFi -> cellular. - get gnome-maps to speak xdg-desktop-portal, and this will be fixed
- epiphany can't save cookies
- see under "preferences", cookies are disabled
- prevents logging into websites (OpenStreetMap)
- works when sandbox is disabled
## REFACTORING: ## REFACTORING:
- add import checks to my Python nix-shell scripts - add import checks to my Python nix-shell scripts
- consolidate ~/dev and ~/ref - consolidate ~/dev and ~/ref
- ~/dev becomes a link to ~/ref/cat/mine - ~/dev becomes a link to ~/ref/cat/mine
- fold hosts/common/home/ssh.nix -> hosts/common/users/colin.nix - fold hosts/common/home/ssh.nix -> hosts/common/users/colin.nix
- don't hardcode IP addresses so much in servo
### sops/secrets ### sops/secrets
- rework secrets to leverage `sane.fs` - rework secrets to leverage `sane.fs`
@@ -53,22 +62,26 @@
## IMPROVEMENTS: ## IMPROVEMENTS:
- systemd/journalctl: use a less shit pager
- there's an env var for it: SYSTEMD_PAGER? and a flag for journalctl
- kernels: ship the same kernel on every machine - kernels: ship the same kernel on every machine
- then i can tune the kernels for hardening, without duplicating that work 4 times - then i can tune the kernels for hardening, without duplicating that work 4 times
- zfs: replace this with something which doesn't require a custom kernel build - zfs: replace this with something which doesn't require a custom kernel build
- mpv: add media looping controls (e.g. loop song, loop playlist) - mpv: add media looping controls (e.g. loop song, loop playlist)
- curlftpfs: replace with something better
- safer (rust? actively maintained? sandboxable?)
- handles spaces/symbols in filenames
- has better multi-stream perf (e.g. `sane-sync-music` should be able to copy N items in parallel)
- firefox: open *all* links (http, https, ...) with system handler
- removes the need for open-in-mpv, firefox-xdg-open, etc.
- matrix room links *just work*.
- `network.protocol-handler.external.https = true` in about:config *seems* to do this,
but breaks some webpages (e.g. Pleroma)
### security/resilience ### security/resilience
- validate duplicity backups! - enable `snapper` btrfs snapshots (`services.snapper`)
- encrypt more ~ dirs (~/archives, ~/records, ..?)
- best to do this after i know for sure i have good backups
- /mnt/desko/home, etc, shouldn't include secrets (~/private) - /mnt/desko/home, etc, shouldn't include secrets (~/private)
- 95% of its use is for remote media access and stuff which isn't in VCS (~/records) - 95% of its use is for remote media access and stuff which isn't in VCS (~/records)
- port all sane.programs to be sandboxed - port all sane.programs to be sandboxed
- sandbox `curlftpfs` - sandbox `nix`
- sandbox `sshfs-fuse`
- enforce that all `environment.packages` has a sandbox profile (or explicitly opts out) - enforce that all `environment.packages` has a sandbox profile (or explicitly opts out)
- revisit "non-sandboxable" apps and check that i'm not actually just missing mountpoints - revisit "non-sandboxable" apps and check that i'm not actually just missing mountpoints
- LL_FS_RW=/ isn't enough -- need all mount points like `=/:/proc:/sys:...`. - LL_FS_RW=/ isn't enough -- need all mount points like `=/:/proc:/sys:...`.
@@ -77,8 +90,6 @@
- lock down dbus calls within the sandbox - lock down dbus calls within the sandbox
- otherwise anyone can `systemd-run --user ...` to potentially escape a sandbox - otherwise anyone can `systemd-run --user ...` to potentially escape a sandbox
- <https://github.com/flatpak/xdg-dbus-proxy> - <https://github.com/flatpak/xdg-dbus-proxy>
- remove `.ssh` access from Firefox!
- limit access to `~/knowledge/secrets` through an agent that requires GUI approval, so a firefox exploit can't steal all my logins
- port sanebox to a compiled language (hare?) - port sanebox to a compiled language (hare?)
- it adds like 50-70ms launch time _on my laptop_. i'd hate to know how much that is on the pinephone. - it adds like 50-70ms launch time _on my laptop_. i'd hate to know how much that is on the pinephone.
- make dconf stuff less monolithic - make dconf stuff less monolithic
@@ -92,14 +103,13 @@
- cleanup waybar/nwg-panel so that it's not invoking playerctl every 2 seconds - cleanup waybar/nwg-panel so that it's not invoking playerctl every 2 seconds
- nwg-panel: doesn't know that virtual-desktop 10/TV exists - nwg-panel: doesn't know that virtual-desktop 10/TV exists
- install apps: - install apps:
- compass viewer (moby)
- display QR codes for WiFi endpoints: <https://linuxphoneapps.org/apps/noappid.wisperwind.wifi2qr/> - display QR codes for WiFi endpoints: <https://linuxphoneapps.org/apps/noappid.wisperwind.wifi2qr/>
- shopping list (not in nixpkgs): <https://linuxphoneapps.org/apps/ro.hume.cosmin.shoppinglist/> - shopping list (not in nixpkgs): <https://linuxphoneapps.org/apps/ro.hume.cosmin.shoppinglist/>
- offline Wikipedia (or, add to `wike`) - offline Wikipedia (or, add to `wike`)
- offline docs viewer (gtk): <https://github.com/workbenchdev/Biblioteca> - offline docs viewer (gtk): <https://github.com/workbenchdev/Biblioteca>
- some type of games manager/launcher - some type of games manager/launcher
- Gnome Highscore (retro games)?: <https://gitlab.gnome.org/World/highscore> - Gnome Highscore (retro games)?: <https://gitlab.gnome.org/World/highscore>
- better maps for mobile (Osmin (QtQuick)? Pure Maps (Qt/Kirigami)? - better maps for mobile (Osmin (QtQuick)? Pure Maps (Qt/Kirigami)?)
- note-taking app: <https://linuxphoneapps.org/categories/note-taking/> - note-taking app: <https://linuxphoneapps.org/categories/note-taking/>
- Folio is nice, uses standard markdown, though it only supports flat repos - Folio is nice, uses standard markdown, though it only supports flat repos
- OSK overlay specifically for mobile gaming - OSK overlay specifically for mobile gaming
@@ -117,18 +127,17 @@
#### moby #### moby
- fix cpuidle (gets better power consumption): <https://xnux.eu/log/077.html> - fix cpuidle (gets better power consumption): <https://xnux.eu/log/077.html>
- fix cpupower for better power/perf
- `journalctl -u cpupower --boot` (problem is present on lappy, at least)
- moby: tune keyboard layout - moby: tune keyboard layout
- SwayNC: - SwayNC: add option to change audio output
- don't show MPRIS if no players detected
- this is a problem of playerctld, i guess
- add option to change audio output
- moby: tune GPS - moby: tune GPS
- fix iio-sensor-proxy magnetometer scaling - fix iio-sensor-proxy magnetometer scaling
- tune QGPS setting in eg25-control, for less jitter? - tune QGPS setting in eg25-control, for less jitter?
- configure geoclue to do some smoothing? - configure geoclue to do some smoothing?
- manually do smoothing, as some layer between mepo and geoclue? - manually do smoothing, as some layer between mepo and geoclue?
- email wigle.net people to unlock API access
- moby: port `freshen-agps` timer service to s6 (maybe i want some `s6-cron` or something) - moby: port `freshen-agps` timer service to s6 (maybe i want some `s6-cron` or something)
- moby: show battery state on ssh login
- moby: improve gPodder launch time - moby: improve gPodder launch time
- moby: theme GTK apps (i.e. non-adwaita styles) - moby: theme GTK apps (i.e. non-adwaita styles)
- especially, make the menubar collapsible - especially, make the menubar collapsible
@@ -137,6 +146,8 @@
#### non-moby #### non-moby
- RSS: integrate a paywall bypass - RSS: integrate a paywall bypass
- e.g. self-hosted [ladder](https://github.com/everywall/ladder) (like 12ft.io) - e.g. self-hosted [ladder](https://github.com/everywall/ladder) (like 12ft.io)
- RSS: have podcasts get downloaded straight into ~/Videos/...
- and strip the ads out using Whisper transcription + asking a LLM where the ad breaks are
- neovim: set up language server (lsp; rnix-lsp; nvim-lspconfig) - neovim: set up language server (lsp; rnix-lsp; nvim-lspconfig)
- neovim: integrate LLMs - neovim: integrate LLMs
- Helix: make copy-to-system clipboard be the default - Helix: make copy-to-system clipboard be the default
@@ -149,6 +160,8 @@
- have xdg-open parse `<repo:...> URIs (or adjust them so that it _can_ parse) - have xdg-open parse `<repo:...> URIs (or adjust them so that it _can_ parse)
- sane-bt-search: show details like 5.1 vs stereo, h264 vs h265 - sane-bt-search: show details like 5.1 vs stereo, h264 vs h265
- maybe just color these "keywords" in all search results? - maybe just color these "keywords" in all search results?
- transmission: apply `sane-tag-media` path fix in `torrent-done` script
- many .mkv files do appear to be tagged: i'd just need to add support in my own tooling
- uninsane.org: make URLs relative to allow local use (and as offline homepage) - uninsane.org: make URLs relative to allow local use (and as offline homepage)
- email: fix so that local mail doesn't go to junk - email: fix so that local mail doesn't go to junk
- git sendmail flow adds the DKIM signatures, but gets delivered locally w/o having the sig checked, so goes into Junk - git sendmail flow adds the DKIM signatures, but gets delivered locally w/o having the sig checked, so goes into Junk

View File

@@ -4,15 +4,19 @@
./fs.nix ./fs.nix
]; ];
sane.services.trust-dns.asSystemResolver = false; # TEMPORARY: TODO: re-enable trust-dns sane.services.hickory-dns.asSystemResolver = false; # TEMPORARY: TODO: re-enable hickory-dns
# sane.programs.devPkgs.enableFor.user.colin = true; # sane.programs.devPkgs.enableFor.user.colin = true;
# sane.guest.enable = true; # sane.guest.enable = true;
# don't enable wifi by default: it messes with connectivity. # don't enable wifi by default: it messes with connectivity.
# systemd.services.iwd.enable = false; # systemd.services.iwd.enable = false;
# networking.wireless.enable = false;
# systemd.services.wpa_supplicant.enable = false; # systemd.services.wpa_supplicant.enable = false;
sane.programs.wpa_supplicant.enableFor.user.colin = lib.mkForce false; # sane.programs.wpa_supplicant.enableFor.user.colin = lib.mkForce false;
sane.programs.wpa_supplicant.enableFor.system = lib.mkForce false; # sane.programs.wpa_supplicant.enableFor.system = lib.mkForce false;
# don't auto-connect to wifi networks
# see: <https://networkmanager.dev/docs/api/latest/NetworkManager.conf.html#device-spec>
networking.networkmanager.unmanaged = [ "type:wifi" ];
sops.secrets.colin-passwd.neededForUsers = true; sops.secrets.colin-passwd.neededForUsers = true;
@@ -24,10 +28,13 @@
sane.services.wg-home.ip = config.sane.hosts.by-name."desko".wg-home.ip; sane.services.wg-home.ip = config.sane.hosts.by-name."desko".wg-home.ip;
sane.ovpn.addrV4 = "172.26.55.21"; sane.ovpn.addrV4 = "172.26.55.21";
# sane.ovpn.addrV6 = "fd00:0000:1337:cafe:1111:1111:20c1:a73c"; # sane.ovpn.addrV6 = "fd00:0000:1337:cafe:1111:1111:20c1:a73c";
sane.services.duplicity.enable = true; sane.services.rsync-net.enable = true;
sane.nixcache.remote-builders.desko = false; sane.nixcache.remote-builders.desko = false;
sane.programs.sane-private-unlock-remote.enableFor.user.colin = true;
sane.programs.sane-private-unlock-remote.config.hosts = [ "servo" ];
sane.programs.sway.enableFor.user.colin = true; sane.programs.sway.enableFor.user.colin = true;
sane.programs.iphoneUtils.enableFor.user.colin = true; sane.programs.iphoneUtils.enableFor.user.colin = true;
sane.programs.steam.enableFor.user.colin = true; sane.programs.steam.enableFor.user.colin = true;
@@ -45,15 +52,18 @@
# needed to use libimobiledevice/ifuse, for iphone sync # needed to use libimobiledevice/ifuse, for iphone sync
services.usbmuxd.enable = true; services.usbmuxd.enable = true;
# TODO: enable snapper (need to make `/nix` or `/nix/persist` a subvolume, somehow).
# default config: https://man.archlinux.org/man/snapper-configs.5 # default config: https://man.archlinux.org/man/snapper-configs.5
# defaults to something like: # defaults to something like:
# - hourly snapshots # - hourly snapshots
# - auto cleanup; keep the last 10 hourlies, last 10 daylies, last 10 monthlys. # - auto cleanup; keep the last 10 hourlies, last 10 daylies, last 10 monthlys.
services.snapper.configs.nix = { # to list snapshots: `sudo snapper --config nix list`
# TODO: for the impermanent setup, we'd prefer to just do /nix/persist, # to take a snapshot: `sudo snapper --config nix create`
# but that also requires setting up the persist dir as a subvol # services.snapper.configs.nix = {
SUBVOLUME = "/nix"; # # TODO: for the impermanent setup, we'd prefer to just do /nix/persist,
# TODO: ALLOW_USERS doesn't seem to work. still need `sudo snapper -c nix list` # # but that also requires setting up the persist dir as a subvol
ALLOW_USERS = [ "colin" ]; # SUBVOLUME = "/nix";
}; # # TODO: ALLOW_USERS doesn't seem to work. still need `sudo snapper -c nix list`
# ALLOW_USERS = [ "colin" ];
# };
} }

View File

@@ -15,6 +15,9 @@
# sane.guest.enable = true; # sane.guest.enable = true;
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ]; sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
sane.programs.sane-private-unlock-remote.enableFor.user.colin = true;
sane.programs.sane-private-unlock-remote.config.hosts = [ "servo" ];
sane.programs.stepmania.enableFor.user.colin = true; sane.programs.stepmania.enableFor.user.colin = true;
sane.programs.sway.enableFor.user.colin = true; sane.programs.sway.enableFor.user.colin = true;
@@ -23,14 +26,20 @@
sops.secrets.colin-passwd.neededForUsers = true; sops.secrets.colin-passwd.neededForUsers = true;
sane.services.rsync-net.enable = true;
# TODO: enable snapper (need to make `/nix` or `/nix/persist` a subvolume, somehow).
# default config: https://man.archlinux.org/man/snapper-configs.5 # default config: https://man.archlinux.org/man/snapper-configs.5
# defaults to something like: # defaults to something like:
# - hourly snapshots # - hourly snapshots
# - auto cleanup; keep the last 10 hourlies, last 10 daylies, last 10 monthlys. # - auto cleanup; keep the last 10 hourlies, last 10 daylies, last 10 monthlys.
services.snapper.configs.nix = { # to list snapshots: `sudo snapper --config nix list`
# TODO: for the impermanent setup, we'd prefer to just do /nix/persist, # to take a snapshot: `sudo snapper --config nix create`
# but that also requires setting up the persist dir as a subvol # services.snapper.configs.nix = {
SUBVOLUME = "/nix"; # # TODO: for the impermanent setup, we'd prefer to just do /nix/persist,
ALLOW_USERS = [ "colin" ]; # # but that also requires setting up the persist dir as a subvol
}; # SUBVOLUME = "/nix";
# # TODO: ALLOW_USERS doesn't seem to work. still need `sudo snapper -c nix list`
# ALLOW_USERS = [ "colin" ];
# };
} }

View File

@@ -23,10 +23,11 @@
# XXX colin: phosh doesn't work well with passwordless login, # XXX colin: phosh doesn't work well with passwordless login,
# so set this more reliable default password should anything go wrong # so set this more reliable default password should anything go wrong
users.users.colin.initialPassword = "147147"; users.users.colin.initialPassword = "147147";
# services.getty.autologinUser = "root"; # allows for emergency maintenance?
sops.secrets.colin-passwd.neededForUsers = true; sops.secrets.colin-passwd.neededForUsers = true;
sane.services.rsync-net.enable = true;
sane.programs.sway.enableFor.user.colin = true; sane.programs.sway.enableFor.user.colin = true;
sane.programs.sway.config.mod = "Mod1"; #< alt key instead of Super sane.programs.sway.config.mod = "Mod1"; #< alt key instead of Super
sane.programs.blueberry.enableFor.user.colin = false; # bluetooth manager: doesn't cross compile! sane.programs.blueberry.enableFor.user.colin = false; # bluetooth manager: doesn't cross compile!

View File

@@ -14,14 +14,14 @@
# sane.programs.matrix-synapse.enableFor.user.colin = true; # sane.programs.matrix-synapse.enableFor.user.colin = true;
sane.roles.build-machine.enable = true; sane.roles.build-machine.enable = true;
sane.programs.zsh.config.showDeadlines = false; # ~/knowledge doesn't always exist sane.programs.sane-deadlines.config.showOnLogin = false; # ~/knowledge doesn't always exist
sane.programs.consoleUtils.suggestedPrograms = [ sane.programs.consoleUtils.suggestedPrograms = [
"consoleMediaUtils" # notably, for go2tv / casting "consoleMediaUtils" # notably, for go2tv / casting
"pcConsoleUtils" "pcConsoleUtils"
"sane-scripts.stop-all-servo" "sane-scripts.stop-all-servo"
]; ];
sane.services.dyn-dns.enable = true; sane.services.dyn-dns.enable = true;
sane.services.trust-dns.asSystemResolver = false; # TODO: enable once it's all working well sane.services.hickory-dns.asSystemResolver = false; # TODO: enable once it's all working well
sane.services.wg-home.enable = true; sane.services.wg-home.enable = true;
sane.services.wg-home.visibleToWan = true; sane.services.wg-home.visibleToWan = true;
sane.services.wg-home.forwardToWan = true; sane.services.wg-home.forwardToWan = true;
@@ -31,11 +31,12 @@
# sane.ovpn.addrV6 = "fd00:0000:1337:cafe:1111:1111:8df3:14b0"; # sane.ovpn.addrV6 = "fd00:0000:1337:cafe:1111:1111:8df3:14b0";
sane.nixcache.remote-builders.desko = false; sane.nixcache.remote-builders.desko = false;
sane.nixcache.remote-builders.servo = false; sane.nixcache.remote-builders.servo = false;
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade sane.services.rsync-net.enable = true;
# automatically log in at the virtual consoles. # automatically log in at the virtual consoles.
# using root here makes sure we always have an escape hatch # using root here makes sure we always have an escape hatch.
services.getty.autologinUser = "root"; # XXX(2024-07-27): this is incompatible with my s6-rc stuff, which needs to auto-login as `colin` to start its user services.
# services.getty.autologinUser = "root";
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ]; sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];

View File

@@ -14,7 +14,7 @@
# show zfs datasets: `zfs list` (will be empty if haven't imported) # show zfs datasets: `zfs list` (will be empty if haven't imported)
# show zfs properties (e.g. compression): `zfs get all pool` # show zfs properties (e.g. compression): `zfs get all pool`
# set zfs properties: `zfs set compression=on pool` # set zfs properties: `zfs set compression=on pool`
{ ... }: { lib, pkgs, ... }:
{ {
# hostId: not used for anything except zfs guardrail? # hostId: not used for anything except zfs guardrail?
@@ -131,6 +131,20 @@
the contents should be a subset of what's in ../media/datasets. the contents should be a subset of what's in ../media/datasets.
''; '';
systemd.services.dedupe-media = {
description = "transparently de-duplicate /var/media entries by using block-level hardlinks";
script = ''
${lib.getExe' pkgs.util-linux "hardlink"} /var/media --reflink=always --ignore-time --verbose
'';
};
systemd.timers.dedupe-media = {
wantedBy = [ "multi-user.target" ];
timerConfig = {
OnStartupSec = "23min";
OnUnitActiveSec = "720min";
};
};
# btrfs doesn't easily support swapfiles # btrfs doesn't easily support swapfiles
# swapDevices = [ # swapDevices = [
# { device = "/nix/persist/swapfile"; size = 4096; } # { device = "/nix/persist/swapfile"; size = 4096; }

View File

@@ -30,6 +30,14 @@ in
config = { config = {
networking.domain = "uninsane.org"; networking.domain = "uninsane.org";
systemd.network.networks."50-eth0" = {
matchConfig.Name = "eth0";
networkConfig.Address = [
"205.201.63.12/32"
"10.78.79.51/22"
];
networkConfig.DNS = [ "10.78.79.1" ];
};
sane.ports.openFirewall = true; sane.ports.openFirewall = true;
sane.ports.openUpnp = true; sane.ports.openUpnp = true;

View File

@@ -20,6 +20,7 @@ let
bitcoind = pkgs.bitcoind; bitcoind = pkgs.bitcoind;
# wrapper to run bitcoind with the tor onion address as externalip (computed at runtime) # wrapper to run bitcoind with the tor onion address as externalip (computed at runtime)
_bitcoindWithExternalIp = pkgs.writeShellScriptBin "bitcoind" '' _bitcoindWithExternalIp = pkgs.writeShellScriptBin "bitcoind" ''
set -xeu
externalip="$(cat /var/lib/tor/onion/bitcoind/hostname)" externalip="$(cat /var/lib/tor/onion/bitcoind/hostname)"
exec ${bitcoind}/bin/bitcoind "-externalip=$externalip" "$@" exec ${bitcoind}/bin/bitcoind "-externalip=$externalip" "$@"
''; '';
@@ -63,23 +64,62 @@ in
passwordHMAC = "30002c05d82daa210550e17a182db3f3$6071444151281e1aa8a2729f75e3e2d224e9d7cac3974810dab60e7c28ffaae4"; passwordHMAC = "30002c05d82daa210550e17a182db3f3$6071444151281e1aa8a2729f75e3e2d224e9d7cac3974810dab60e7c28ffaae4";
}; };
extraConfig = '' extraConfig = ''
# checkblocks: default 6: how many blocks to verify on start
checkblocks=3
# don't load the wallet, and disable wallet RPC calls # don't load the wallet, and disable wallet RPC calls
disablewallet=1 disablewallet=1
# proxy all outbound traffic through Tor # proxy all outbound traffic through Tor
proxy=127.0.0.1:9050 proxy=127.0.0.1:9050
''; '';
extraCmdlineOptions = [
# "-debug"
# "-debug=estimatefee"
# "-debug=http"
# "-debug=net"
"-debug=proxy"
"-debug=rpc"
# "-debug=validation"
];
}; };
users.users.bitcoind-mainnet.extraGroups = [ "tor" ]; users.users.bitcoind-mainnet.extraGroups = [ "tor" ];
systemd.services.bitcoind-mainnet.serviceConfig.RestartSec = "30s"; #< default is 0 systemd.services.bitcoind-mainnet = {
after = [ "tor.service" ];
requires = [ "tor.service" ];
serviceConfig.RestartSec = "30s"; #< default is 0
# hardening (systemd-analyze security bitcoind-mainnet)
serviceConfig.StateDirectory = "bitcoind-mainnet";
serviceConfig.LockPersonality = true;
serviceConfig.MemoryDenyWriteExecute = "true";
serviceConfig.NoNewPrivileges = "true";
serviceConfig.PrivateDevices = "true";
serviceConfig.PrivateMounts = true;
serviceConfig.PrivateTmp = "true";
serviceConfig.PrivateUsers = true;
serviceConfig.ProcSubset = "pid";
serviceConfig.ProtectControlGroups = true;
serviceConfig.ProtectHome = true;
serviceConfig.ProtectHostname = true;
serviceConfig.ProtectKernelLogs = true;
serviceConfig.ProtectKernelModules = true;
serviceConfig.ProtectKernelTunables = true;
serviceConfig.ProtectProc = "invisible";
serviceConfig.ProtectSystem = lib.mkForce "strict";
serviceConfig.RemoveIPC = true;
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
serviceConfig.RestrictNamespaces = true;
serviceConfig.RestrictSUIDSGID = true;
serviceConfig.SystemCallArchitectures = "native";
serviceConfig.SystemCallFilter = [ "@system-service" ];
};
sane.users.colin.fs.".bitcoin/bitcoin.conf" = sane-lib.fs.wantedSymlinkTo config.sops.secrets."bitcoin.conf".path;
sops.secrets."bitcoin.conf" = { sops.secrets."bitcoin.conf" = {
mode = "0600"; mode = "0600";
owner = "colin"; owner = "colin";
group = "users"; group = "users";
}; };
sane.programs.bitcoind.enableFor.user.colin = true; # for debugging/administration: `bitcoin-cli` sane.programs.bitcoin-cli.enableFor.user.colin = true; # for debugging/administration: `bitcoin-cli`
} }

View File

@@ -72,13 +72,11 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
{ {
sane.persist.sys.byStore.ext = [ sane.persist.sys.byStore.private = [
# clightning takes up only a few MB. but then several hundred MB of crash logs that i should probably GC.
{ user = "clightning"; group = "clightning"; mode = "0710"; path = "/var/lib/clightning"; method = "bind"; } { user = "clightning"; group = "clightning"; mode = "0710"; path = "/var/lib/clightning"; method = "bind"; }
]; ];
# `lightning-cli` finds its RPC file via `~/.lightning/bitcoin/lightning-rpc`, to message the daemon
sane.user.fs.".lightning".symlink.target = "/var/lib/clightning";
# see bitcoin.nix for how to generate this # see bitcoin.nix for how to generate this
services.bitcoind.mainnet.rpc.users.clightning.passwordHMAC = services.bitcoind.mainnet.rpc.users.clightning.passwordHMAC =
"befcb82d9821049164db5217beb85439$2c31ac7db3124612e43893ae13b9527dbe464ab2d992e814602e7cb07dc28985"; "befcb82d9821049164db5217beb85439$2c31ac7db3124612e43893ae13b9527dbe464ab2d992e814602e7cb07dc28985";
@@ -105,6 +103,7 @@
users.users.clightning.extraGroups = [ "tor" ]; users.users.clightning.extraGroups = [ "tor" ];
systemd.services.clightning.after = [ "tor.service" ]; systemd.services.clightning.after = [ "tor.service" ];
systemd.services.clightning.requires = [ "tor.service" ];
# lightning-config contains fields from here: # lightning-config contains fields from here:
# - <https://docs.corelightning.org/docs/configuration> # - <https://docs.corelightning.org/docs/configuration>
@@ -117,13 +116,15 @@
# - feature configs (i.e. experimental-xyz options) # - feature configs (i.e. experimental-xyz options)
sane.services.clightning.extraConfig = '' sane.services.clightning.extraConfig = ''
# log levels: "io", "debug", "info", "unusual", "broken" # log levels: "io", "debug", "info", "unusual", "broken"
log-level=info:lightningd log-level=info
# log-level=info:lightningd
# log-level=debug:lightningd # log-level=debug:lightningd
# log-level=debug
# peerswap: # peerswap:
# - config example: <https://github.com/fort-nix/nix-bitcoin/pull/462/files#diff-b357d832705b8ce8df1f41934d613f79adb77c4cd5cd9e9eb12a163fca3e16c6> # - config example: <https://github.com/fort-nix/nix-bitcoin/pull/462/files#diff-b357d832705b8ce8df1f41934d613f79adb77c4cd5cd9e9eb12a163fca3e16c6>
# XXX: peerswap crashes clightning on launch. stacktrace is useless. # XXX: peerswap crashes clightning on launch. stacktrace is useless.
# plugin=${pkgs.peerswap}/bin/peerswap # plugin={pkgs.peerswap}/bin/peerswap
# peerswap-db-path=/var/lib/clightning/peerswap/swaps # peerswap-db-path=/var/lib/clightning/peerswap/swaps
# peerswap-policy-path=... # peerswap-policy-path=...
''; '';
@@ -134,6 +135,5 @@
group = "clightning"; group = "clightning";
}; };
sane.programs.clightning.enableFor.user.colin = true; # for debugging/admin: `lightning-cli` sane.programs.lightning-cli.enableFor.user.colin = true; # for debugging/admin:
sane.programs.clightning.packageUnwrapped = config.sane.services.clightning.package;
} }

View File

@@ -1,4 +1,5 @@
{ ... }: { lib, ... }:
lib.mkIf false #< 2024/07/27: i don't use it, too much surface-area for me to run it pro-bono (`systemd-analyze security monero`)
{ {
services.i2p.enable = true; services.i2p.enable = true;
} }

View File

@@ -1,5 +1,6 @@
# as of 2023/11/26: complete downloaded blockchain should be 200GiB on disk, give or take. # as of 2023/11/26: complete downloaded blockchain should be 200GiB on disk, give or take.
{ ... }: { lib, ... }:
lib.mkIf false #< 2024/07/27: i don't use it, too much surface-area for me to run it pro-bono (`systemd-analyze security monero`)
{ {
sane.persist.sys.byStore.ext = [ sane.persist.sys.byStore.ext = [
# /var/lib/monero/lmdb is what consumes most of the space # /var/lib/monero/lmdb is what consumes most of the space

View File

@@ -1,9 +1,9 @@
# tor settings: <https://2019.www.torproject.org/docs/tor-manual.html.en> # tor settings: <https://2019.www.torproject.org/docs/tor-manual.html.en>
{ lib, ... }: { lib, ... }:
{ {
# tor hidden service hostnames aren't deterministic, so persist. sane.persist.sys.byStore.ephemeral = [
# might be able to get away with just persisting /var/lib/tor/onion, not sure. # N.B.: tor hidden service hostnames aren't deterministic, so if you need them
sane.persist.sys.byStore.plaintext = [ # to be preserved across reboots then persist /var/lib/tor/onion in "private" store.
{ user = "tor"; group = "tor"; mode = "0710"; path = "/var/lib/tor"; method = "bind"; } { user = "tor"; group = "tor"; mode = "0710"; path = "/var/lib/tor"; method = "bind"; }
]; ];

View File

@@ -7,10 +7,11 @@
./ejabberd.nix ./ejabberd.nix
./freshrss.nix ./freshrss.nix
./export ./export
./hickory-dns.nix
./gitea.nix ./gitea.nix
./goaccess.nix ./goaccess.nix
./ipfs.nix ./ipfs.nix
./jackett.nix ./jackett
./jellyfin.nix ./jellyfin.nix
./kiwix-serve.nix ./kiwix-serve.nix
./komga.nix ./komga.nix
@@ -20,13 +21,13 @@
./nginx.nix ./nginx.nix
./nixos-prebuild.nix ./nixos-prebuild.nix
./ntfy ./ntfy
./ollama.nix
./pict-rs.nix ./pict-rs.nix
./pleroma.nix ./pleroma.nix
./postgres.nix ./postgres.nix
./prosody ./prosody
./slskd.nix ./slskd.nix
./transmission ./transmission
./trust-dns.nix
./wikipedia.nix ./wikipedia.nix
]; ];
} }

View File

@@ -44,7 +44,7 @@ in
# everything configured below was fine: used ejabberd for several months. # everything configured below was fine: used ejabberd for several months.
lib.mkIf false lib.mkIf false
{ {
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.private = [
{ user = "ejabberd"; group = "ejabberd"; path = "/var/lib/ejabberd"; method = "bind"; } { user = "ejabberd"; group = "ejabberd"; path = "/var/lib/ejabberd"; method = "bind"; }
]; ];
sane.ports.ports = lib.mkMerge ([ sane.ports.ports = lib.mkMerge ([

View File

@@ -83,8 +83,8 @@
# sieve_plugins = sieve_imapsieve # sieve_plugins = sieve_imapsieve
# } # }
mail_debug = yes # mail_debug = yes
auth_debug = yes # auth_debug = yes
# verbose_ssl = yes # verbose_ssl = yes
''; '';

View File

@@ -1,4 +1,11 @@
# postfix config options: <https://www.postfix.org/postconf.5.html> # postfix config options: <https://www.postfix.org/postconf.5.html>
# config files:
# - /etc/postfix/main.cf
# - /etc/postfix/master.cf
#
# logs:
# - postfix logs directly to *syslog*,
# so check e.g. ~/.local/share/rsyslog
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
@@ -18,14 +25,14 @@ let
}; };
in in
{ {
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.private = [
# TODO: mode? could be more granular # TODO: mode? could be more granular
{ user = "opendkim"; group = "opendkim"; path = "/var/lib/opendkim"; method = "bind"; } { user = "opendkim"; group = "opendkim"; path = "/var/lib/opendkim"; method = "bind"; } #< TODO: migrate to secrets
{ user = "root"; group = "root"; path = "/var/lib/postfix"; method = "bind"; }
{ user = "root"; group = "root"; path = "/var/spool/mail"; method = "bind"; } { user = "root"; group = "root"; path = "/var/spool/mail"; method = "bind"; }
# *probably* don't need these dirs: # *probably* don't need these dirs:
# "/var/lib/dhparams" # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/dhparams.nix # "/var/lib/dhparams" # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/security/dhparams.nix
# "/var/lib/dovecot" # "/var/lib/dovecot"
# "/var/lib/postfix"
]; ];
# XXX(2023/10/20): opening these ports in the firewall has the OPPOSITE effect as intended. # XXX(2023/10/20): opening these ports in the firewall has the OPPOSITE effect as intended.
@@ -95,6 +102,7 @@ in
services.postfix.sslCert = "/var/lib/acme/mx.uninsane.org/fullchain.pem"; services.postfix.sslCert = "/var/lib/acme/mx.uninsane.org/fullchain.pem";
services.postfix.sslKey = "/var/lib/acme/mx.uninsane.org/key.pem"; services.postfix.sslKey = "/var/lib/acme/mx.uninsane.org/key.pem";
# see: `man 5 virtual`
services.postfix.virtual = '' services.postfix.virtual = ''
notify.matrix@uninsane.org matrix-synapse notify.matrix@uninsane.org matrix-synapse
@uninsane.org colin @uninsane.org colin
@@ -135,6 +143,20 @@ in
# smtpd_sender_restrictions = reject_unknown_sender_domain # smtpd_sender_restrictions = reject_unknown_sender_domain
}; };
# debugging options:
# services.postfix.masterConfig = {
# "proxymap".args = [ "-v" ];
# "proxywrite".args = [ "-v" ];
# "relay".args = [ "-v" ];
# "smtp".args = [ "-v" ];
# "smtp_inet".args = [ "-v" ];
# "submission".args = [ "-v" ];
# "submissions".args = [ "-v" ];
# "submissions".chroot = false;
# "submissions".private = false;
# "submissions".privileged = true;
# };
services.postfix.enableSubmission = true; services.postfix.enableSubmission = true;
services.postfix.submissionOptions = submissionOptions; services.postfix.submissionOptions = submissionOptions;
services.postfix.enableSubmissions = true; services.postfix.enableSubmissions = true;
@@ -142,6 +164,10 @@ in
systemd.services.postfix.after = [ "wireguard-wg-ovpns.service" ]; systemd.services.postfix.after = [ "wireguard-wg-ovpns.service" ];
systemd.services.postfix.partOf = [ "wireguard-wg-ovpns.service" ]; systemd.services.postfix.partOf = [ "wireguard-wg-ovpns.service" ];
systemd.services.postfix.unitConfig.RequiresMountsFor = [
"/var/spool/mail" # spooky errors when postfix is run w/o this: `warning: connect #1 to subsystem private/proxymap: Connection refused`
"/var/lib/opendkim"
];
systemd.services.postfix.serviceConfig = { systemd.services.postfix.serviceConfig = {
# run this behind the OVPN static VPN # run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns"; NetworkNamespacePath = "/run/netns/ovpns";
@@ -175,23 +201,30 @@ in
#### OUTGOING MESSAGE REWRITING: #### OUTGOING MESSAGE REWRITING:
services.postfix.enableHeaderChecks = true; # - `man 5 header_checks`
services.postfix.headerChecks = [ # - <https://www.postfix.org/header_checks.5.html>
# intercept gitea registration confirmations and manually screen them # - populates `/var/lib/postfix/conf/header_checks`
{ # XXX(2024-08-06): registration gating via email matches is AWFUL:
# headerChecks are somehow ignorant of alias rules: have to redirect to a real user # 1. bypassed if the service offers localization.
action = "REDIRECT colin@uninsane.org"; # 2. if i try to forward the registration request, it may match the filter again and get sent back to my inbox.
pattern = "/^Subject: Please activate your account/"; # 3. header checks are possibly under-used in the ecosystem, and may break postfix config.
} # services.postfix.enableHeaderChecks = true;
# intercept Matrix registration confirmations # services.postfix.headerChecks = [
{ # # intercept gitea registration confirmations and manually screen them
action = "REDIRECT colin@uninsane.org";
pattern = "/^Subject:.*Validate your email/";
}
# XXX postfix only supports performing ONE action per header.
# { # {
# action = "REPLACE Subject: git application: Please activate your account"; # # headerChecks are somehow ignorant of alias rules: have to redirect to a real user
# pattern = "/^Subject:.*activate your account/"; # action = "REDIRECT colin@uninsane.org";
# pattern = "/^Subject: Please activate your account/";
# } # }
]; # # intercept Matrix registration confirmations
# {
# action = "REDIRECT colin@uninsane.org";
# pattern = "/^Subject:.*Validate your email/";
# }
# # XXX postfix only supports performing ONE action per header.
# # {
# # action = "REPLACE Subject: git application: Please activate your account";
# # pattern = "/^Subject:.*activate your account/";
# # }
# ];
} }

View File

@@ -12,10 +12,6 @@
device = "/var/media"; device = "/var/media";
options = [ "rbind" ]; options = [ "rbind" ];
}; };
fileSystems."/var/export/pub" = {
device = "/var/www/sites/uninsane.org/share";
options = [ "rbind" ];
};
# fileSystems."/var/export/playground" = { # fileSystems."/var/export/playground" = {
# device = config.fileSystems."/mnt/persist/ext".device; # device = config.fileSystems."/mnt/persist/ext".device;
# fsType = "btrfs"; # fsType = "btrfs";
@@ -55,4 +51,11 @@
- be a friendly troll - be a friendly troll
''; '';
}; };
sane.fs."/var/export/.public_for_test/test" = {
wantedBy = [ "nfs.service" "sftpgo.service" ];
file.text = ''
automated tests read this file to probe connectivity
'';
};
} }

View File

@@ -80,12 +80,6 @@ in
port = 21; port = 21;
debug = true; debug = true;
} }
{
# binding this means any LAN client can connect (also WAN traffic forwarded from the gateway)
address = "10.78.79.51";
port = 21;
debug = true;
}
{ {
# binding this means any wireguard client can connect # binding this means any wireguard client can connect
address = "10.0.10.5"; address = "10.0.10.5";
@@ -93,6 +87,12 @@ in
debug = true; debug = true;
tls_mode = 2; # 2 = "implicit FTPS": client negotiates TLS before any FTP command. tls_mode = 2; # 2 = "implicit FTPS": client negotiates TLS before any FTP command.
} }
{
# binding this means any LAN client can connect (also WAN traffic forwarded from the gateway)
address = "10.78.79.51";
port = 21;
debug = true;
}
{ {
# binding this means any LAN client can connect (also WAN traffic forwarded from the gateway) # binding this means any LAN client can connect (also WAN traffic forwarded from the gateway)
address = "10.78.79.51"; address = "10.78.79.51";
@@ -107,6 +107,13 @@ in
debug = true; debug = true;
tls_mode = 2; # 2 = "implicit FTPS": client negotiates TLS before any FTP command. tls_mode = 2; # 2 = "implicit FTPS": client negotiates TLS before any FTP command.
} }
{
# binding this means any LAN client can connect via `ftp.uninsane.org` (TLS only)
address = config.sane.netns.doof.netnsPubIpv4;
port = 990;
debug = true;
tls_mode = 2; # 2 = "implicit FTPS": client negotiates TLS before any FTP command.
}
]; ];
# active mode is susceptible to "bounce attacks", without much benefit over passive mode # active mode is susceptible to "bounce attacks", without much benefit over passive mode

View File

@@ -129,14 +129,14 @@ def getAuthResponse(ip: str, username: str, password: str) -> dict:
return mkAuthOk(username, permissions = { return mkAuthOk(username, permissions = {
"/": PERM_RW, "/": PERM_RW,
"/playground": PERM_RW, "/playground": PERM_RW,
"/pub": PERM_RO, "/.public_for_test": PERM_RO,
}) })
if isWireguard(ip): if isWireguard(ip):
# allow any user from wireguard # allow any user from wireguard
return mkAuthOk(username, permissions = { return mkAuthOk(username, permissions = {
"/": PERM_RW, "/": PERM_RW,
"/playground": PERM_RW, "/playground": PERM_RW,
"/pub": PERM_RO, "/.public_for_test": PERM_RO,
}) })
if isLan(ip): if isLan(ip):
if username == "anonymous": if username == "anonymous":
@@ -144,7 +144,7 @@ def getAuthResponse(ip: str, username: str, password: str) -> dict:
return mkAuthOk("anonymous", permissions = { return mkAuthOk("anonymous", permissions = {
"/": PERM_RO, "/": PERM_RO,
"/playground": PERM_RW, "/playground": PERM_RW,
"/pub": PERM_RO, "/.public_for_test": PERM_RO,
}) })
if username == "anonymous": if username == "anonymous":
# anonymous users from the www can have even more limited access. # anonymous users from the www can have even more limited access.
@@ -154,7 +154,7 @@ def getAuthResponse(ip: str, username: str, password: str) -> dict:
"/": PERM_LIST, #< REQUIRED, even for lftp to list a subdir "/": PERM_LIST, #< REQUIRED, even for lftp to list a subdir
"/media": PERM_DENY, "/media": PERM_DENY,
"/playground": PERM_DENY, "/playground": PERM_DENY,
"/pub": PERM_RO, "/.public_for_test": PERM_RO,
# "/README.md": PERM_RO, #< does not work # "/README.md": PERM_RO, #< does not work
}) })

View File

@@ -1,11 +1,14 @@
# config options: <https://docs.gitea.io/en-us/administration/config-cheat-sheet/> # config options: <https://docs.gitea.io/en-us/administration/config-cheat-sheet/>
# TODO: service shouldn't run as `git` user, but as `gitea`
{ config, pkgs, lib, ... }: { config, pkgs, lib, ... }:
{ {
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.private = [
# TODO: mode? could be more granular { user = "git"; group = "gitea"; mode = "0750"; path = "/var/lib/gitea"; method = "bind"; }
{ user = "git"; group = "gitea"; path = "/var/lib/gitea"; method = "bind"; }
]; ];
sane.programs.gitea.enableFor.user.colin = true; # for admin, and monitoring
services.gitea.enable = true; services.gitea.enable = true;
services.gitea.user = "git"; # default is 'gitea' services.gitea.user = "git"; # default is 'gitea'
services.gitea.database.type = "postgres"; services.gitea.database.type = "postgres";
@@ -41,14 +44,21 @@
# timeout for email approval. 5760 = 4 days. 10080 = 7 days # timeout for email approval. 5760 = 4 days. 10080 = 7 days
ACTIVE_CODE_LIVE_MINUTES = 10080; ACTIVE_CODE_LIVE_MINUTES = 10080;
# REGISTER_EMAIL_CONFIRM = false; # REGISTER_EMAIL_CONFIRM = false;
# REGISTER_MANUAL_CONFIRM = true; # REGISTER_EMAIL_CONFIRM = true; #< override REGISTER_MANUAL_CONFIRM
REGISTER_EMAIL_CONFIRM = true; REGISTER_MANUAL_CONFIRM = true;
# not sure what this notifies *on*... # not sure what this notifies *on*...
ENABLE_NOTIFY_MAIL = true; ENABLE_NOTIFY_MAIL = true;
# defaults to image-based captcha. # defaults to image-based captcha.
# also supports recaptcha (with custom URLs) or hCaptcha. # also supports recaptcha (with custom URLs) or hCaptcha.
ENABLE_CAPTCHA = true; ENABLE_CAPTCHA = true;
NOREPLY_ADDRESS = "noreply.anonymous.git@uninsane.org"; NOREPLY_ADDRESS = "noreply.anonymous.git@uninsane.org";
EMAIL_DOMAIN_BLOCKLIST = lib.concatStringsSep ", " [
"*.claychoen.top"
"*.gemmasmith.co.uk"
"*.jenniferlawrence.uk"
"*.sarahconnor.co.uk"
"*.marymarshall.co.uk"
];
}; };
session = { session = {
COOKIE_SECURE = true; COOKIE_SECURE = true;
@@ -109,6 +119,10 @@
locations."/" = { locations."/" = {
proxyPass = "http://127.0.0.1:3000"; proxyPass = "http://127.0.0.1:3000";
}; };
# fuck you @anthropic
locations."= /robots.txt".extraConfig = ''
return 200 "User-agent: *\nDisallow: /\n";
'';
# gitea serves all `raw` files as content-type: plain, but i'd like to serve them as their actual content type. # gitea serves all `raw` files as content-type: plain, but i'd like to serve them as their actual content type.
# or at least, enough to make specific pages viewable (serving unoriginal content as arbitrary content type is dangerous). # or at least, enough to make specific pages viewable (serving unoriginal content as arbitrary content type is dangerous).
locations."~ ^/colin/phone-case-cq/raw/.*.html" = { locations."~ ^/colin/phone-case-cq/raw/.*.html" = {

View File

@@ -48,16 +48,14 @@ in
# so, org. can specify ns2/ns3 as being to the VPN, with no mention of ns1. we provide ns1 here. # so, org. can specify ns2/ns3 as being to the VPN, with no mention of ns1. we provide ns1 here.
A."ns1" = "%ANATIVE%"; A."ns1" = "%ANATIVE%";
A."ns2" = "%ADOOF%"; A."ns2" = "%ADOOF%";
A."ns3" = "%AOVPNS%";
A."ovpns" = "%AOVPNS%"; A."ovpns" = "%AOVPNS%";
NS."@" = [ NS."@" = [
"ns1.uninsane.org." "ns1.uninsane.org."
"ns2.uninsane.org." "ns2.uninsane.org."
"ns3.uninsane.org."
]; ];
}; };
services.trust-dns.settings.zones = [ "uninsane.org" ]; services.hickory-dns.settings.zones = [ "uninsane.org" ];
networking.nat.enable = true; #< TODO: try removing this? networking.nat.enable = true; #< TODO: try removing this?
@@ -85,8 +83,8 @@ in
# }; # };
sane.services.trust-dns.enable = true; sane.services.hickory-dns.enable = true;
sane.services.trust-dns.instances = let sane.services.hickory-dns.instances = let
mkSubstitutions = flavor: { mkSubstitutions = flavor: {
"%ADOOF%" = config.sane.netns.doof.netnsPubIpv4; "%ADOOF%" = config.sane.netns.doof.netnsPubIpv4;
"%ANATIVE%" = nativeAddrs."servo.${flavor}"; "%ANATIVE%" = nativeAddrs."servo.${flavor}";
@@ -100,7 +98,9 @@ in
substitutions = mkSubstitutions "doof"; substitutions = mkSubstitutions "doof";
listenAddrsIpv4 = [ listenAddrsIpv4 = [
config.sane.netns.doof.hostVethIpv4 config.sane.netns.doof.hostVethIpv4
config.sane.netns.ovpns.hostVethIpv4 config.sane.netns.doof.netnsPubIpv4
nativeAddrs."servo.lan"
# config.sane.netns.ovpns.hostVethIpv4
]; ];
}; };
hn = { hn = {
@@ -128,11 +128,11 @@ in
# ]; # ];
# }; # };
}; };
lan = { # lan = {
substitutions = mkSubstitutions "lan"; # substitutions = mkSubstitutions "lan";
listenAddrsIpv4 = [ nativeAddrs."servo.lan" ]; # listenAddrsIpv4 = [ nativeAddrs."servo.lan" ];
# port = 1053; # # port = 1053;
}; # };
# wan = { # wan = {
# substitutions = mkSubstitutions "wan"; # substitutions = mkSubstitutions "wan";
# listenAddrsIpv4 = [ # listenAddrsIpv4 = [
@@ -141,10 +141,5 @@ in
# }; # };
}; };
sane.services.dyn-dns.restartOnChange = [ sane.services.dyn-dns.restartOnChange = lib.map (c: "${c.service}.service") (builtins.attrValues config.sane.services.hickory-dns.instances);
"trust-dns-doof.service"
"trust-dns-hn.service"
"trust-dns-lan.service"
# "trust-dns-wan.service"
];
} }

View File

@@ -10,7 +10,7 @@
lib.mkIf false # i don't actively use ipfs anymore lib.mkIf false # i don't actively use ipfs anymore
{ {
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.private = [
# TODO: mode? could be more granular # TODO: mode? could be more granular
{ user = "261"; group = "261"; path = "/var/lib/ipfs"; method = "bind"; } { user = "261"; group = "261"; path = "/var/lib/ipfs"; method = "bind"; }
]; ];

View File

@@ -1,34 +0,0 @@
{ config, lib, pkgs, ... }:
{
sane.persist.sys.byStore.plaintext = [
# TODO: mode? we only need this to save Indexer creds ==> migrate to config?
{ user = "root"; group = "root"; path = "/var/lib/jackett"; method = "bind"; }
];
services.jackett.enable = true;
systemd.services.jackett.after = [ "wireguard-wg-ovpns.service" ];
systemd.services.jackett.partOf = [ "wireguard-wg-ovpns.service" ];
systemd.services.jackett.serviceConfig = {
# run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns";
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect ${config.sane.netns.ovpns.netnsPubIpv4}" ]; # abort if public IP is not as expected
# 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://${config.sane.netns.ovpns.netnsVethIpv4}:9117";
recommendedProxySettings = true;
};
};
sane.dns.zones."uninsane.org".inet.CNAME."jackett" = "native";
}

View File

@@ -0,0 +1,68 @@
{ config, lib, pkgs, ... }:
let
cfg = config.services.jackett;
in
{
sane.persist.sys.byStore.private = [
# TODO: mode? we only need this to save Indexer creds ==> migrate to config?
{ user = "jackett"; group = "jackett"; path = "/var/lib/jackett"; method = "bind"; }
];
services.jackett.enable = true;
systemd.services.jackett.after = [ "wireguard-wg-ovpns.service" ];
systemd.services.jackett.partOf = [ "wireguard-wg-ovpns.service" ];
systemd.services.jackett = {
# run this behind the OVPN static VPN
serviceConfig.NetworkNamespacePath = "/run/netns/ovpns";
serviceConfig.ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect ${config.sane.netns.ovpns.netnsPubIpv4}" ]; # abort if public IP is not as expected
# patch in `--ListenPublic` so that it's reachable from the netns veth.
# this also makes it reachable from the VPN pub address. oh well.
serviceConfig.ExecStart = lib.mkForce "${cfg.package}/bin/Jackett --ListenPublic --NoUpdates --DataFolder '${cfg.dataDir}'";
serviceConfig.RestartSec = "30s";
# hardening (systemd-analyze security jackett)
# TODO: upstream into nixpkgs
serviceConfig.StateDirectory = "jackett";
serviceConfig.LockPersonality = true;
serviceConfig.NoNewPrivileges = true;
# serviceConfig.MemoryDenyWriteExecute = true; #< Failed to create CoreCLR, HRESULT: 0x80004005
serviceConfig.PrivateDevices = true;
serviceConfig.PrivateMounts = true;
serviceConfig.PrivateTmp = true;
serviceConfig.PrivateUsers = true;
serviceConfig.ProcSubset = "pid";
serviceConfig.ProtectClock = true;
serviceConfig.ProtectControlGroups = true;
serviceConfig.ProtectHome = true;
serviceConfig.ProtectHostname = true;
serviceConfig.ProtectKernelLogs = true;
serviceConfig.ProtectKernelModules = true;
serviceConfig.ProtectKernelTunables = true;
serviceConfig.ProtectProc = "invisible";
serviceConfig.ProtectSystem = "strict";
serviceConfig.RemoveIPC = true;
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
serviceConfig.RestrictNamespaces = true;
serviceConfig.RestrictSUIDSGID = true;
serviceConfig.SystemCallArchitectures = "native";
serviceConfig.SystemCallFilter = [ "@system-service" "~@privileged" ];
};
# jackett torrent search
services.nginx.virtualHosts."jackett.uninsane.org" = {
forceSSL = true;
enableACME = true;
# inherit kTLS;
locations."/" = {
proxyPass = "http://${config.sane.netns.ovpns.netnsVethIpv4}:9117";
recommendedProxySettings = true;
};
locations."= /robots.txt".extraConfig = ''
return 200 "User-agent: *\nDisallow: /\n";
'';
};
sane.dns.zones."uninsane.org".inet.CNAME."jackett" = "native";
}

View File

@@ -21,6 +21,9 @@
enableACME = true; enableACME = true;
# inherit kTLS; # inherit kTLS;
locations."/".proxyPass = "http://127.0.0.1:8013"; locations."/".proxyPass = "http://127.0.0.1:8013";
locations."= /robots.txt".extraConfig = ''
return 200 "User-agent: *\nDisallow: /\n";
'';
}; };
sane.dns.zones."uninsane.org".inet.CNAME."w" = "native"; sane.dns.zones."uninsane.org".inet.CNAME."w" = "native";

View File

@@ -17,6 +17,9 @@ in
locations."/" = { locations."/" = {
proxyPass = "http://127.0.0.1:${builtins.toString port}"; proxyPass = "http://127.0.0.1:${builtins.toString port}";
}; };
locations."= /robots.txt".extraConfig = ''
return 200 "User-agent: *\nDisallow: /\n";
'';
}; };
sane.dns.zones."uninsane.org".inet.CNAME."komga" = "native"; sane.dns.zones."uninsane.org".inet.CNAME."komga" = "native";
} }

View File

@@ -38,15 +38,10 @@ in {
nginx.enable = true; nginx.enable = true;
}; };
systemd.services.lemmy.serviceConfig = {
# fix to use a normal user so we can configure perms correctly
DynamicUser = mkForce false;
User = "lemmy";
Group = "lemmy";
};
systemd.services.lemmy.environment = { systemd.services.lemmy.environment = {
RUST_BACKTRACE = "full"; RUST_BACKTRACE = "full";
RUST_LOG = "warn"; RUST_LOG = "error";
# RUST_LOG = "warn";
# RUST_LOG = "debug"; # RUST_LOG = "debug";
# RUST_LOG = "trace"; # RUST_LOG = "trace";
# upstream defaults LEMMY_DATABASE_URL = "postgres:///lemmy?host=/run/postgresql"; # upstream defaults LEMMY_DATABASE_URL = "postgres:///lemmy?host=/run/postgresql";
@@ -73,6 +68,73 @@ in {
sane.dns.zones."uninsane.org".inet.CNAME."lemmy" = "native"; sane.dns.zones."uninsane.org".inet.CNAME."lemmy" = "native";
systemd.services.lemmy = {
# fix to use a normal user so we can configure perms correctly
# XXX(2024-07-28): this hasn't been rigorously tested:
# possible that i've set something too strict and won't notice right away
serviceConfig.DynamicUser = mkForce false;
serviceConfig.User = "lemmy";
serviceConfig.Group = "lemmy";
# hardening (systemd-analyze security lemmy)
# a handful of these are specified in upstream nixpkgs, but mostly not
serviceConfig.LockPersonality = true;
serviceConfig.NoNewPrivileges = true;
serviceConfig.MemoryDenyWriteExecute = true;
serviceConfig.PrivateDevices = true;
serviceConfig.PrivateMounts = true;
serviceConfig.PrivateTmp = true;
serviceConfig.PrivateUsers = true;
serviceConfig.ProcSubset = "pid";
serviceConfig.ProtectClock = true;
serviceConfig.ProtectControlGroups = true;
serviceConfig.ProtectHome = true;
serviceConfig.ProtectHostname = true;
serviceConfig.ProtectKernelLogs = true;
serviceConfig.ProtectKernelModules = true;
serviceConfig.ProtectKernelTunables = true;
serviceConfig.ProtectProc = "invisible";
serviceConfig.ProtectSystem = "strict";
serviceConfig.RemoveIPC = true;
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
serviceConfig.RestrictNamespaces = true;
serviceConfig.RestrictSUIDSGID = true;
serviceConfig.SystemCallArchitectures = "native";
serviceConfig.SystemCallFilter = [ "@system-service" ];
};
systemd.services.lemmy-ui = {
# hardening (systemd-analyze security lemmy-ui)
# TODO: upstream into nixpkgs
serviceConfig.LockPersonality = true;
serviceConfig.NoNewPrivileges = true;
# serviceConfig.MemoryDenyWriteExecute = true; #< it uses v8, JIT
serviceConfig.PrivateDevices = true;
serviceConfig.PrivateMounts = true;
serviceConfig.PrivateTmp = true;
serviceConfig.PrivateUsers = true;
serviceConfig.ProcSubset = "pid";
serviceConfig.ProtectClock = true;
serviceConfig.ProtectControlGroups = true;
serviceConfig.ProtectHome = true;
serviceConfig.ProtectHostname = true;
serviceConfig.ProtectKernelLogs = true;
serviceConfig.ProtectKernelModules = true;
serviceConfig.ProtectKernelTunables = true;
serviceConfig.ProtectProc = "invisible";
serviceConfig.ProtectSystem = "strict";
serviceConfig.RemoveIPC = true;
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
serviceConfig.RestrictNamespaces = true;
serviceConfig.RestrictSUIDSGID = true;
serviceConfig.SystemCallArchitectures = "native";
serviceConfig.SystemCallFilter = [ "@system-service" "@pkey" "@sandbox" ];
};
#v DO NOT REMOVE: defaults to 0.3, instead of latest, so always need to explicitly set this. #v DO NOT REMOVE: defaults to 0.3, instead of latest, so always need to explicitly set this.
services.pict-rs.package = pict-rs; services.pict-rs.package = pict-rs;
@@ -82,10 +144,38 @@ in {
# - via CLI flags (overrides everything above) # - via CLI flags (overrides everything above)
# some of the CLI flags have defaults, making it the only actual way to configure certain things even when docs claim otherwise. # some of the CLI flags have defaults, making it the only actual way to configure certain things even when docs claim otherwise.
# CLI args: <https://git.asonix.dog/asonix/pict-rs#user-content-running> # CLI args: <https://git.asonix.dog/asonix/pict-rs#user-content-running>
systemd.services.pict-rs.serviceConfig.ExecStart = lib.mkForce (lib.concatStringsSep " " [ systemd.services.pict-rs = {
serviceConfig.ExecStart = lib.mkForce (lib.concatStringsSep " " [
"${lib.getBin pict-rs}/bin/pict-rs run" "${lib.getBin pict-rs}/bin/pict-rs run"
"--media-video-max-frame-count" (builtins.toString (30*60*60)) "--media-video-max-frame-count" (builtins.toString (30*60*60))
"--media-process-timeout 120" "--media-process-timeout 120"
"--media-video-allow-audio" # allow audio "--media-video-allow-audio" # allow audio
]); ]);
# hardening (systemd-analyze security pict-rs)
# TODO: upstream into nixpkgs
serviceConfig.LockPersonality = true;
serviceConfig.NoNewPrivileges = true;
serviceConfig.MemoryDenyWriteExecute = true;
serviceConfig.PrivateDevices = true;
serviceConfig.PrivateMounts = true;
serviceConfig.PrivateTmp = true;
serviceConfig.PrivateUsers = true;
serviceConfig.ProcSubset = "pid";
serviceConfig.ProtectClock = true;
serviceConfig.ProtectControlGroups = true;
serviceConfig.ProtectHome = true;
serviceConfig.ProtectHostname = true;
serviceConfig.ProtectKernelLogs = true;
serviceConfig.ProtectKernelModules = true;
serviceConfig.ProtectKernelTunables = true;
serviceConfig.ProtectProc = "invisible";
serviceConfig.ProtectSystem = "strict";
serviceConfig.RemoveIPC = true;
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
serviceConfig.RestrictNamespaces = true;
serviceConfig.RestrictSUIDSGID = true;
serviceConfig.SystemCallArchitectures = "native";
serviceConfig.SystemCallFilter = [ "@system-service" ];
};
} }

View File

@@ -20,17 +20,17 @@
./signal.nix ./signal.nix
]; ];
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.private = [
{ user = "matrix-synapse"; group = "matrix-synapse"; path = "/var/lib/matrix-synapse"; method = "bind"; } { user = "matrix-synapse"; group = "matrix-synapse"; path = "/var/lib/matrix-synapse"; method = "bind"; }
]; ];
services.matrix-synapse.enable = true; services.matrix-synapse.enable = true;
services.matrix-synapse.log.root.level = "WARNING"; # accepts "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL" (?) services.matrix-synapse.log.root.level = "ERROR"; # accepts "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL" (?)
services.matrix-synapse.settings = { services.matrix-synapse.settings = {
server_name = "uninsane.org"; server_name = "uninsane.org";
# services.matrix-synapse.enable_registration_captcha = true; # services.matrix-synapse.enable_registration_captcha = true;
# services.matrix-synapse.enable_registration_without_verification = true; # services.matrix-synapse.enable_registration_without_verification = true;
enable_registration = true; # enable_registration = true;
# services.matrix-synapse.registration_shared_secret = "<shared key goes here>"; # services.matrix-synapse.registration_shared_secret = "<shared key goes here>";
# default for listeners is port = 8448, tls = true, x_forwarded = false. # default for listeners is port = 8448, tls = true, x_forwarded = false.

View File

@@ -5,7 +5,7 @@
# - recommended to use mautrix-discord: <https://github.com/NixOS/nixpkgs/pull/200462> # - recommended to use mautrix-discord: <https://github.com/NixOS/nixpkgs/pull/200462>
lib.mkIf false lib.mkIf false
{ {
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.private = [
{ user = "matrix-synapse"; group = "matrix-synapse"; path = "/var/lib/mx-puppet-discord"; method = "bind"; } { user = "matrix-synapse"; group = "matrix-synapse"; path = "/var/lib/mx-puppet-discord"; method = "bind"; }
]; ];

View File

@@ -99,7 +99,7 @@ in
}) })
]; ];
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.private = [
# TODO: mode? # TODO: mode?
{ user = "matrix-appservice-irc"; group = "matrix-appservice-irc"; path = "/var/lib/matrix-appservice-irc"; method = "bind"; } { user = "matrix-appservice-irc"; group = "matrix-appservice-irc"; path = "/var/lib/matrix-appservice-irc"; method = "bind"; }
]; ];

View File

@@ -4,7 +4,7 @@
lib.mkIf false # disabled 2024/01/11: i don't use it, and pkgs.mautrix-signal had some API changes lib.mkIf false # disabled 2024/01/11: i don't use it, and pkgs.mautrix-signal had some API changes
{ {
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.private = [
{ user = "mautrix-signal"; group = "mautrix-signal"; path = "/var/lib/mautrix-signal"; method = "bind"; } { user = "mautrix-signal"; group = "mautrix-signal"; path = "/var/lib/mautrix-signal"; method = "bind"; }
{ user = "signald"; group = "signald"; path = "/var/lib/signald"; method = "bind"; } { user = "signald"; group = "signald"; path = "/var/lib/signald"; method = "bind"; }
]; ];

View File

@@ -29,6 +29,12 @@ in
}; };
services.nginx.enable = true; services.nginx.enable = true;
# nginxStable is one release behind nginxMainline.
# nginx itself recommends running mainline; nixos defaults to stable.
# services.nginx.package = pkgs.nginxMainline;
# XXX(2024-07-31): nixos defaults to zlib-ng -- supposedly more performant, but spams log with
# "gzip filter failed to use preallocated memory: ..."
services.nginx.package = pkgs.nginxMainline.override { zlib = pkgs.zlib; };
services.nginx.appendConfig = '' services.nginx.appendConfig = ''
# use 1 process per core. # use 1 process per core.
# may want to increase worker_connections too, but `ulimit -n` must be increased first. # may want to increase worker_connections too, but `ulimit -n` must be increased first.
@@ -44,8 +50,10 @@ in
log_format vcombined '$host:$server_port $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referrer" "$http_user_agent"'; log_format vcombined '$host:$server_port $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referrer" "$http_user_agent"';
access_log /var/log/nginx/private.log vcombined; access_log /var/log/nginx/private.log vcombined;
''; '';
# sets gzip_comp_level = 5 # enables gzip and sets gzip_comp_level = 5
services.nginx.recommendedGzipSettings = true; services.nginx.recommendedGzipSettings = true;
# enables zstd and sets zstd_comp_level = 9
services.nginx.recommendedZstdSettings = true;
# enables OCSP stapling (so clients don't need contact the OCSP server -- i do instead) # enables OCSP stapling (so clients don't need contact the OCSP server -- i do instead)
# - doesn't seem to, actually: <https://www.ssllabs.com/ssltest/analyze.html?d=uninsane.org> # - doesn't seem to, actually: <https://www.ssllabs.com/ssltest/analyze.html?d=uninsane.org>
# caches TLS sessions for 10m # caches TLS sessions for 10m
@@ -99,6 +107,16 @@ in
disable_symlinks on; disable_symlinks on;
''; '';
}; };
locations."/share/Ubunchu/" = {
alias = "/var/media/Books/Visual/HiroshiSeo/Ubunchu/";
extraConfig = ''
# autoindex => render directory listings
autoindex on;
# don't follow any symlinks when serving files
# otherwise it allows a directory escape
disable_symlinks on;
'';
};
# allow matrix users to discover that @user:uninsane.org is reachable via matrix.uninsane.org # allow matrix users to discover that @user:uninsane.org is reachable via matrix.uninsane.org
locations."= /.well-known/matrix/server".extraConfig = locations."= /.well-known/matrix/server".extraConfig =
@@ -180,8 +198,15 @@ in
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.plaintext = [
{ user = "acme"; group = "acme"; path = "/var/lib/acme"; method = "bind"; } { user = "acme"; group = "acme"; path = "/var/lib/acme"; method = "bind"; }
];
sane.persist.sys.byStore.private = [
{ user = "colin"; group = "users"; path = "/var/www/sites"; method = "bind"; } { user = "colin"; group = "users"; path = "/var/www/sites"; method = "bind"; }
]; ];
sane.persist.sys.byStore.ephemeral = [
# logs *could* be persisted to private storage, but then there's the issue of
# "what if servo boots, isn't unlocked, and the whole / tmpfs is consumed by logs"
{ user = "nginx"; group = "nginx"; path = "/var/log/nginx"; method = "bind"; }
];
# let's encrypt default chain looks like: # let's encrypt default chain looks like:
# - End-entity certificate ← R3 ← ISRG Root X1 ← DST Root CA X3 # - End-entity certificate ← R3 ← ISRG Root X1 ← DST Root CA X3

View File

@@ -30,7 +30,7 @@ let
altPort = 2587; altPort = 2587;
in in
{ {
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.private = [
# not 100% necessary to persist this, but ntfy does keep a 12hr (by default) cache # not 100% necessary to persist this, but ntfy does keep a 12hr (by default) cache
# for pushing notifications to users who become offline. # for pushing notifications to users who become offline.
# ACLs also live here. # ACLs also live here.
@@ -46,7 +46,7 @@ in
# defaults to 45s. # defaults to 45s.
# note that the client may still do its own TCP-level keepalives, typically every 30s # note that the client may still do its own TCP-level keepalives, typically every 30s
keepalive-interval = "15m"; keepalive-interval = "15m";
log-level = "trace"; # trace, debug, info (default), warn, error log-level = "info"; # trace, debug, info (default), warn, error
auth-default-access = "deny-all"; auth-default-access = "deny-all";
}; };
systemd.services.ntfy-sh.serviceConfig.DynamicUser = lib.mkForce false; systemd.services.ntfy-sh.serviceConfig.DynamicUser = lib.mkForce false;

View File

@@ -0,0 +1,23 @@
# ollama: <https://github.com/ollama/ollama>
# use: `ollama run llama3.1`
# or: `ollama run llama3.1:70b`
# or use a remote session: <https://github.com/ggozad/oterm>
{ lib, ... }:
lib.mkIf false #< WIP
{
sane.persist.sys.byStore.plaintext = [
{ user = "ollama"; group = "ollama"; path = "/var/lib/ollama"; method = "bind"; }
];
services.ollama.enable = true;
services.ollama.user = "ollama";
services.ollama.group = "ollama";
users.groups.ollama = {};
users.users.ollama = {
group = "ollama";
isSystemUser = true;
};
systemd.services.ollama.serviceConfig.DynamicUser = lib.mkForce false;
}

View File

@@ -7,14 +7,15 @@
# to run it in a oci-container: <https://github.com/barrucadu/nixfiles/blob/master/services/pleroma.nix> # to run it in a oci-container: <https://github.com/barrucadu/nixfiles/blob/master/services/pleroma.nix>
# #
# admin frontend: <https://fed.uninsane.org/pleroma/admin> # admin frontend: <https://fed.uninsane.org/pleroma/admin>
{ config, pkgs, ... }: { config, lib, pkgs, ... }:
let let
logLevel = "warn"; logLevel = "warn";
# logLevel = "debug"; # logLevel = "debug";
in in
{ {
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.private = [
# contains media i've uploaded to the server
{ user = "pleroma"; group = "pleroma"; path = "/var/lib/pleroma"; method = "bind"; } { user = "pleroma"; group = "pleroma"; path = "/var/lib/pleroma"; method = "bind"; }
]; ];
services.pleroma.enable = true; services.pleroma.enable = true;
@@ -135,25 +136,52 @@ in
# something inside pleroma invokes `sh` w/o specifying it by path, so this is needed to allow pleroma to start # something inside pleroma invokes `sh` w/o specifying it by path, so this is needed to allow pleroma to start
pkgs.bash pkgs.bash
# used by Pleroma to strip geo tags from uploads # used by Pleroma to strip geo tags from uploads
pkgs.exiftool config.sane.programs.exiftool.package
# i saw some errors when pleroma was shutting down about it not being able to find `awk`. probably not critical # i saw some errors when pleroma was shutting down about it not being able to find `awk`. probably not critical
pkgs.gawk config.sane.programs.gawk.package
# needed for email operations like password reset # needed for email operations like password reset
pkgs.postfix pkgs.postfix
]; ];
systemd.services.pleroma.serviceConfig = { systemd.services.pleroma = {
# postgres can be slow to service early requests, preventing pleroma from starting on the first try # postgres can be slow to service early requests, preventing pleroma from starting on the first try
Restart = "on-failure"; serviceConfig.Restart = "on-failure";
RestartSec = "10s"; serviceConfig.RestartSec = "10s";
};
# systemd.services.pleroma.serviceConfig = { # hardening (systemd-analyze security pleroma)
# # required for sendmail. see https://git.pleroma.social/pleroma/pleroma/-/issues/2259 # XXX(2024-07-28): this hasn't been rigorously tested:
# NoNewPrivileges = lib.mkForce false; # possible that i've set something too strict and won't notice right away
# PrivateTmp = lib.mkForce false; # make sure to test:
# CapabilityBoundingSet = lib.mkForce "~"; # - image/media uploading
# }; serviceConfig.CapabilityBoundingSet = "~CAP_SYS_ADMIN"; #< TODO: reduce this. try: CAP_SYS_NICE CAP_DAC_READ_SEARCH CAP_SYS_CHROOT CAP_SETGID CAP_SETUID
serviceConfig.LockPersonality = true;
serviceConfig.NoNewPrivileges = true;
serviceConfig.MemoryDenyWriteExecute = true;
serviceConfig.PrivateDevices = lib.mkForce true; #< dunno why nixpkgs has this set false; it seems to work as true
serviceConfig.PrivateMounts = true;
serviceConfig.PrivateTmp = true;
serviceConfig.PrivateUsers = true;
serviceConfig.ProtectProc = "invisible";
serviceConfig.ProcSubset = "all"; #< needs /proc/sys/kernel/overflowuid for bwrap
serviceConfig.ProtectClock = true;
serviceConfig.ProtectControlGroups = true;
serviceConfig.ProtectHome = true;
serviceConfig.ProtectKernelModules = true;
serviceConfig.ProtectSystem = lib.mkForce "strict";
serviceConfig.RemoveIPC = true;
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
serviceConfig.RestrictSUIDSGID = true;
serviceConfig.SystemCallArchitectures = "native";
serviceConfig.SystemCallFilter = [ "@system-service" "@mount" "@sandbox" ]; #< "sandbox" might not actually be necessary
serviceConfig.ProtectHostname = false; #< else brap can't mount /proc
serviceConfig.ProtectKernelLogs = false; #< else breaks exiftool ("bwrap: Can't mount proc on /newroot/proc: Operation not permitted")
serviceConfig.ProtectKernelTunables = false; #< else breaks exiftool
serviceConfig.RestrictNamespaces = false; # media uploads require bwrap
};
# this is required to allow pleroma to send email. # this is required to allow pleroma to send email.
# raw `sendmail` works, but i think pleroma's passing it some funny flags or something, idk. # raw `sendmail` works, but i think pleroma's passing it some funny flags or something, idk.

View File

@@ -6,9 +6,9 @@ let
KiB = n: 1024*n; KiB = n: 1024*n;
in in
{ {
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.private = [
# TODO: mode? { user = "postgres"; group = "postgres"; mode = "0750"; path = "/var/lib/postgresql"; method = "bind"; }
{ user = "postgres"; group = "postgres"; path = "/var/lib/postgresql"; method = "bind"; } { user = "postgres"; group = "postgres"; mode = "0750"; path = "/var/backup/postgresql"; method = "bind"; }
]; ];
services.postgresql.enable = true; services.postgresql.enable = true;

View File

@@ -56,7 +56,8 @@ let
enableDebug = false; enableDebug = false;
in in
{ {
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.private = [
# TODO: mode?
{ user = "prosody"; group = "prosody"; path = "/var/lib/prosody"; method = "bind"; } { user = "prosody"; group = "prosody"; path = "/var/lib/prosody"; method = "bind"; }
]; ];
sane.ports.ports."5000" = { sane.ports.ports."5000" = {

View File

@@ -10,7 +10,9 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
{ {
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.ephemeral = [
# {data,downloads,incomplete,logs}: contains logs, search history, and downloads
# so, move the downloaded data to persistent storage regularly, or configure the downloads/incomplete dirs to point to persisted storage (in nixpkgs slskd config)
{ user = "slskd"; group = "media"; path = "/var/lib/slskd"; method = "bind"; } { user = "slskd"; group = "media"; path = "/var/lib/slskd"; method = "bind"; }
]; ];
sops.secrets."slskd_env" = { sops.secrets."slskd_env" = {
@@ -68,12 +70,20 @@
# flags.volatile = true; # store searches and active transfers in RAM (completed transfers still go to disk). rec for btrfs/zfs # flags.volatile = true; # store searches and active transfers in RAM (completed transfers still go to disk). rec for btrfs/zfs
}; };
systemd.services.slskd.serviceConfig = { systemd.services.slskd = {
# run this behind the OVPN static VPN # run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns"; serviceConfig.NetworkNamespacePath = "/run/netns/ovpns";
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect ${config.sane.netns.ovpns.netnsPubIpv4}" ]; # abort if public IP is not as expected serviceConfig.ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect ${config.sane.netns.ovpns.netnsPubIpv4}" ]; # abort if public IP is not as expected
Restart = lib.mkForce "always"; # exits "success" when it fails to connect to soulseek server serviceConfig.Restart = lib.mkForce "always"; # exits "success" when it fails to connect to soulseek server
RestartSec = "60s"; serviceConfig.RestartSec = "60s";
# hardening (systemd-analyze security slskd)
# upstream nixpkgs specifies moderate defaults; these are supplementary
# serviceConfig.MemoryDenyWriteExecute = true;
# serviceConfig.ProcSubset = "pid";
# serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
# serviceConfig.SystemCallArchitectures = "native";
# serviceConfig.SystemCallFilter = [ "@system-service" ];
}; };
} }

View File

@@ -31,14 +31,14 @@ let
"coreutils" "coreutils"
"findutils" "findutils"
"rsync" "rsync"
"util-linux"
]; ];
}; };
in in
{ {
sane.persist.sys.byStore.plaintext = [ sane.persist.sys.byStore.private = [
# TODO: mode? we need this specifically for the stats tracking in .config/ # TODO: mode? we need this specifically for the stats tracking in .config/
{ user = "transmission"; group = config.users.users.transmission.group; path = "/var/lib/transmission"; method = "bind"; } { user = "transmission"; group = config.users.users.transmission.group; path = "/var/lib/transmission"; method = "bind"; }
{ user = "transmission"; group = config.users.users.transmission.group; path = "/var/backup/torrents"; method = "bind"; }
]; ];
users.users.transmission.extraGroups = [ "media" ]; users.users.transmission.extraGroups = [ "media" ];
@@ -107,16 +107,31 @@ in
script-torrent-done-filename = "${torrent-done}/bin/torrent-done"; script-torrent-done-filename = "${torrent-done}/bin/torrent-done";
}; };
systemd.services.transmission.after = [ "wireguard-wg-ovpns.service" ]; systemd.services.transmission = {
systemd.services.transmission.partOf = [ "wireguard-wg-ovpns.service" ]; after = [ "wireguard-wg-ovpns.service" ];
systemd.services.transmission.serviceConfig = { partOf = [ "wireguard-wg-ovpns.service" ];
environment.TR_DEBUG = "1";
# run this behind the OVPN static VPN # run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns"; serviceConfig.NetworkNamespacePath = "/run/netns/ovpns";
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect ${config.sane.netns.ovpns.netnsPubIpv4}" ]; # abort if public IP is not as expected serviceConfig.ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect ${config.sane.netns.ovpns.netnsPubIpv4}" ]; # abort if public IP is not as expected
Restart = "on-failure"; serviceConfig.Restart = "on-failure";
RestartSec = "30s"; serviceConfig.RestartSec = "30s";
BindPaths = [ "/var/media" ]; #< so it can move completed torrents into the media library serviceConfig.BindPaths = [ "/var/media" ]; #< so it can move completed torrents into the media library
serviceConfig.SystemCallFilter = lib.mkForce [
# the torrent-done script does stuff which fails the nixos default syscall filter.
# allow a bunch of stuff, speculatively, to hopefully fix that:
"@aio"
"@basic-io"
"@chown"
"@file-system"
"@io-event"
"@process"
"@sandbox"
"@sync"
"@system-service"
"quotactl"
];
}; };
# service to automatically backup torrents i add to transmission # service to automatically backup torrents i add to transmission

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell #!/usr/bin/env nix-shell
#!nix-shell -i bash -p acl -p bash -p coreutils -p findutils -p rsync -p util-linux #!nix-shell -i bash -p acl -p bash -p coreutils -p findutils -p rsync
# transmission invokes this with no args, and the following env vars: # transmission invokes this with no args, and the following env vars:
# - TR_TORRENT_DIR: full path to the folder i told transmission to download it to. # - TR_TORRENT_DIR: full path to the folder i told transmission to download it to.
@@ -7,7 +7,6 @@
# optionally: # optionally:
# - TR_DRY_RUN=1 # - TR_DRY_RUN=1
# - TR_DEBUG=1 # - TR_DEBUG=1
# - TR_NO_HARDLINK=1
DOWNLOAD_DIR=/var/media/torrents DOWNLOAD_DIR=/var/media/torrents
@@ -41,10 +40,11 @@ REL_DIR="${TR_TORRENT_DIR#$DOWNLOAD_DIR/}"
MEDIA_DIR="/var/media/$REL_DIR" MEDIA_DIR="/var/media/$REL_DIR"
destructive mkdir -p "$(dirname "$MEDIA_DIR")" destructive mkdir -p "$(dirname "$MEDIA_DIR")"
destructive rsync -arv "$TR_TORRENT_DIR/" "$MEDIA_DIR/" destructive rsync -rlv "$TR_TORRENT_DIR/" "$MEDIA_DIR/"
# make the media rwx by anyone in the group # make the media rwx by anyone in the group
destructive find "$MEDIA_DIR" -type d -exec setfacl --recursive --modify d:g::rwx,o::rx {} \; destructive find "$MEDIA_DIR" -type d -exec setfacl --recursive --modify d:g::rwx,o::rx {} \;
destructive find "$MEDIA_DIR" -type d -exec chmod g+rw,a+rx {} \; destructive find "$MEDIA_DIR" -type d -exec chmod g+rw,a+rx {} \;
destructive find "$MEDIA_DIR" -type f -exec chmod g+rw,a+r {} \;
# if there's a single directory inside the media dir, then inline that # if there's a single directory inside the media dir, then inline that
subdirs=("$MEDIA_DIR"/*) subdirs=("$MEDIA_DIR"/*)
@@ -58,19 +58,13 @@ if [ ${#subdirs[@]} -eq 1 ]; then
fi fi
# remove noisy files: # remove noisy files:
# -iname means "insensitive", but the syntax is NOT regex -- more similar to shell matching
destructive find "$MEDIA_DIR/" -type f \(\ destructive find "$MEDIA_DIR/" -type f \(\
-iname '.*downloaded.?from.*' \ -iname '*downloaded?from*' \
-o -iname 'source.txt' \ -o -iname 'source.txt' \
-o -iname 'upcoming.?releases.*' \ -o -iname '*upcoming?releases*' \
-o -iname 'www.YTS.*.jpg' \ -o -iname 'www.YTS*.jpg' \
-o -iname 'WWW.YIFY*.COM.jpg' \ -o -iname 'WWW.YIFY*.COM.jpg' \
-o -iname 'YIFY*.com.txt' \ -o -iname 'YIFY*.com.txt' \
-o -iname 'YTS*.com.txt' \ -o -iname 'YTS*.com.txt' \
\) -exec rm {} \; \) -exec rm {} \;
if ! [ -n "${TR_NO_HARDLINK}" ]; then
# dedupe the whole media library.
# yeah, a bit excessive: move this to a cron job if that's problematic
# or make it run with only 1/N probability, etc.
destructive hardlink /var/media --reflink=always --ignore-time --verbose
fi

View File

@@ -46,5 +46,6 @@
# manifests as spurious "No space left on device" when trying to install watches, # manifests as spurious "No space left on device" when trying to install watches,
# e.g. in dyn-dns by `systemctl start dyn-dns-watcher.path`. # e.g. in dyn-dns by `systemctl start dyn-dns-watcher.path`.
# see: <https://askubuntu.com/questions/828779/failed-to-add-run-systemd-ask-password-to-directory-watch-no-space-left-on-dev> # see: <https://askubuntu.com/questions/828779/failed-to-add-run-systemd-ask-password-to-directory-watch-no-space-left-on-dev>
boot.kernel.sysctl."fs.inotify.max_user_watches" = 1048576; boot.kernel.sysctl."fs.inotify.max_user_watches" = 4194304;
boot.kernel.sysctl."fs.inotify.max_user_instances" = 4194304;
} }

View File

@@ -10,7 +10,6 @@
./machine-id.nix ./machine-id.nix
./net ./net
./nix.nix ./nix.nix
./persist.nix
./polyunfill.nix ./polyunfill.nix
./programs ./programs
./quirks.nix ./quirks.nix

View File

@@ -2,7 +2,9 @@
# - universal search/directory: <https://podcastindex.org> # - universal search/directory: <https://podcastindex.org>
# - list of lists: <https://en.wikipedia.org/wiki/Category:Lists_of_podcasts> # - list of lists: <https://en.wikipedia.org/wiki/Category:Lists_of_podcasts>
# - podcasts w/ a community: <https://lemmyverse.net/communities?query=podcast> # - podcasts w/ a community: <https://lemmyverse.net/communities?query=podcast>
# - podcast rec thread: <https://lemmy.ml/post/1565858> # - podcast recs:
# - active lemmy: <https://slrpnk.net/c/podcasts>
# - old thread: <https://lemmy.ml/post/1565858>
# #
{ lib, sane-data, ... }: { lib, sane-data, ... }:
let let
@@ -57,6 +59,7 @@ let
podcasts = [ podcasts = [
(fromDb "acquiredlpbonussecretsecret.libsyn.com" // tech) # ACQ2 - more "Acquired" episodes (fromDb "acquiredlpbonussecretsecret.libsyn.com" // tech) # ACQ2 - more "Acquired" episodes
(fromDb "allinchamathjason.libsyn.com" // pol) (fromDb "allinchamathjason.libsyn.com" // pol)
(fromDb "api.oyez.org/podcasts/oral-arguments/2015" // pol) # Supreme Court Oral Arguments ("2015" in URL means nothing -- it's still updated)
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech) # Civboot -- https://anchor.fm/civboot (fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech) # Civboot -- https://anchor.fm/civboot
(fromDb "anchor.fm/s/2da69154/podcast/rss" // tech) # POD OF JAKE -- https://podofjake.com/ (fromDb "anchor.fm/s/2da69154/podcast/rss" // tech) # POD OF JAKE -- https://podofjake.com/
(fromDb "cast.postmarketos.org" // tech) (fromDb "cast.postmarketos.org" // tech)
@@ -70,16 +73,17 @@ let
(fromDb "feeds.feedburner.com/radiolab" // pol) # Radiolab -- also available here, but ONLY OVER HTTP: <http://feeds.wnyc.org/radiolab> (fromDb "feeds.feedburner.com/radiolab" // pol) # Radiolab -- also available here, but ONLY OVER HTTP: <http://feeds.wnyc.org/radiolab>
(fromDb "feeds.megaphone.fm/behindthebastards" // pol) # also Maggie Killjoy (fromDb "feeds.megaphone.fm/behindthebastards" // pol) # also Maggie Killjoy
(fromDb "feeds.megaphone.fm/recodedecode" // tech) # The Verge - Decoder (fromDb "feeds.megaphone.fm/recodedecode" // tech) # The Verge - Decoder
(fromDb "feeds.simplecast.com/54nAGcIl" // pol) # The Daily
(fromDb "feeds.simplecast.com/82FI35Px" // pol) # Ezra Klein Show (fromDb "feeds.simplecast.com/82FI35Px" // pol) # Ezra Klein Show
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat) # Econ Talk (fromDb "feeds.simplecast.com/wgl4xEgL" // rat) # Econ Talk
(fromDb "feeds.simplecast.com/xKJ93w_w" // uncat) # Atlas Obscura (fromDb "feeds.simplecast.com/xKJ93w_w" // uncat) # Atlas Obscura
(fromDb "feeds.transistor.fm/acquired" // tech) (fromDb "feeds.transistor.fm/acquired" // tech)
(fromDb "feeds.transistor.fm/complex-systems-with-patrick-mckenzie-patio11" // tech) # Patrick Mackenzie (from Bits About Money)
(fromDb "feeds.twit.tv/floss.xml" // tech) (fromDb "feeds.twit.tv/floss.xml" // tech)
(fromDb "fulltimenix.com" // tech) (fromDb "fulltimenix.com" // tech)
(fromDb "futureofcoding.org/episodes" // tech) (fromDb "futureofcoding.org/episodes" // tech)
(fromDb "hackerpublicradio.org" // tech) (fromDb "hackerpublicradio.org" // tech)
(fromDb "lexfridman.com/podcast" // rat) (fromDb "lexfridman.com/podcast" // rat)
(fromDb "linktr.ee/betteroffline" // pol)
(fromDb "mapspodcast.libsyn.com" // uncat) # Multidisciplinary Association for Psychedelic Studies (fromDb "mapspodcast.libsyn.com" // uncat) # Multidisciplinary Association for Psychedelic Studies
(fromDb "microarch.club" // tech) (fromDb "microarch.club" // tech)
(fromDb "mintcast.org" // tech) (fromDb "mintcast.org" // tech)
@@ -87,8 +91,8 @@ let
(fromDb "omny.fm/shows/cool-people-who-did-cool-stuff" // pol) # Maggie Killjoy -- referenced by Cory Doctorow (fromDb "omny.fm/shows/cool-people-who-did-cool-stuff" // pol) # Maggie Killjoy -- referenced by Cory Doctorow
(fromDb "omny.fm/shows/money-stuff-the-podcast") # Matt Levine (fromDb "omny.fm/shows/money-stuff-the-podcast") # Matt Levine
(fromDb "omny.fm/shows/the-dollop-with-dave-anthony-and-gareth-reynolds") # The Dollop history/comedy (fromDb "omny.fm/shows/the-dollop-with-dave-anthony-and-gareth-reynolds") # The Dollop history/comedy
(fromDb "omny.fm/shows/weird-little-guys") # Cool Zone Media
(fromDb "originstories.libsyn.com" // uncat) (fromDb "originstories.libsyn.com" // uncat)
(fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
(fromDb "politicalorphanage.libsyn.com" // pol) (fromDb "politicalorphanage.libsyn.com" // pol)
(fromDb "reverseengineering.libsyn.com/rss" // tech) # UnNamed Reverse Engineering Podcast (fromDb "reverseengineering.libsyn.com/rss" // tech) # UnNamed Reverse Engineering Podcast
(fromDb "rss.acast.com/deconstructed") # The Intercept - Deconstructed (fromDb "rss.acast.com/deconstructed") # The Intercept - Deconstructed
@@ -111,7 +115,9 @@ let
# (fromDb "feeds.libsyn.com/421877" // rat) # Less Wrong Curated # (fromDb "feeds.libsyn.com/421877" // rat) # Less Wrong Curated
# (fromDb "feeds.megaphone.fm/hubermanlab" // uncat) # Daniel Huberman on sleep # (fromDb "feeds.megaphone.fm/hubermanlab" // uncat) # Daniel Huberman on sleep
# (fromDb "feeds.simplecast.com/54nAGcIl" // pol) # The Daily
# (fromDb "feeds.simplecast.com/l2i9YnTd" // tech // pol) # Hard Fork (NYtimes tech) # (fromDb "feeds.simplecast.com/l2i9YnTd" // tech // pol) # Hard Fork (NYtimes tech)
# (fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
# (fromDb "podcast.thelinuxexp.com" // tech) # low-brow linux/foss PR announcements # (fromDb "podcast.thelinuxexp.com" // tech) # low-brow linux/foss PR announcements
# (fromDb "rss.art19.com/your-welcome" // pol) # Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232> # (fromDb "rss.art19.com/your-welcome" // pol) # Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232>
# (fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol) #< possible URL rot # (fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol) #< possible URL rot
@@ -237,9 +243,9 @@ let
(fromDb "youtube.com/@TheB1M") (fromDb "youtube.com/@TheB1M")
(fromDb "youtube.com/@TomScottGo") (fromDb "youtube.com/@TomScottGo")
(fromDb "youtube.com/@Vihart") (fromDb "youtube.com/@Vihart")
(fromDb "youtube.com/@Vox")
# (fromDb "youtube.com/@Vsauce") # they're all like 1-minute long videos now? what happened @Vsauce?
# (fromDb "youtube.com/@Vox")
# (fromDb "youtube.com/@Vsauce") # they're all like 1-minute long videos now? what happened @Vsauce?
# (fromDb "youtube.com/@rossmanngroup" // pol // tech) # Louis Rossmann # (fromDb "youtube.com/@rossmanngroup" // pol // tech) # Louis Rossmann
]; ];

View File

@@ -45,7 +45,7 @@ let
"gid=100" "gid=100"
]; ];
ssh = common ++ fuse ++ [ ssh = common ++ fuseColin ++ [
"identityfile=/home/colin/.ssh/id_ed25519" "identityfile=/home/colin/.ssh/id_ed25519"
# i *think* idmap=user means that `colin` on `localhost` and `colin` on the remote are actually treated as the same user, even if their uid/gid differs? # i *think* idmap=user means that `colin` on `localhost` and `colin` on the remote are actually treated as the same user, even if their uid/gid differs?
# i.e., local colin's id is translated to/from remote colin's id on every operation? # i.e., local colin's id is translated to/from remote colin's id on every operation?
@@ -107,66 +107,207 @@ let
"connect_timeout=20" "connect_timeout=20"
]; ];
}; };
ifSshAuthorized = lib.mkIf config.sane.hosts.by-name."${config.networking.hostName}".ssh.authorized;
remoteHome = host: { remoteHome = host: {
sane.programs.sshfs-fuse.enableFor.system = true; sane.programs.sshfs-fuse.enableFor.system = true;
system.fsPackages = [
config.sane.programs.sshfs-fuse.package
];
fileSystems."/mnt/${host}/home" = { fileSystems."/mnt/${host}/home" = {
device = "colin@${host}:/home/colin"; device = "sshfs#colin@${host}:/home/colin";
fsType = "fuse.sshfs"; fsType = "fuse3";
options = fsOpts.sshColin ++ fsOpts.lazyMount; options = fsOpts.sshColin ++ fsOpts.lazyMount ++ [
# drop_privileges: after `mount.fuse3` opens /dev/fuse, it will drop all capabilities before invoking sshfs
"drop_privileges"
"auto_unmount" #< ensures that when the fs exits, it releases its mountpoint. then systemd can recognize it as failed.
];
noCheck = true; noCheck = true;
}; };
sane.fs."/mnt/${host}/home" = sane-lib.fs.wanted { sane.fs."/mnt/${host}/home" = {
dir.acl.user = "colin"; dir.acl.user = "colin";
dir.acl.group = "users"; dir.acl.group = "users";
dir.acl.mode = "0700"; dir.acl.mode = "0700";
wantedBy = [ "default.target" ];
mount.depends = [ "network-online.target" ];
mount.mountConfig.ExecSearchPath = [ "/run/current-system/sw/bin" ];
mount.mountConfig.User = "colin";
mount.mountConfig.AmbientCapabilities = "CAP_SETPCAP CAP_SYS_ADMIN";
# hardening (systemd-analyze security mnt-desko-home.mount):
# TODO: i can't use ProtectSystem=full here, because i can't create a new mount space; but...
# with drop_privileges, i *could* sandbox the actual `sshfs` program using e.g. bwrap
mount.mountConfig.CapabilityBoundingSet = "CAP_SETPCAP CAP_SYS_ADMIN";
mount.mountConfig.LockPersonality = true;
mount.mountConfig.MemoryDenyWriteExecute = true;
mount.mountConfig.NoNewPrivileges = true;
mount.mountConfig.ProtectClock = true;
mount.mountConfig.ProtectHostname = true;
mount.mountConfig.RemoveIPC = true;
mount.mountConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
#VVV this includes anything it reads from, e.g. /bin/sh; /nix/store/...
# see `systemd-analyze filesystems` for a full list
mount.mountConfig.RestrictFileSystems = "@common-block @basic-api fuse";
mount.mountConfig.RestrictRealtime = true;
mount.mountConfig.RestrictSUIDSGID = true;
mount.mountConfig.SystemCallArchitectures = "native";
mount.mountConfig.SystemCallFilter = [
"@system-service"
"@mount"
"~@chown"
"~@cpu-emulation"
"~@keyring"
# could remove almost all io calls, however one has to keep `open`, and `write`, to communicate with the fuse device.
# so that's pretty useless as a way to prevent write access
];
mount.mountConfig.IPAddressDeny = "any";
mount.mountConfig.IPAddressAllow = "10.0.0.0/8";
mount.mountConfig.DevicePolicy = "closed"; # only allow /dev/{null,zero,full,random,urandom}
mount.mountConfig.DeviceAllow = "/dev/fuse";
# mount.mountConfig.RestrictNamespaces = true; #< my sshfs sandboxing uses bwrap
}; };
}; };
remoteServo = subdir: { remoteServo = subdir: let
localPath = "/mnt/servo/${subdir}";
systemdName = utils.escapeSystemdPath localPath;
in {
sane.programs.curlftpfs.enableFor.system = true; sane.programs.curlftpfs.enableFor.system = true;
sane.fs."/mnt/servo/${subdir}" = sane-lib.fs.wanted { system.fsPackages = [
dir.acl.user = "colin"; config.sane.programs.curlftpfs.package
dir.acl.group = "users"; ];
dir.acl.mode = "0750"; fileSystems."${localPath}" = {
}; device = "curlftpfs#ftp://servo-hn:/${subdir}";
fileSystems."/mnt/servo/${subdir}" = {
device = "ftp://servo-hn:/${subdir}";
noCheck = true; noCheck = true;
fsType = "fuse.curlftpfs"; fsType = "fuse3";
options = fsOpts.ftp ++ fsOpts.noauto; options = fsOpts.ftp ++ fsOpts.noauto ++ [
# drop_privileges: after `mount.fuse3` opens /dev/fuse, it will drop all capabilities before invoking sshfs
"drop_privileges"
"auto_unmount" #< ensures that when the fs exits, it releases its mountpoint. then systemd can recognize it as failed.
];
# fsType = "nfs"; # fsType = "nfs";
# options = fsOpts.nfs ++ fsOpts.lazyMount; # options = fsOpts.nfs ++ fsOpts.lazyMount;
}; };
systemd.services."automount-servo-${utils.escapeSystemdPath subdir}" = let sane.fs."${localPath}" = {
fs = config.fileSystems."/mnt/servo/${subdir}"; dir.acl.user = "colin";
in { dir.acl.group = "users";
# this is a *flaky* network mount, especially on moby. dir.acl.mode = "0750";
# if done as a normal autofs mount, access will eternally block when network is dropped.
# notably, this would block *any* sandboxed app which allows media access, whether they actually try to use that media or not.
# a practical solution is this: mount as a service -- instead of autofs -- and unmount on timeout error, in a restart loop.
# until the ftp handshake succeeds, nothing is actually mounted to the vfs, so this doesn't slow down any I/O when network is down.
description = "automount /mnt/servo/${subdir} in a fault-tolerant and non-blocking manner";
after = [ "network-online.target" ];
requires = [ "network-online.target" ];
wantedBy = [ "default.target" ]; wantedBy = [ "default.target" ];
mount.depends = [ "network-online.target" "${systemdName}-reachable.service" ];
#VVV patch so that when the mount fails, we start a timer to remount it.
# and for a disconnection after a good mount (onSuccess), restart the timer to be more aggressive
mount.unitConfig.OnFailure = [ "${systemdName}.timer" ];
mount.unitConfig.OnSuccess = [ "${systemdName}-restart-timer.target" ];
serviceConfig.Type = "simple"; mount.mountConfig.TimeoutSec = "10s";
serviceConfig.ExecStart = lib.escapeShellArgs [ mount.mountConfig.ExecSearchPath = [ "/run/current-system/sw/bin" ];
"/usr/bin/env" mount.mountConfig.User = "colin";
"PATH=/run/current-system/sw/bin" mount.mountConfig.AmbientCapabilities = "CAP_SETPCAP CAP_SYS_ADMIN";
"mount.${fs.fsType}" # hardening (systemd-analyze security mnt-servo-playground.mount)
"-f" # foreground (i.e. don't daemonize) mount.mountConfig.CapabilityBoundingSet = "CAP_SETPCAP CAP_SYS_ADMIN";
"-s" # single-threaded (TODO: it's probably ok to disable this?) mount.mountConfig.LockPersonality = true;
"-o" mount.mountConfig.MemoryDenyWriteExecute = true;
(lib.concatStringsSep "," (lib.filter (o: !lib.hasPrefix "x-systemd." o) fs.options)) mount.mountConfig.NoNewPrivileges = true;
fs.device mount.mountConfig.ProtectClock = true;
"/mnt/servo/${subdir}" mount.mountConfig.ProtectHostname = true;
mount.mountConfig.RemoveIPC = true;
mount.mountConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
#VVV this includes anything it reads from, e.g. /bin/sh; /nix/store/...
# see `systemd-analyze filesystems` for a full list
mount.mountConfig.RestrictFileSystems = "@common-block @basic-api fuse";
mount.mountConfig.RestrictRealtime = true;
mount.mountConfig.RestrictSUIDSGID = true;
mount.mountConfig.SystemCallArchitectures = "native";
mount.mountConfig.SystemCallFilter = [
"@system-service"
"@mount"
"~@chown"
"~@cpu-emulation"
"~@keyring"
# could remove almost all io calls, however one has to keep `open`, and `write`, to communicate with the fuse device.
# so that's pretty useless as a way to prevent write access
]; ];
# not sure if this configures a linear, or exponential backoff. mount.mountConfig.IPAddressDeny = "any";
# but the first restart will be after `RestartSec`, and the n'th restart (n = RestartSteps) will be RestartMaxDelaySec after the n-1'th exit. mount.mountConfig.IPAddressAllow = "10.0.10.5";
serviceConfig.Restart = "always"; mount.mountConfig.DevicePolicy = "closed"; # only allow /dev/{null,zero,full,random,urandom}
serviceConfig.RestartSec = "10s"; mount.mountConfig.DeviceAllow = "/dev/fuse";
serviceConfig.RestartMaxDelaySec = "120s"; # mount.mountConfig.RestrictNamespaces = true;
serviceConfig.RestartSteps = "5"; };
systemd.services."${systemdName}-reachable" = {
serviceConfig.ExecSearchPath = [ "/run/current-system/sw/bin" ];
serviceConfig.ExecStart = lib.escapeShellArgs [
"curlftpfs"
"ftp://servo-hn:/${subdir}"
"/dev/null"
"-o"
(lib.concatStringsSep "," ([ "exit_after_connect" ] ++ config.fileSystems."${localPath}".options))
];
serviceConfig.RemainAfterExit = true;
serviceConfig.Type = "oneshot";
unitConfig.BindsTo = [ "${systemdName}.mount" ];
# hardening (systemd-analyze security mnt-servo-playground-reachable.service)
serviceConfig.AmbientCapabilities = "";
serviceConfig.CapabilityBoundingSet = "";
serviceConfig.DynamicUser = true;
serviceConfig.LockPersonality = true;
serviceConfig.MemoryDenyWriteExecute = true;
serviceConfig.NoNewPrivileges = true;
serviceConfig.PrivateDevices = true;
serviceConfig.PrivateMounts = true;
serviceConfig.PrivateTmp = true;
serviceConfig.PrivateUsers = true;
serviceConfig.ProcSubset = "all";
serviceConfig.ProtectClock = true;
serviceConfig.ProtectControlGroups = true;
serviceConfig.ProtectHome = true;
serviceConfig.ProtectKernelModules = true;
serviceConfig.ProtectProc = "invisible";
serviceConfig.ProtectSystem = "strict";
serviceConfig.RemoveIPC = true;
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
# serviceConfig.RestrictFileSystems = "@common-block @basic-api"; #< NOPE
serviceConfig.RestrictRealtime = true;
serviceConfig.RestrictSUIDSGID = true;
serviceConfig.SystemCallArchitectures = "native";
serviceConfig.SystemCallFilter = [
"@system-service"
"@mount"
"~@chown"
"~@cpu-emulation"
"~@keyring"
# "~@privileged" #< NOPE
"~@resources"
# could remove some more probably
];
serviceConfig.IPAddressDeny = "any";
serviceConfig.IPAddressAllow = "10.0.10.5";
serviceConfig.DevicePolicy = "closed";
# exceptions
serviceConfig.ProtectHostname = false;
serviceConfig.ProtectKernelLogs = false;
serviceConfig.ProtectKernelTunables = false;
};
systemd.targets."${systemdName}-restart-timer" = {
# hack unit which, when started, stops the timer (if running), and then starts it again.
after = [ "${systemdName}.timer" ];
conflicts = [ "${systemdName}.timer" ];
upholds = [ "${systemdName}.timer" ];
unitConfig.StopWhenUnneeded = true;
};
systemd.timers."${systemdName}" = {
timerConfig.Unit = "${systemdName}.mount";
timerConfig.AccuracySec = "2s";
timerConfig.OnActiveSec = [
# try to remount at these timestamps, backing off gradually
# there seems to be an implicit mount attempt at t=0.
"10s"
"30s"
"60s"
"120s"
];
# cap the backoff to a fixed interval.
timerConfig.OnUnitActiveSec = [ "120s" ];
}; };
}; };
in in
@@ -212,10 +353,11 @@ lib.mkMerge [
programs.fuse.userAllowOther = true; #< necessary for `allow_other` or `allow_root` options. programs.fuse.userAllowOther = true; #< necessary for `allow_other` or `allow_root` options.
} }
(remoteHome "crappy") (ifSshAuthorized (remoteHome "crappy"))
(remoteHome "desko") (ifSshAuthorized (remoteHome "desko"))
(remoteHome "lappy") (ifSshAuthorized (remoteHome "lappy"))
(remoteHome "moby") (ifSshAuthorized (remoteHome "moby"))
(ifSshAuthorized (remoteHome "servo"))
# this granularity of servo media mounts is necessary to support sandboxing: # this granularity of servo media mounts is necessary to support sandboxing:
# for flaky mounts, we can only bind the mountpoint itself into the sandbox, # for flaky mounts, we can only bind the mountpoint itself into the sandbox,
# so it's either this or unconditionally bind all of media/. # so it's either this or unconditionally bind all of media/.

View File

@@ -1,31 +1,30 @@
{ config, lib, ... }: { config, lib, ... }:
{ {
sane.user.persist.byStore.plaintext = [ sane.user.persist.byStore.plaintext = [
"archive" # TODO: some of ~/dev should be private too, but maybe not all 800+ GB of it
# perhaps i ought to rethink how it's organized
"dev" "dev"
# TODO: records should be private
"records"
"ref" "ref"
"tmp"
"use" "use"
"Books/local" "Books/local"
"Music" "Music"
# this is persisted simply to save on RAM. mesa_shader_cache is < 10 MB.
# TODO: integrate with sane.programs.sandbox?
".cache/mesa_shader_cache"
];
sane.user.persist.byStore.private = [
"archive"
"Pictures/albums" "Pictures/albums"
"Pictures/cat" "Pictures/cat"
"Pictures/from" "Pictures/from"
"Pictures/Screenshots" #< XXX: something is case-sensitive about this? "Pictures/Screenshots" #< XXX: something is case-sensitive about this?
"Pictures/Photos" "Pictures/Photos"
"Videos/local" "records"
"tmp"
# these are persisted simply to save on RAM.
# ~/.cache/nix can become several GB.
# mesa_shader_cache is < 10 MB.
# TODO: integrate with sane.programs.sandbox?
".cache/mesa_shader_cache"
".cache/nix"
];
sane.user.persist.byStore.private = [
"knowledge" "knowledge"
"Videos/local"
]; ];
# convenience # convenience
@@ -34,7 +33,7 @@
in { in {
".persist/private" = lib.mkIf persistEnabled { symlink.target = config.sane.persist.stores.private.origin; }; ".persist/private" = lib.mkIf persistEnabled { symlink.target = config.sane.persist.stores.private.origin; };
".persist/plaintext" = lib.mkIf persistEnabled { symlink.target = config.sane.persist.stores.plaintext.origin; }; ".persist/plaintext" = lib.mkIf persistEnabled { symlink.target = config.sane.persist.stores.plaintext.origin; };
".persist/ephemeral" = lib.mkIf persistEnabled { symlink.target = config.sane.persist.stores.cryptClearOnBoot.origin; }; ".persist/ephemeral" = lib.mkIf persistEnabled { symlink.target = config.sane.persist.stores.ephemeral.origin; };
"nixos".symlink.target = "dev/nixos"; "nixos".symlink.target = "dev/nixos";

View File

@@ -45,8 +45,8 @@
sane.ids.pict-rs.gid = 2409; sane.ids.pict-rs.gid = 2409;
sane.ids.sftpgo.uid = 2410; sane.ids.sftpgo.uid = 2410;
sane.ids.sftpgo.gid = 2410; sane.ids.sftpgo.gid = 2410;
sane.ids.trust-dns.uid = 2411; sane.ids.hickory-dns.uid = 2411; #< previously "trust-dns"
sane.ids.trust-dns.gid = 2411; sane.ids.hickory-dns.gid = 2411; #< previously "trust-dns"
sane.ids.export.gid = 2412; sane.ids.export.gid = 2412;
sane.ids.nfsuser.uid = 2413; sane.ids.nfsuser.uid = 2413;
sane.ids.media.gid = 2414; sane.ids.media.gid = 2414;
@@ -63,6 +63,8 @@
sane.ids.nix-serve.uid = 2420; sane.ids.nix-serve.uid = 2420;
sane.ids.nix-serve.gid = 2420; sane.ids.nix-serve.gid = 2420;
sane.ids.plugdev.gid = 2421; sane.ids.plugdev.gid = 2421;
sane.ids.ollama.uid = 2422;
sane.ids.ollama.gid = 2422;
sane.ids.colin.uid = 1000; sane.ids.colin.uid = 1000;
sane.ids.guest.uid = 1100; sane.ids.guest.uid = 1100;

View File

@@ -12,6 +12,7 @@
systemd.network.enable = true; systemd.network.enable = true;
networking.useNetworkd = true; networking.useNetworkd = true;
networking.usePredictableInterfaceNames = false; #< set false to get `eth0`, `wlan0`, etc instead of `enp3s0`/etc
# view refused/dropped packets with: `sudo journalctl -k` # view refused/dropped packets with: `sudo journalctl -k`
# networking.firewall.logRefusedPackets = true; # networking.firewall.logRefusedPackets = true;

View File

@@ -23,16 +23,16 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
lib.mkMerge [ lib.mkMerge [
{ {
sane.services.trust-dns.enable = lib.mkDefault config.sane.services.trust-dns.asSystemResolver; sane.services.hickory-dns.enable = lib.mkDefault config.sane.services.hickory-dns.asSystemResolver;
sane.services.trust-dns.asSystemResolver = lib.mkDefault true; sane.services.hickory-dns.asSystemResolver = lib.mkDefault true;
} }
(lib.mkIf (!config.sane.services.trust-dns.asSystemResolver) { (lib.mkIf (!config.sane.services.hickory-dns.asSystemResolver) {
# use systemd's stub resolver. # use systemd's stub resolver.
# /etc/resolv.conf isn't sophisticated enough to use different servers per net namespace (or link). # /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 # instead, running the stub resolver on a known address in the root ns lets us rewrite packets
# in servo's ovnps namespace to use the provider's DNS resolvers. # in servo's 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?) # a weakness is we can only query 1 NS at a time (unless we were to clone the packets?)
# TODO: improve trust-dns recursive resolver and then remove this # TODO: improve hickory-dns recursive resolver and then remove this
services.resolved.enable = true; #< to disable, set ` = lib.mkForce false`, as other systemd features default to enabling `resolved`. services.resolved.enable = true; #< to disable, set ` = lib.mkForce false`, as other systemd features default to enabling `resolved`.
# without DNSSEC: # without DNSSEC:
# - dig matrix.org => works # - dig matrix.org => works
@@ -40,7 +40,7 @@ lib.mkMerge [
# with default DNSSEC: # with default DNSSEC:
# - dig matrix.org => works # - dig matrix.org => works
# - curl https://matrix.org => fails # - curl https://matrix.org => fails
# i don't know why. this might somehow be interfering with the DNS run on this device (trust-dns) # i don't know why. this might somehow be interfering with the DNS run on this device (hickory-dns)
services.resolved.dnssec = "false"; services.resolved.dnssec = "false";
networking.nameservers = [ networking.nameservers = [
# use systemd-resolved resolver # use systemd-resolved resolver
@@ -74,7 +74,7 @@ lib.mkMerge [
sane.silencedAssertions = [''.*Loading NSS modules from system.nssModules.*requires services.nscd.enable being set to true.*'']; sane.silencedAssertions = [''.*Loading NSS modules from system.nssModules.*requires services.nscd.enable being set to true.*''];
# add NSS modules into their own subdirectory. # add NSS modules into their own subdirectory.
# then i can add just the NSS modules library path to the global LD_LIBRARY_PATH, rather than ALL of /run/current-system/sw/lib. # then i can add just the NSS modules library path to the global LD_LIBRARY_PATH, rather than ALL of /run/current-system/sw/lib.
# TODO: i'm doing this so as to achieve mdns DNS resolution (avahi). it would be better to just have trust-dns delegate .local to avahi # TODO: i'm doing this so as to achieve mdns DNS resolution (avahi). it would be better to just have hickory-dns delegate .local to avahi
# (except avahi doesn't act as a local resolver over DNS protocol -- only dbus). # (except avahi doesn't act as a local resolver over DNS protocol -- only dbus).
environment.systemPackages = [(pkgs.symlinkJoin { environment.systemPackages = [(pkgs.symlinkJoin {
name = "nss-modules"; name = "nss-modules";

View File

@@ -14,7 +14,6 @@
# after = [ "polkit.service" ]; # after = [ "polkit.service" ];
# requires = [ "polkit.service" ]; # requires = [ "polkit.service" ];
wantedBy = [ "network.target" ]; #< default is `multi-user.target`, somehow it doesn't auto-start with that... wantedBy = [ "network.target" ]; #< default is `multi-user.target`, somehow it doesn't auto-start with that...
path = [ "/run/current-system/sw" ]; #< so it can find `sanebox`
# serviceConfig.Type = "dbus"; # serviceConfig.Type = "dbus";
# serviceConfig.BusName = "org.freedesktop.ModemManager1"; # serviceConfig.BusName = "org.freedesktop.ModemManager1";
@@ -38,7 +37,11 @@
# serviceConfig.RestrictAddressFamilies = "AF_NETLINK AF_UNIX AF_QIPCRTR"; # serviceConfig.RestrictAddressFamilies = "AF_NETLINK AF_UNIX AF_QIPCRTR";
# serviceConfig.NoNewPrivileges = true; # serviceConfig.NoNewPrivileges = true;
serviceConfig.CapabilityBoundingSet = [ "CAP_NET_ADMIN" ]; #< TODO: make sure this is *really* taking effect, and isn't supplemental to upstream's `CAP_SYS_ADMIN` setting serviceConfig.CapabilityBoundingSet = [
"" #< reset upstream capabilities
"CAP_NET_ADMIN"
"CAP_SYS_ADMIN" #< TODO: remove CAP_SYS_ADMIN!
];
serviceConfig.LockPersonality = true; serviceConfig.LockPersonality = true;
# serviceConfig.PrivateUsers = true; #< untried, not likely to work since it needs capabilities # serviceConfig.PrivateUsers = true; #< untried, not likely to work since it needs capabilities
serviceConfig.PrivateTmp = true; serviceConfig.PrivateTmp = true;

View File

@@ -2,21 +2,28 @@
let let
# networkmanager = pkgs.networkmanager; # networkmanager = pkgs.networkmanager;
networkmanager = pkgs.networkmanager.overrideAttrs (upstream: { networkmanager = pkgs.networkmanager.overrideAttrs (upstream: {
src = pkgs.fetchFromGitea { # src = pkgs.fetchFromGitea {
domain = "git.uninsane.org"; # domain = "git.uninsane.org";
owner = "colin"; # owner = "colin";
repo = "NetworkManager"; # repo = "NetworkManager";
# patched to fix polkit permissions (with `nmcli`) when NetworkManager runs as user networkmanager # # patched to fix polkit permissions (with `nmcli`) when NetworkManager runs as user networkmanager
rev = "dev-sane-1.48.0"; # rev = "dev-sane-1.48.0";
hash = "sha256-vGmOKtwVItxjYioZJlb1og3K6u9s4rcmDnjAPLBC3ao="; # hash = "sha256-vGmOKtwVItxjYioZJlb1og3K6u9s4rcmDnjAPLBC3ao=";
}; # };
# patches = []; patches = (upstream.patches or []) ++ [
(pkgs.fetchpatch {
name = "polkit: add owner annotations to all actions";
url = "https://git.uninsane.org/colin/NetworkManager/commit/a01293861fa24201ffaeb84c07f1c71136c49759.patch";
hash = "sha256-th1/M2slo7rjkVBwETZII53Lmhyw8OMS0aT9QYI5Uvk=";
})
];
}); });
# split the package into `daemon` and `nmcli` outputs, because the networkmanager *service* # split the package into `daemon` and `nmcli` outputs, because the networkmanager *service*
# doesn't need `nmcli`/`nmtui` tooling # doesn't need `nmcli`/`nmtui` tooling
networkmanager-split = pkgs.networkmanager-split.override { inherit networkmanager; }; networkmanager-split = pkgs.networkmanager-split.override { inherit networkmanager; };
in { in {
networking.networkmanager.enable = true; networking.networkmanager.enable = true;
systemd.network.wait-online.enable = false; # systemd-networkd-wait-online.service reliably fails on lappy. docs don't match behavior. shit software.
# plugins mostly add support for establishing different VPN connections. # plugins mostly add support for establishing different VPN connections.
# the default plugin set includes mostly proprietary VPNs: # the default plugin set includes mostly proprietary VPNs:
# - fortisslvpn (Fortinet) # - fortisslvpn (Fortinet)
@@ -59,6 +66,11 @@ in {
serviceConfig.User = "networkmanager"; serviceConfig.User = "networkmanager";
serviceConfig.Group = "networkmanager"; serviceConfig.Group = "networkmanager";
serviceConfig.AmbientCapabilities = [ serviceConfig.AmbientCapabilities = [
"CAP_NET_ADMIN"
"CAP_NET_RAW"
"CAP_NET_BIND_SERVICE"
];
serviceConfig.CapabilityBoundingSet = [
# "CAP_DAC_OVERRIDE" # "CAP_DAC_OVERRIDE"
"CAP_NET_ADMIN" "CAP_NET_ADMIN"
"CAP_NET_RAW" #< required, else `libndp: ndp_sock_open: Failed to create ICMP6 socket.` "CAP_NET_RAW" #< required, else `libndp: ndp_sock_open: Failed to create ICMP6 socket.`
@@ -69,6 +81,7 @@ in {
]; ];
serviceConfig.LockPersonality = true; serviceConfig.LockPersonality = true;
serviceConfig.NoNewPrivileges = true; serviceConfig.NoNewPrivileges = true;
serviceConfig.MemoryDenyWriteExecute = true;
serviceConfig.PrivateDevices = true; # remount /dev with just the basics, syscall filter to block @raw-io serviceConfig.PrivateDevices = true; # remount /dev with just the basics, syscall filter to block @raw-io
serviceConfig.PrivateIPC = true; serviceConfig.PrivateIPC = true;
serviceConfig.PrivateTmp = true; serviceConfig.PrivateTmp = true;
@@ -80,7 +93,10 @@ in {
serviceConfig.ProtectKernelLogs = true; # disable /proc/kmsg, /dev/kmsg serviceConfig.ProtectKernelLogs = true; # disable /proc/kmsg, /dev/kmsg
serviceConfig.ProtectKernelModules = true; # syscall filter to prevent module calls (probably not upstreamable: NM will want to load modules like `ppp`) serviceConfig.ProtectKernelModules = true; # syscall filter to prevent module calls (probably not upstreamable: NM will want to load modules like `ppp`)
serviceConfig.ProtectKernelTunables = true; # but NM might need to write /proc/sys/net/... serviceConfig.ProtectKernelTunables = true; # but NM might need to write /proc/sys/net/...
serviceConfig.ProtectProc = "invisible";
serviceConfig.ProcSubset = "pid";
serviceConfig.ProtectSystem = "strict"; # makes read-only: all but /dev, /proc, /sys. serviceConfig.ProtectSystem = "strict"; # makes read-only: all but /dev, /proc, /sys.
serviceConfig.RemoveIPC = true;
serviceConfig.RestrictAddressFamilies = [ serviceConfig.RestrictAddressFamilies = [
"AF_INET" "AF_INET"
"AF_INET6" "AF_INET6"
@@ -91,19 +107,25 @@ in {
# AF_BLUETOOTH ? # AF_BLUETOOTH ?
# AF_BRIDGE ? # AF_BRIDGE ?
]; ];
serviceConfig.RestrictNamespaces = true;
serviceConfig.RestrictSUIDSGID = true; serviceConfig.RestrictSUIDSGID = true;
serviceConfig.SystemCallArchitectures = "native"; # prevents e.g. aarch64 syscalls in the event that the kernel is multi-architecture. serviceConfig.SystemCallArchitectures = "native"; # prevents e.g. aarch64 syscalls in the event that the kernel is multi-architecture.
serviceConfig.SystemCallFilter = [
"@system-service"
# TODO: restrict SystemCallFilter more aggressively
];
# TODO: restrict `DeviceAllow`
# from earlier `landlock` sandboxing, i know it needs these directories: # from earlier `landlock` sandboxing, i know it needs these directories:
# - "/proc/net" # - "/proc/net"
# - "/proc/sys/net" # - "/proc/sys/net"
# - "/run/NetworkManager" # - "/run/NetworkManager"
# - "/run/systemd" # for trust-dns-nmhook # - "/run/systemd" # for hickory-dns-nmhook
# - "/run/udev" # - "/run/udev"
# - # "/run/wg-home.priv" # - # "/run/wg-home.priv"
# - "/sys/class" # - "/sys/class"
# - "/sys/devices" # - "/sys/devices"
# - "/var/lib/NetworkManager" # - "/var/lib/NetworkManager"
# - "/var/lib/trust-dns" #< for trust-dns-nmhook # - "/var/lib/hickory-dns" #< for hickory-dns-nmhook
# - "/run/systemd" # - "/run/systemd"
}; };
@@ -115,7 +137,12 @@ in {
# fix NetworkManager-dispatcher to actually run as a daemon, # fix NetworkManager-dispatcher to actually run as a daemon,
# and sandbox it a bit # and sandbox it a bit
systemd.services.NetworkManager-dispatcher = { systemd.services.NetworkManager-dispatcher = {
after = [ "trust-dns-localhost.service" ]; #< so that /var/lib/trust-dns will exist #VVV so that /var/lib/hickory-dns will exist (the hook needs to write here).
# but this creates a cycle: hickory-dns-localhost > network.target > NetworkManager-dispatcher > hickory-dns-localhost.
# (seemingly) impossible to remove the network.target dep on NetworkManager-dispatcher.
# beffore would be to have the dispatcher not write hickory-dns files
# but rather just its own, and create a .path unit which restarts hickory-dns appropriately.
# after = [ "hickory-dns-localhost.service" ];
# serviceConfig.ExecStart = [ # serviceConfig.ExecStart = [
# "" # first blank line is to clear the upstream `ExecStart` field. # "" # first blank line is to clear the upstream `ExecStart` field.
# "${cfg.package}/libexec/nm-dispatcher --persist" # --persist is needed for it to actually run as a daemon # "${cfg.package}/libexec/nm-dispatcher --persist" # --persist is needed for it to actually run as a daemon
@@ -123,7 +150,7 @@ in {
# serviceConfig.Restart = "always"; # serviceConfig.Restart = "always";
# serviceConfig.RestartSec = "1s"; # serviceConfig.RestartSec = "1s";
# serviceConfig.DynamicUser = true; #< not possible, else we lose group perms (so can't write to `trust-dns`'s files in the nm hook) # serviceConfig.DynamicUser = true; #< not possible, else we lose group perms (so can't write to `hickory-dns`'s files in the nm hook)
serviceConfig.User = "networkmanager"; # TODO: should arguably use `DynamicUser` serviceConfig.User = "networkmanager"; # TODO: should arguably use `DynamicUser`
serviceConfig.Group = "networkmanager"; serviceConfig.Group = "networkmanager";
serviceConfig.LockPersonality = true; serviceConfig.LockPersonality = true;
@@ -139,7 +166,7 @@ in {
serviceConfig.ProtectKernelLogs = true; # disable /proc/kmsg, /dev/kmsg serviceConfig.ProtectKernelLogs = true; # disable /proc/kmsg, /dev/kmsg
serviceConfig.ProtectKernelModules = true; # syscall filter to prevent module calls serviceConfig.ProtectKernelModules = true; # syscall filter to prevent module calls
serviceConfig.ProtectKernelTunables = true; serviceConfig.ProtectKernelTunables = true;
serviceConfig.ProtectSystem = "full"; # makes read-only: /boot, /etc/, /usr. `strict` isn't possible due to trust-dns hook serviceConfig.ProtectSystem = "full"; # makes read-only: /boot, /etc/, /usr. `strict` isn't possible due to hickory-dns hook
serviceConfig.RestrictAddressFamilies = [ serviceConfig.RestrictAddressFamilies = [
"AF_UNIX" # required, probably for dbus or systemd connectivity "AF_UNIX" # required, probably for dbus or systemd connectivity
]; ];
@@ -199,9 +226,15 @@ in {
logging.level = "INFO"; logging.level = "INFO";
# main.dhcp = "internal"; #< default # main.dhcp = "internal"; #< default
# main.dns controls what to do when NM gets a DNS server via DHCP
# - "none" (populate /run/NetworkManager/resolv.conf with DHCP settings)
# - "internal" (?)
# - "systemd-resolved" (tell systemd-resolved about it, and point /run/NetworkManager/resolv.conf -> systemd)
# without this, systemd-resolved won't be able to resolve anything (because it has no upstream servers)
# note that NM's resolv.conf isn't (necessarily) /etc/resolv.conf -- that is managed by nixos (via symlinking)
main.dns = if config.services.resolved.enable then main.dns = if config.services.resolved.enable then
"systemd-resolved" "systemd-resolved"
else if config.sane.services.trust-dns.enable && config.sane.services.trust-dns.asSystemResolver then else if config.sane.services.hickory-dns.enable && config.sane.services.hickory-dns.asSystemResolver then
"none" "none"
else else
"internal" "internal"
@@ -243,7 +276,7 @@ in {
users.users.networkmanager = { users.users.networkmanager = {
isSystemUser = true; isSystemUser = true;
group = "networkmanager"; group = "networkmanager";
extraGroups = [ "trust-dns" ]; extraGroups = [ "hickory-dns" ];
}; };
# there is, unfortunately, no proper interface by which to plumb wpa_supplicant into the NixOS service, except by overlay. # there is, unfortunately, no proper interface by which to plumb wpa_supplicant into the NixOS service, except by overlay.

View File

@@ -1,17 +0,0 @@
{ ... }:
{
# store /home/colin/a/b in /mnt/persist/private/a/b instead of /mnt/persist/private/home/colin/a/b
sane.persist.stores.private.prefix = "/home/colin";
sane.persist.sys.byStore.initrd = [
"/var/log"
];
sane.persist.sys.byStore.plaintext = [
# TODO: these should be private.. somehow
"/var/backup" # for e.g. postgres dumps
];
sane.persist.sys.byStore.cryptClearOnBoot = [
"/var/lib/systemd/coredump"
];
}

View File

@@ -1,12 +1,11 @@
# strictly *decrease* the scope of the default nixos installation/config # strictly *decrease* the scope of the default nixos installation/config
{ lib, pkgs, ... }: { config, lib, pkgs, ... }:
let let
suidlessPam = pkgs.pam.overrideAttrs (upstream: { suidlessPam = pkgs.pam.overrideAttrs (upstream: {
# nixpkgs' pam hardcodes unix_chkpwd path to the /run/wrappers one, # nixpkgs' pam hardcodes unix_chkpwd path to the /run/wrappers one,
# but i don't want the wrapper, so undo that. # but i don't want the wrapper, so undo that.
# ideally i would patch this via an overlay, but pam is in the bootstrap so that forces a full rebuild. # ideally i would patch this via an overlay, but pam is in the bootstrap so that forces a full rebuild.
# TODO: add a `package` option to the nixos' pam module and substitute it that way.
postPatch = (if upstream.postPatch != null then upstream.postPatch else "") + '' postPatch = (if upstream.postPatch != null then upstream.postPatch else "") + ''
substituteInPlace modules/pam_unix/Makefile.am --replace-fail \ substituteInPlace modules/pam_unix/Makefile.am --replace-fail \
"/run/wrappers/bin/unix_chkpwd" "$out/bin/unix_chkpwd" "/run/wrappers/bin/unix_chkpwd" "$out/bin/unix_chkpwd"
@@ -39,8 +38,7 @@ in
])); ]));
}; };
options.security.pam.services = lib.mkOption { options.security.pam.services = lib.mkOption {
apply = services: let apply = lib.filterAttrs (name: _: !(builtins.elem name [
filtered = lib.filterAttrs (name: _: !(builtins.elem name [
# from <repo:nixos/nixpkgs:nixos/modules/security/pam.nix> # from <repo:nixos/nixpkgs:nixos/modules/security/pam.nix>
"i3lock" "i3lock"
"i3lock-color" "i3lock-color"
@@ -62,13 +60,7 @@ in
"usermod" "usermod"
# from <repo:nixos/nixpkgs:nixos/modules/system/boot/systemd/user.nix> # from <repo:nixos/nixpkgs:nixos/modules/system/boot/systemd/user.nix>
"systemd-user" #< N.B.: this causes the `systemd --user` service manager to not be started! "systemd-user" #< N.B.: this causes the `systemd --user` service manager to not be started!
])) services; ]));
in lib.mapAttrs (_serviceName: service: service // {
# replace references with the old pam_unix, which calls into /run/wrappers/bin/unix_chkpwd,
# with a pam_unix that calls into unix_chkpwd via the nix store.
# TODO: use `security.pam.package` instead once <https://github.com/NixOS/nixpkgs/pull/314791> lands.
text = lib.replaceStrings [" pam_unix.so" ] [ " ${suidlessPam}/lib/security/pam_unix.so" ] service.text;
}) filtered;
}; };
options.environment.systemPackages = lib.mkOption { options.environment.systemPackages = lib.mkOption {
@@ -111,7 +103,11 @@ in
# pkgs.which # pkgs.which
# pkgs.zstd # pkgs.zstd
]; ];
in lib.filter (p: ! builtins.elem p requiredPackages); conveniencePackages = [
config.boot.kernelPackages.cpupower # <repo:nixos/nixpkgs:nixos/modules/tasks/cpu-freq.nix> places it on PATH for convenience if powerManagement.cpuFreqGovernor is set
pkgs.kbd # <repo:nixos/nixpkgs:nixos/modules/config/console.nix> places it on PATH as part of console/virtual TTYs, but probably not needed unless you want to set console fonts
];
in lib.filter (p: ! builtins.elem p (requiredPackages ++ conveniencePackages));
}; };
options.system.fsPackages = lib.mkOption { options.system.fsPackages = lib.mkOption {
@@ -212,5 +208,16 @@ in
# see: <repo:nixos/nixpkgs:nixos/modules/virtualisation/nixos-containers.nix> # see: <repo:nixos/nixpkgs:nixos/modules/virtualisation/nixos-containers.nix>
boot.enableContainers = lib.mkDefault false; boot.enableContainers = lib.mkDefault false;
# see: <repo:nixos/nixpkgs:nixos/modules/tasks/lvm.nix>
# lvm places `pkgs.lvm2` onto PATH, which has like 100 binaries.
# it is, actually, needed for some userspace tools (cryptsetup). probably just the udev rules. try to reduce this set?
services.lvm.enable = lib.mkDefault false;
services.udev.packages = [ pkgs.lvm2.out ]; #< N.B. `lvm2.out` != `lvm2`
# systemd.packages = [ pkgs.lvm2 ];
# systemd.tmpfiles.packages = [ pkgs.lvm2.out ];
# environment.systemPackages = [ pkgs.lvm2 ];
security.pam.package = suidlessPam;
}; };
} }

View File

@@ -38,7 +38,9 @@ in
"bridge-utils" # for brctl; debug linux "bridge" inet devices "bridge-utils" # for brctl; debug linux "bridge" inet devices
"btrfs-progs" "btrfs-progs"
"cacert.unbundled" # some services require unbundled /etc/ssl/certs "cacert.unbundled" # some services require unbundled /etc/ssl/certs
"captree"
"cryptsetup" "cryptsetup"
"curl"
"ddrescue" "ddrescue"
"dig" "dig"
"dtc" # device tree [de]compiler "dtc" # device tree [de]compiler
@@ -46,6 +48,7 @@ in
"efibootmgr" "efibootmgr"
"errno" "errno"
"ethtool" "ethtool"
"evtest"
"fatresize" "fatresize"
"fd" "fd"
"file" "file"
@@ -68,7 +71,7 @@ in
"killall" "killall"
"less" "less"
"lftp" "lftp"
# "libcap_ng" # for `netcap` "libcap_ng" # for `netcap`, `pscap`, `captest`
"lsof" "lsof"
"man-pages" "man-pages"
"man-pages-posix" "man-pages-posix"
@@ -79,6 +82,7 @@ in
"neovim" "neovim"
"netcat" "netcat"
"nethogs" "nethogs"
"nix"
"nmap" "nmap"
"nmcli" "nmcli"
"nvme-cli" # nvme "nvme-cli" # nvme
@@ -107,9 +111,6 @@ in
# "zfs" # doesn't cross-compile (requires samba) # "zfs" # doesn't cross-compile (requires samba)
]; ];
sysadminExtraUtils = declPackageSet [ sysadminExtraUtils = declPackageSet [
"backblaze-b2"
"duplicity"
"sane-scripts.backup"
"sqlite" # to debug sqlite3 databases "sqlite" # to debug sqlite3 databases
]; ];
@@ -125,6 +126,7 @@ in
# "dmidecode" # "dmidecode"
"dtrx" # `unar` alternative, "Do The Right eXtraction" "dtrx" # `unar` alternative, "Do The Right eXtraction"
# "efivar" # "efivar"
"exiftool"
"eza" # a better 'ls' "eza" # a better 'ls'
# "flashrom" # "flashrom"
"git" # needed as a user package, for config. "git" # needed as a user package, for config.
@@ -155,8 +157,13 @@ in
# "python3.pkgs.eyeD3" # music tagging # "python3.pkgs.eyeD3" # music tagging
"ripgrep" # needed as a user package so that its user-level config file can be installed "ripgrep" # needed as a user package so that its user-level config file can be installed
"rsync" "rsync"
# "rsyslog" # KEEP THIS HERE if you want persistent logging (TODO: port to systemd, store in /var/log/...)
"sane-deadlines"
"sane-scripts.bittorrent" "sane-scripts.bittorrent"
"sane-scripts.cli" "sane-scripts.cli"
"sane-secrets-unlock"
"sane-sysload"
"sc-im"
# "snapper" # "snapper"
"sops" # for manually viewing secrets; outside `sane-secrets` (TODO: improve sane-secrets!) "sops" # for manually viewing secrets; outside `sane-secrets` (TODO: improve sane-secrets!)
"speedtest-cli" "speedtest-cli"
@@ -275,7 +282,6 @@ in
# "emote" # "emote"
# "evince" # PDF viewer # "evince" # PDF viewer
# "flare-signal" # gtk4 signal client # "flare-signal" # gtk4 signal client
# "foliate" # e-book reader
"fractal" # matrix client "fractal" # matrix client
"g4music" # local music player "g4music" # local music player
# "gnome.cheese" # "gnome.cheese"
@@ -306,14 +312,14 @@ in
"mpv" "mpv"
"networkmanagerapplet" # for nm-connection-editor: it's better than not having any gui! "networkmanagerapplet" # for nm-connection-editor: it's better than not having any gui!
"ntfy-sh" # notification service "ntfy-sh" # notification service
# "newsflash" # RSS viewer "newsflash" # RSS viewer
"pavucontrol" "pavucontrol"
"pwvucontrol" # pipewire version of pavu "pwvucontrol" # pipewire version of pavu
# "picard" # music tagging # "picard" # music tagging
# "libsForQt5.plasmatube" # Youtube player # "libsForQt5.plasmatube" # Youtube player
"signal-desktop" "signal-desktop"
# "snapshot" # camera app # "snapshot" # camera app
"spot" # Gnome Spotify client # "spot" # Gnome Spotify client
# "sublime-music" # "sublime-music"
# "tdesktop" # broken on phosh # "tdesktop" # broken on phosh
# "tokodon" # "tokodon"
@@ -321,6 +327,7 @@ in
"vulkan-tools" # vulkaninfo "vulkan-tools" # vulkaninfo
# "whalebird" # pleroma client (Electron). input is broken on phosh. # "whalebird" # pleroma client (Electron). input is broken on phosh.
"xdg-terminal-exec" "xdg-terminal-exec"
"youtube-tui"
"zathura" # PDF/CBZ/ePUB viewer "zathura" # PDF/CBZ/ePUB viewer
]; ];
@@ -329,9 +336,11 @@ in
# "chatty" # matrix/xmpp/irc client (2023/12/29: disabled because broken cross build) # "chatty" # matrix/xmpp/irc client (2023/12/29: disabled because broken cross build)
# "cozy" # audiobook player # "cozy" # audiobook player
"epiphany" # gnome's web browser "epiphany" # gnome's web browser
"foliate" # e-book reader
# "iotas" # note taking app # "iotas" # note taking app
"komikku" "komikku"
"koreader" "koreader"
"lgtrombetta-compass"
"megapixels" # camera app "megapixels" # camera app
"notejot" # note taking, e.g. shopping list "notejot" # note taking, e.g. shopping list
"planify" # todo-tracker/planner "planify" # todo-tracker/planner
@@ -377,13 +386,13 @@ in
# "monero-gui" # x86-only # "monero-gui" # x86-only
# "mumble" # "mumble"
# "nheko" # Matrix chat client # "nheko" # Matrix chat client
# "nicotine-plus" # soulseek client. before re-enabling this make sure it's properly sandboxed! "nicotine-plus" # soulseek client
# "obsidian" # "obsidian"
# "openscad" # 3d modeling # "openscad" # 3d modeling
# "rhythmbox" # local music player # "rhythmbox" # local music player
# "slic3r" # "slic3r"
"soundconverter" "soundconverter"
"spotify" # x86-only # "spotify" # x86-only
"tor-browser" # x86-only "tor-browser" # x86-only
# "vlc" # "vlc"
"wireshark" # could maybe ship the cli as sysadmin pkg "wireshark" # could maybe ship the cli as sysadmin pkg
@@ -400,12 +409,6 @@ in
backblaze-b2 = {}; backblaze-b2 = {};
bitcoind.sandbox.method = "bwrap";
bitcoind.sandbox.extraHomePaths = [
".config/bitcoin/bitcoin.conf"
];
bitcoind.sandbox.net = "all"; # actually needs only localhost
blanket.buildCost = 1; blanket.buildCost = 1;
blanket.sandbox.method = "bwrap"; blanket.sandbox.method = "bwrap";
blanket.sandbox.whitelistAudio = true; blanket.sandbox.whitelistAudio = true;
@@ -428,17 +431,12 @@ in
btrfs-progs.sandbox.method = "bwrap"; #< bwrap, landlock: both work btrfs-progs.sandbox.method = "bwrap"; #< bwrap, landlock: both work
btrfs-progs.sandbox.autodetectCliPaths = "existing"; # e.g. `btrfs filesystem df /my/fs` btrfs-progs.sandbox.autodetectCliPaths = "existing"; # e.g. `btrfs filesystem df /my/fs`
"cacert.unbundled".sandbox.enable = false; "cacert.unbundled".sandbox.enable = false; #< data only
cargo.persist.byStore.plaintext = [ ".cargo" ]; cargo.persist.byStore.plaintext = [ ".cargo" ];
clang = {}; clang = {};
clightning.sandbox.method = "bwrap";
clightning.sandbox.extraHomePaths = [
".lightning/bitcoin/lightning-rpc"
];
clightning-sane.sandbox.method = "bwrap"; clightning-sane.sandbox.method = "bwrap";
clightning-sane.sandbox.extraPaths = [ clightning-sane.sandbox.extraPaths = [
"/var/lib/clightning/bitcoin/lightning-rpc" "/var/lib/clightning/bitcoin/lightning-rpc"
@@ -513,7 +511,7 @@ in
electrum.sandbox.method = "bwrap"; # TODO:sandbox: untested electrum.sandbox.method = "bwrap"; # TODO:sandbox: untested
electrum.sandbox.net = "all"; # TODO: probably want to make this run behind a VPN, always electrum.sandbox.net = "all"; # TODO: probably want to make this run behind a VPN, always
electrum.sandbox.whitelistWayland = true; electrum.sandbox.whitelistWayland = true;
electrum.persist.byStore.cryptClearOnBoot = [ ".electrum" ]; #< TODO: use XDG dirs! electrum.persist.byStore.ephemeral = [ ".electrum" ]; #< TODO: use XDG dirs!
endless-sky.buildCost = 1; endless-sky.buildCost = 1;
endless-sky.persist.byStore.plaintext = [ ".local/share/endless-sky" ]; endless-sky.persist.byStore.plaintext = [ ".local/share/endless-sky" ];
@@ -530,9 +528,17 @@ in
ethtool.sandbox.method = "landlock"; ethtool.sandbox.method = "landlock";
ethtool.sandbox.capabilities = [ "net_admin" ]; ethtool.sandbox.capabilities = [ "net_admin" ];
evtest.sandbox.method = "bwrap";
evtest.sandbox.autodetectCliPaths = "existingFile"; # `evtest /dev/foo` to monitor events for a specific device
evtest.sandbox.extraPaths = [
"/dev/input"
];
# eza `ls` replacement # eza `ls` replacement
# eza.sandbox.method = "landlock"; # bwrap causes `/proc` files to be listed differently (e.g. `eza /proc/sys/net/ipv6/conf/`)
eza.sandbox.method = "bwrap"; #< note that bwrap causes `/proc` files to be listed differently (e.g. `eza /proc/sys/net/ipv6/conf/`) # bwrap loses group info (so files owned by other users appear as owner "nobody")
eza.sandbox.method = "landlock";
# eza.sandbox.method = "bwrap";
eza.sandbox.autodetectCliPaths = "existing"; eza.sandbox.autodetectCliPaths = "existing";
eza.sandbox.whitelistPwd = true; eza.sandbox.whitelistPwd = true;
eza.sandbox.extraHomePaths = [ eza.sandbox.extraHomePaths = [
@@ -622,6 +628,8 @@ in
"/tmp" # "Cannot open display:" if it can't mount /tmp 👀 "/tmp" # "Cannot open display:" if it can't mount /tmp 👀
]; ];
gitea = {};
gnome-calculator.buildCost = 1; gnome-calculator.buildCost = 1;
gnome-calculator.sandbox.method = "bwrap"; gnome-calculator.sandbox.method = "bwrap";
gnome-calculator.sandbox.whitelistWayland = true; gnome-calculator.sandbox.whitelistWayland = true;
@@ -677,7 +685,7 @@ in
"Pictures/Screenshots" "Pictures/Screenshots"
"Pictures/servo-macros" "Pictures/servo-macros"
]; ];
gnome-frog.persist.byStore.cryptClearOnBoot = [ gnome-frog.persist.byStore.ephemeral = [
".local/share/tessdata" # 15M; dunno what all it is. ".local/share/tessdata" # 15M; dunno what all it is.
]; ];
@@ -759,7 +767,7 @@ in
iotop.sandbox.capabilities = [ "net_admin" ]; iotop.sandbox.capabilities = [ "net_admin" ];
# provides `ip`, `routel`, `bridge`, others. # provides `ip`, `routel`, `bridge`, others.
# landlock works fine for most of these, but `ip netns exec` wants to attach to an existing namespace # landlock works fine for most of these, but `ip netns exec` wants to attach to an existing namespace (which requires sudo)
# and that means we can't use ANY sandboxer for it. # and that means we can't use ANY sandboxer for it.
iproute2.sandbox.enable = false; iproute2.sandbox.enable = false;
# iproute2.sandbox.net = "all"; # iproute2.sandbox.net = "all";
@@ -807,14 +815,23 @@ in
"tmp" "tmp"
]; ];
landlock-sandboxer.sandbox.enable = false; #< sandbox helper
libcamera = {}; libcamera = {};
libcap.sandbox.enable = false; #< for `capsh`, which i use as a sandboxer libcap_ng.sandbox.enable = false; # TODO: `pscap` can sandbox with bwrap, `captest` and `netcap` with landlock
libcap_ng.sandbox.enable = false; # there's something about /proc/$pid/fd which breaks `readlink`/stat with every sandbox technique (except capsh-only)
libnotify.sandbox.method = "bwrap"; libnotify.sandbox.method = "bwrap";
libnotify.sandbox.whitelistDbus = [ "user" ]; # notify-send libnotify.sandbox.whitelistDbus = [ "user" ]; # notify-send
lightning-cli.packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.clightning "lightning-cli";
lightning-cli.sandbox.method = "bwrap";
lightning-cli.sandbox.extraHomePaths = [
".lightning/bitcoin/lightning-rpc"
];
# `lightning-cli` finds its RPC file via `~/.lightning/bitcoin/lightning-rpc`, to message the daemon
lightning-cli.fs.".lightning".symlink.target = "/var/lib/clightning";
losslesscut-bin.buildCost = 1; losslesscut-bin.buildCost = 1;
losslesscut-bin.sandbox.method = "bwrap"; losslesscut-bin.sandbox.method = "bwrap";
losslesscut-bin.sandbox.extraHomePaths = [ losslesscut-bin.sandbox.extraHomePaths = [
@@ -835,8 +852,8 @@ in
lua = {}; lua = {};
man-pages.sandbox.enable = false; man-pages.sandbox.enable = false; #< data only
man-pages-posix.sandbox.enable = false; man-pages-posix.sandbox.enable = false; #< data only
mercurial.sandbox.method = "bwrap"; # TODO:sandbox: untested mercurial.sandbox.method = "bwrap"; # TODO:sandbox: untested
mercurial.sandbox.net = "clearnet"; mercurial.sandbox.net = "clearnet";
@@ -891,7 +908,7 @@ in
nixpkgs-review.sandbox.extraPaths = [ nixpkgs-review.sandbox.extraPaths = [
"/nix" "/nix"
]; ];
nixpkgs-review.persist.byStore.cryptClearOnBoot = [ nixpkgs-review.persist.byStore.ephemeral = [
".cache/nixpkgs-review" #< help it not exhaust / tmpfs ".cache/nixpkgs-review" #< help it not exhaust / tmpfs
]; ];
@@ -942,7 +959,7 @@ in
"/sys/devices" "/sys/devices"
]; ];
"perlPackages.FileMimeInfo".sandbox.enable = false; #< TODO: sandbox `mimetype` but not `mimeopen`. "perlPackages.FileMimeInfo" = {};
powertop.sandbox.method = "landlock"; powertop.sandbox.method = "landlock";
powertop.sandbox.capabilities = [ "ipc_lock" "sys_admin" ]; powertop.sandbox.capabilities = [ "ipc_lock" "sys_admin" ];
@@ -1005,9 +1022,17 @@ in
sane-weather.sandbox.method = "bwrap"; sane-weather.sandbox.method = "bwrap";
sane-weather.sandbox.net = "clearnet"; sane-weather.sandbox.net = "clearnet";
sc-im.sandbox.method = "bwrap";
sc-im.sandbox.autodetectCliPaths = "existingFile";
screen.sandbox.enable = false; #< tty; needs to run anything screen.sandbox.enable = false; #< tty; needs to run anything
sequoia.sandbox.method = "bwrap"; # TODO:sandbox: untested sequoia.packageUnwrapped = pkgs.sequoia.overrideAttrs (_: {
# XXX(2024-07-30): sq_autocrypt_import test failure: "Warning: 9B7DD433F254904A is expired."
doCheck = false;
});
sequoia.buildCost = 1;
sequoia.sandbox.method = "bwrap";
sequoia.sandbox.whitelistPwd = true; sequoia.sandbox.whitelistPwd = true;
sequoia.sandbox.autodetectCliPaths = "existingFileOrParent"; # supports `-o <file-to-create>` sequoia.sandbox.autodetectCliPaths = "existingFileOrParent"; # supports `-o <file-to-create>`
@@ -1035,7 +1060,7 @@ in
# TODO: enable dma heaps for more efficient buffer sharing: <https://gitlab.com/postmarketOS/pmaports/-/issues/2789> # TODO: enable dma heaps for more efficient buffer sharing: <https://gitlab.com/postmarketOS/pmaports/-/issues/2789>
snapshot = {}; snapshot = {};
sops.sandbox.method = "bwrap"; # TODO:sandbox: untested sops.sandbox.method = "bwrap";
sops.sandbox.extraHomePaths = [ sops.sandbox.extraHomePaths = [
".config/sops" ".config/sops"
"nixos" "nixos"
@@ -1076,7 +1101,16 @@ in
sqlite = {}; sqlite = {};
sshfs-fuse = {}; # used by fs.nix sshfs-fuse.sandbox.method = "bwrap"; #< N.B. if you call this from the CLI -- without `mount.fuse` -- set this to `none`
sshfs-fuse.sandbox.net = "all";
sshfs-fuse.sandbox.autodetectCliPaths = "parent";
# sshfs-fuse.sandbox.extraPaths = [
# "/dev/fd" # fuse.mount3 -o drop_privileges passes us data over /dev/fd/3
# "/mnt" # XXX: not sure why i need all this, instead of just /mnt/desko, or /mnt/desko/home, etc
# ];
sshfs-fuse.sandbox.extraHomePaths = [
".ssh/id_ed25519" #< TODO: add -o foo,bar=path/to/thing style arguments to autodetection
];
strace.sandbox.enable = false; #< needs to `exec` its args, and therefore support *anything* strace.sandbox.enable = false; #< needs to `exec` its args, and therefore support *anything*
@@ -1118,7 +1152,7 @@ in
tumiki-fighters.sandbox.whitelistWayland = true; tumiki-fighters.sandbox.whitelistWayland = true;
tumiki-fighters.sandbox.whitelistX = true; tumiki-fighters.sandbox.whitelistX = true;
util-linux.sandbox.enable = false; #< TODO: possible to sandbox if i specific a different profile for each of its ~50 binaries util-linux.sandbox.enable = false; #< TODO: possible to sandbox if i specify a different profile for each of its ~50 binaries
unzip.sandbox.method = "bwrap"; unzip.sandbox.method = "bwrap";
unzip.sandbox.autodetectCliPaths = "existingOrParent"; unzip.sandbox.autodetectCliPaths = "existingOrParent";
@@ -1164,10 +1198,12 @@ in
# `wg`, `wg-quick` # `wg`, `wg-quick`
wireguard-tools.sandbox.method = "landlock"; wireguard-tools.sandbox.method = "landlock";
wireguard-tools.sandbox.net = "all";
wireguard-tools.sandbox.capabilities = [ "net_admin" ]; wireguard-tools.sandbox.capabilities = [ "net_admin" ];
# provides `iwconfig`, `iwlist`, `iwpriv`, ... # provides `iwconfig`, `iwlist`, `iwpriv`, ...
wirelesstools.sandbox.method = "landlock"; wirelesstools.sandbox.method = "landlock";
wirelesstools.sandbox.net = "all";
wirelesstools.sandbox.capabilities = [ "net_admin" ]; wirelesstools.sandbox.capabilities = [ "net_admin" ];
wl-clipboard.sandbox.method = "bwrap"; wl-clipboard.sandbox.method = "bwrap";
@@ -1187,7 +1223,7 @@ in
yarn.persist.byStore.plaintext = [ ".cache/yarn" ]; yarn.persist.byStore.plaintext = [ ".cache/yarn" ];
yt-dlp.sandbox.method = "bwrap"; # TODO:sandbox: untested yt-dlp.sandbox.method = "bwrap";
yt-dlp.sandbox.net = "all"; yt-dlp.sandbox.net = "all";
yt-dlp.sandbox.whitelistPwd = true; # saves to pwd by default yt-dlp.sandbox.whitelistPwd = true; # saves to pwd by default
}; };
@@ -1219,7 +1255,7 @@ in
'' ''
tryNotifyUser() { tryNotifyUser() {
local user="$1" local user="$1"
local new_path="$PATH:${pkgs.sudo}/bin:${pkgs.libnotify}/bin" local new_path="$PATH:/etc/profiles/per-user/$user/bin:${pkgs.sudo}/bin:${pkgs.libnotify}/bin"
local version="$(cat $systemConfig/nixos-version)" local version="$(cat $systemConfig/nixos-version)"
PATH="$new_path" sudo -u "$user" \ PATH="$new_path" sudo -u "$user" \
env PATH="$new_path" NIXOS_VERSION="$version" /bin/sh -c \ env PATH="$new_path" NIXOS_VERSION="$version" /bin/sh -c \
@@ -1227,7 +1263,7 @@ in
} }
'' ''
] ++ lib.mapAttrsToList ] ++ lib.mapAttrsToList
(user: en: lib.optionalString en "tryNotifyUser ${user}") (user: en: lib.optionalString en "tryNotifyUser ${user} > /dev/null")
config.sane.programs.guiApps.enableFor.user config.sane.programs.guiApps.enableFor.user
); );
}; };

View File

@@ -2,7 +2,7 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
sane.programs.ausyscall = { sane.programs.ausyscall = {
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.audit "bin/ausyscall"; packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.audit "ausyscall";
sandbox.method = "landlock"; sandbox.method = "landlock";
}; };

View File

@@ -10,14 +10,26 @@
# - `LD_LIBRARY_PATH=/nix/store/ngwj3jqmxh8k4qji2z0lj7y1f8vzqrn2-nss-mdns-0.15.1/lib getent hosts desko.local` # - `LD_LIBRARY_PATH=/nix/store/ngwj3jqmxh8k4qji2z0lj7y1f8vzqrn2-nss-mdns-0.15.1/lib getent hosts desko.local`
# nss-mdns goes through avahi-daemon, so there IS caching here # nss-mdns goes through avahi-daemon, so there IS caching here
# #
{ config, lib, ... }: { config, lib, pkgs, ... }:
{ {
sane.programs.avahi = { sane.programs.avahi = {
packageUnwrapped = pkgs.avahi.overrideAttrs (upstream: {
# avahi wants to do its own sandboxing opaque to systemd & maybe in conflict with my bwrap.
# --no-drop-root disables that, so that i can e.g. run it as User=avahi, etc.
# do this here, because the service isn't so easily patched.
postInstall = (upstream.postInstall or "") + ''
wrapProgram "$out/sbin/avahi-daemon" \
--add-flags --no-drop-root
'';
nativeBuildInputs = upstream.nativeBuildInputs ++ [
pkgs.makeBinaryWrapper
];
});
sandbox.method = "bwrap"; sandbox.method = "bwrap";
sandbox.whitelistDbus = [ "system" ]; sandbox.whitelistDbus = [ "system" ];
sandbox.net = "all"; #< otherwise it will show 'null' in place of each interface name. sandbox.net = "all"; #< otherwise it will show 'null' in place of each interface name.
sandbox.extraPaths = [ sandbox.extraPaths = [
"/" #< else the daemon exits immediately. TODO: decrease this scope. "/" #< TODO: decrease this, but be weary that the daemon might exit immediately
]; ];
}; };
services.avahi = lib.mkIf config.sane.programs.avahi.enabled { services.avahi = lib.mkIf config.sane.programs.avahi.enabled {
@@ -32,6 +44,7 @@
# particularly, the default config disallows loopback, which is kinda fucking retarded, right? # particularly, the default config disallows loopback, which is kinda fucking retarded, right?
"ens1" #< servo "ens1" #< servo
"enp5s0" #< desko "enp5s0" #< desko
"eth0"
"lo" "lo"
"wg-home" "wg-home"
"wlan0" #< moby "wlan0" #< moby
@@ -39,4 +52,40 @@
"wlp4s0" #< desko "wlp4s0" #< desko
]; ];
}; };
systemd.services.avahi-daemon = lib.mkIf config.sane.programs.avahi.enabled {
# hardening: see `systemd-analyze security avahi-daemon`
serviceConfig.User = "avahi";
serviceConfig.Group = "avahi";
serviceConfig.AmbientCapabilities = "";
serviceConfig.CapabilityBoundingSet = "";
serviceConfig.LockPersonality = true;
serviceConfig.MemoryDenyWriteExecute = true;
serviceConfig.NoNewPrivileges = true;
serviceConfig.PrivateDevices = true;
serviceConfig.PrivateMounts = true;
serviceConfig.PrivateTmp = true;
serviceConfig.PrivateUsers = true;
serviceConfig.ProcSubset = "all";
serviceConfig.ProtectClock = true;
serviceConfig.ProtectControlGroups = true;
serviceConfig.ProtectHome = true;
serviceConfig.ProtectHostname = true;
serviceConfig.ProtectKernelLogs = true;
serviceConfig.ProtectKernelModules = true;
serviceConfig.ProtectKernelTunables = true;
serviceConfig.ProtectProc = "noaccess";
serviceConfig.ProtectSystem = "strict";
serviceConfig.RemoveIPC = true; #< this *might* slow down the initial connection?
serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
serviceConfig.RestrictRealtime = true;
serviceConfig.RestrictSUIDSGID = true;
serviceConfig.SystemCallArchitectures = "native";
serviceConfig.SystemCallFilter = [
"@system-service"
"@mount"
"~@resources"
# "~@privileged"
];
};
} }

View File

@@ -0,0 +1,13 @@
{ pkgs, ... }:
{
sane.programs.bitcoin-cli = {
packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.bitcoind "bitcoin-cli";
sandbox.method = "bwrap";
sandbox.autodetectCliPaths = "existing"; #< for `bitcoin-cli -datadir=/var/lib/...`
sandbox.extraHomePaths = [
".bitcoin/bitcoin.conf"
];
sandbox.net = "all"; # actually needs only localhost
secrets.".bitcoin/bitcoin.conf" = ../../../secrets/servo/bitcoin.conf.bin;
};
}

View File

@@ -21,7 +21,7 @@
sandbox.whitelistDri = true; sandbox.whitelistDri = true;
sandbox.whitelistWayland = true; sandbox.whitelistWayland = true;
persist.byStore.cryptClearOnBoot = [ persist.byStore.ephemeral = [
".cache/BraveSoftware" ".cache/BraveSoftware"
".config/BraveSoftware" ".config/BraveSoftware"
]; ];

View File

@@ -8,6 +8,10 @@
# - the bot will reply with auto-generated username/password plus a SIP server endpoint. # - the bot will reply with auto-generated username/password plus a SIP server endpoint.
# just copy those into gnome-calls' GUI configurator # just copy those into gnome-calls' GUI configurator
# - now gnome-calls can do outbound calls. inbound calls can be routed by messaging the bot: "configure calls" # - now gnome-calls can do outbound calls. inbound calls can be routed by messaging the bot: "configure calls"
#
# user guide:
# - "Use for Calls" means, "when i click a tel: URI, use this account": <https://gitlab.gnome.org/GNOME/calls/-/issues/513>
# - `calls -vvv` for verbosity
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
let let
cfg = config.sane.programs.calls; cfg = config.sane.programs.calls;
@@ -24,7 +28,23 @@ in
}; };
}; };
packageUnwrapped = pkgs.rmDbusServicesInPlace (pkgs.calls.overrideAttrs (upstream: { packageUnwrapped = pkgs.rmDbusServicesInPlace ((pkgs.calls.override {
gtk3 = pkgs.gtk4;
libpeas = pkgs.libpeas2;
wrapGAppsHook3 = pkgs.wrapGAppsHook4;
}).overrideAttrs (upstream: {
# XXX(2024-08-08): v46.3 has a bug where if it has no network connection on launch, it forever stays disconnected & never retries
version = "47_beta.0-unstable-2024-08-08";
src = lib.warnIf (lib.versionOlder "47.0" upstream.version) "gnome-calls outdated; remove src override? (keep UI patches though!)" pkgs.fetchFromGitLab {
domain = "gitlab.gnome.org";
owner = "GNOME";
repo = "calls";
fetchSubmodules = true;
# rev = "main";
rev = "ff213579a52222e7c95e585843d97b5b817b2a8b";
hash = "sha256-0QYC8FJpfg/X2lIjBDooba2idUfpJNQhcpv8Z5I/B4k=";
};
patches = (upstream.patches or []) ++ [ patches = (upstream.patches or []) ++ [
(pkgs.fetchpatch { (pkgs.fetchpatch {
# usability improvement... if the UI is visible, then i can receive calls. otherwise, i can't! # usability improvement... if the UI is visible, then i can receive calls. otherwise, i can't!
@@ -33,6 +53,14 @@ in
hash = "sha256-NoVQV2TlkCcsBt0uwSyK82hBKySUW4pADrJVfLFvWgU="; hash = "sha256-NoVQV2TlkCcsBt0uwSyK82hBKySUW4pADrJVfLFvWgU=";
}) })
]; ];
nativeBuildInputs = upstream.nativeBuildInputs ++ [
pkgs.dbus #< for dbus-run-session (should be test only, but it's not)
];
buildInputs = upstream.buildInputs ++ [
pkgs.libadwaita
];
})); }));
sandbox.method = "bwrap"; sandbox.method = "bwrap";
@@ -55,6 +83,10 @@ in
"gnome-keyring" # to remember the password "gnome-keyring" # to remember the password
]; ];
mime.associations."x-scheme-handler/tel" = "org.gnome.Calls.desktop";
mime.associations."x-scheme-handler/sip" = "org.gnome.Calls.desktop";
mime.associations."x-scheme-handler/sips" = "org.gnome.Calls.desktop";
services.gnome-calls = { services.gnome-calls = {
description = "gnome-calls daemon to monitor incoming SIP calls"; description = "gnome-calls daemon to monitor incoming SIP calls";
partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ]; partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ];

View File

@@ -0,0 +1,7 @@
{ pkgs, ... }:
{
sane.programs.capsh = {
packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.libcap "capsh";
sandbox.enable = false; #< i use `capsh` as a sandboxer.
};
}

View File

@@ -0,0 +1,8 @@
{ pkgs, ... }:
{
sane.programs.captree = {
packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.libcap-with-captree "captree";
sandbox.method = "bwrap";
sandbox.isolatePids = false;
};
}

View File

@@ -0,0 +1,8 @@
{ ... }:
{
sane.programs.curl = {
sandbox.method = "bwrap";
sandbox.net = "all";
sandbox.autodetectCliPaths = "parent"; #< for `-o` option
};
}

View File

@@ -1,35 +1,8 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
sane.programs.curlftpfs = { sane.programs.curlftpfs = {
packageUnwrapped = pkgs.curlftpfs.overrideAttrs (upstream: { packageUnwrapped = pkgs.curlftpfs-sane;
# my fork includes: sandbox.method = "bwrap";
# - per-operation timeouts (CURLOPT_TIMEOUT; would use CURLOPT_LOW_SPEED_TIME/CURLOPT_LOW_SPEED_LIMIT but they don't apply) sandbox.net = "all";
# - exit on timeout (so that one knows to abort the mount, instead of waiting indefinitely)
# - support for "meta" keys found in /etc/fstab
src = pkgs.fetchFromGitea {
domain = "git.uninsane.org";
owner = "colin";
repo = "curlftpfs";
rev = "0890d32e709b5a01153f00d29ed4c00299744f5d";
hash = "sha256-M28PzHqEAkezQdtPeL16z56prwl3BfMZqry0dlpXJls=";
};
# `mount` clears PATH before calling the mount helper (see util-linux/lib/env.c),
# so the traditional /etc/fstab approach of fstype=fuse and device = curlftpfs#URI doesn't work.
# instead, install a `mount.curlftpfs` mount helper. this is what programs like `gocryptfs` do.
postInstall = (upstream.postInstall or "") + ''
ln -s curlftpfs $out/bin/mount.fuse.curlftpfs
ln -s curlftpfs $out/bin/mount.curlftpfs
'';
});
# TODO: try to sandbox this better? maybe i can have fuse (unsandboxed) invoke curlftpfs (sandboxed)?
# - landlock gives EPERM
# - bwrap just silently doesn't mount it, maybe because of setuid stuff around fuse?
# sandbox.method = "capshonly";
# sandbox.net = "all";
# sandbox.capabilities = [
# "sys_admin"
# "sys_module"
# ];
}; };
} }

View File

@@ -12,6 +12,7 @@
./ausyscall.nix ./ausyscall.nix
./avahi.nix ./avahi.nix
./bemenu.nix ./bemenu.nix
./bitcoin-cli.nix
./blast-ugjka ./blast-ugjka
./bonsai.nix ./bonsai.nix
./brave.nix ./brave.nix
@@ -20,12 +21,15 @@
./callaudiod.nix ./callaudiod.nix
./calls.nix ./calls.nix
./cantata.nix ./cantata.nix
./capsh.nix
./captree.nix
./catt.nix ./catt.nix
./celeste64.nix ./celeste64.nix
./chatty.nix ./chatty.nix
./conky ./conky
./cozy.nix ./cozy.nix
./cups.nix ./cups.nix
./curl.nix
./curlftpfs.nix ./curlftpfs.nix
./dbus.nix ./dbus.nix
./dconf.nix ./dconf.nix
@@ -40,10 +44,13 @@
./epiphany.nix ./epiphany.nix
./errno.nix ./errno.nix
./evince.nix ./evince.nix
./exiftool.nix
./fcitx5.nix ./fcitx5.nix
./feedbackd.nix ./feedbackd.nix
./firefox.nix ./firefox.nix
./firefox-xdg-open.nix
./flare-signal.nix ./flare-signal.nix
./foliate.nix
./fontconfig.nix ./fontconfig.nix
./fractal.nix ./fractal.nix
./free.nix ./free.nix
@@ -63,6 +70,7 @@
./gnome-maps.nix ./gnome-maps.nix
./gnome-weather.nix ./gnome-weather.nix
./go2tv.nix ./go2tv.nix
./gocryptfs.nix
./gpodder.nix ./gpodder.nix
./gpsd.nix ./gpsd.nix
./gps-share.nix ./gps-share.nix
@@ -82,6 +90,7 @@
./koreader ./koreader
./less.nix ./less.nix
./lftp.nix ./lftp.nix
./lgtrombetta-compass.nix
./libreoffice.nix ./libreoffice.nix
./lemoa.nix ./lemoa.nix
./loupe.nix ./loupe.nix
@@ -89,6 +98,7 @@
./megapixels.nix ./megapixels.nix
./mepo.nix ./mepo.nix
./mimeo ./mimeo
./mimetype.nix
./mmcli.nix ./mmcli.nix
./mopidy.nix ./mopidy.nix
./mpv ./mpv
@@ -100,6 +110,7 @@
./nheko.nix ./nheko.nix
./nicotine-plus.nix ./nicotine-plus.nix
./nix-index.nix ./nix-index.nix
./nix.nix
./nmcli.nix ./nmcli.nix
./notejot.nix ./notejot.nix
./ntfy-sh.nix ./ntfy-sh.nix
@@ -111,7 +122,7 @@
./open-in-mpv.nix ./open-in-mpv.nix
./pactl.nix ./pactl.nix
./pidof.nix ./pidof.nix
./pipewire.nix ./pipewire
./pkill.nix ./pkill.nix
./planify.nix ./planify.nix
./portfolio-filemanager.nix ./portfolio-filemanager.nix
@@ -121,12 +132,16 @@
./rhythmbox.nix ./rhythmbox.nix
./ripgrep.nix ./ripgrep.nix
./rofi ./rofi
./rsyslog
./rtkit.nix ./rtkit.nix
./s6-rc.nix ./s6-rc.nix
./sane-deadlines.nix
./sane-input-handler ./sane-input-handler
./sane-open.nix ./sane-open.nix
./sane-private-unlock-remote.nix
./sane-screenshot.nix ./sane-screenshot.nix
./sane-scripts.nix ./sane-scripts.nix
./sane-secrets-unlock.nix
./sane-sysload.nix ./sane-sysload.nix
./sane-theme.nix ./sane-theme.nix
./sanebox.nix ./sanebox.nix
@@ -169,10 +184,12 @@
./wvkbd.nix ./wvkbd.nix
./xarchiver.nix ./xarchiver.nix
./xdg-desktop-portal.nix ./xdg-desktop-portal.nix
./xdg-desktop-portal-gnome
./xdg-desktop-portal-gtk.nix ./xdg-desktop-portal-gtk.nix
./xdg-desktop-portal-wlr.nix ./xdg-desktop-portal-wlr.nix
./xdg-terminal-exec.nix ./xdg-terminal-exec.nix
./xdg-utils.nix ./xdg-utils.nix
./youtube-tui.nix
./zathura.nix ./zathura.nix
./zeal.nix ./zeal.nix
./zecwallet-lite.nix ./zecwallet-lite.nix

View File

@@ -32,6 +32,7 @@ in
startCommand = "eg25-control --enable-gps --dump-debug-info --verbose"; startCommand = "eg25-control --enable-gps --dump-debug-info --verbose";
cleanupCommand = "eg25-control --disable-gps --dump-debug-info --verbose"; cleanupCommand = "eg25-control --disable-gps --dump-debug-info --verbose";
depends = [ "eg25-control-powered" ]; depends = [ "eg25-control-powered" ];
partOf = [ "gps" ];
}; };
persist.byStore.plaintext = [ ".cache/eg25-control" ]; #< for cached agps data persist.byStore.plaintext = [ ".cache/eg25-control" ]; #< for cached agps data

View File

@@ -45,6 +45,9 @@
"Videos/servo" "Videos/servo"
"tmp" "tmp"
]; ];
sandbox.extraPaths = [
"/dev/snd" #< needed only when playing embedded audio (not embedded video!)
];
# creds/session keys, etc # creds/session keys, etc
persist.byStore.private = [ ".config/Element" ]; persist.byStore.private = [ ".config/Element" ];

View File

@@ -1,19 +1,15 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
sane.programs.errno = { sane.programs.errno = {
# packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.moreutils "bin/errno"; # packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.moreutils "errno";
# actually, don't build all of moreutils because not all of it builds for cross targets. # actually, don't build all of moreutils because not all of it builds for cross targets.
# some of this can be simplified after <https://github.com/NixOS/nixpkgs/pull/316446>
packageUnwrapped = pkgs.moreutils.overrideAttrs (base: { packageUnwrapped = pkgs.moreutils.overrideAttrs (base: {
makeFlags = (base.makeFlags or []) ++ [ makeFlags = (base.makeFlags or []) ++ [
"BINS=errno" "BINS=errno"
"MANS=errno.1" "MANS=errno.1"
"PERLSCRIPTS=errno" #< Makefile errors if empty, but this works :) "PERLSCRIPTS=errno" #< Makefile errors if empty, but this works :)
"INSTALL_BIN=install"
]; ];
#v disable the perl-specific stuff buildInputs = []; #< errno has no runtime perl deps, and they don't cross compile, so disable them.
propagatedBuildInputs = [];
postInstall = "";
}); });
sandbox.method = "landlock"; sandbox.method = "landlock";

View File

@@ -0,0 +1,7 @@
{ ... }:
{
sane.programs.exiftool = {
sandbox.method = "bwrap";
sandbox.autodetectCliPaths = "existingFile";
};
}

View File

@@ -0,0 +1,13 @@
{ pkgs, ... }:
{
sane.programs.firefox-xdg-open = {
packageUnwrapped = pkgs.firefox-extensions.firefox-xdg-open.systemComponent;
sandbox.method = "bwrap";
sandbox.whitelistDbus = [ "user" ]; # for xdg-open/portals
mime.associations."x-scheme-handler/xdg-open" = "xdg-open.desktop";
suggestedPrograms = [ "xdg-utils" ];
};
}

View File

@@ -105,6 +105,33 @@ let
}; };
# extraPrefs = ... # extraPrefs = ...
}).overrideAttrs (base: { }).overrideAttrs (base: {
nativeBuildInputs = (base.nativeBuildInputs or []) ++ [
pkgs.copyDesktopItems
];
desktopItems = (base.desktopItems or []) ++ [
(pkgs.makeDesktopItem {
name = "${cfg.browser.libName}-in-vpn";
desktopName = "${cfg.browser.libName} (VPN)";
genericName = "Web Browser";
# N.B.: --new-instance ensures we don't reuse an existing differenty-namespaced instance.
# OTOH, it may error about "only one instance can run at a time": close the other instance if you see that.
exec = "${lib.getExe pkgs.sane-scripts.vpn} do default -- ${cfg.browser.libName} --new-instance";
icon = cfg.browser.libName;
categories = [ "Network" "WebBrowser" ];
type = "Application";
})
(pkgs.makeDesktopItem {
name = "${cfg.browser.libName}-stub-dns";
desktopName = "${cfg.browser.libName} (stub DNS)";
genericName = "Web Browser";
# N.B.: --new-instance ensures we don't reuse an existing differently-namespaced instance.
# OTOH, it may error about "only one instance can run at a time": close the other instance if you see that.
exec = "${lib.getExe pkgs.sane-scripts.vpn} do none -- ${cfg.browser.libName} --new-instance";
icon = cfg.browser.libName;
categories = [ "Network" "WebBrowser" ];
type = "Application";
})
];
# de-associate `ctrl+shift+c` from activating the devtools. # de-associate `ctrl+shift+c` from activating the devtools.
# based on <https://stackoverflow.com/a/54260938> # based on <https://stackoverflow.com/a/54260938>
# TODO: could use `zip -f` to only update the one changed file, instead of rezipping everything. # TODO: could use `zip -f` to only update the one changed file, instead of rezipping everything.
@@ -130,7 +157,8 @@ let
echo "omni.ja AFTER:" echo "omni.ja AFTER:"
ls -l $out/lib/${cfg.browser.libName}/browser/omni.ja ls -l $out/lib/${cfg.browser.libName}/browser/omni.ja
# runHook postFixup to allow sane.programs sandbox wrappers to wrap the binaries runHook postBuild
runHook postInstall
runHook postFixup runHook postFixup
''; '';
}); });
@@ -160,7 +188,7 @@ let
persistCache = mkOption { persistCache = mkOption {
description = "optional store name to which persist browser cache"; description = "optional store name to which persist browser cache";
type = types.nullOr types.str; type = types.nullOr types.str;
default = "cryptClearOnBoot"; default = "ephemeral";
}; };
addons = mkOption { addons = mkOption {
type = types.attrsOf addonOpts; type = types.attrsOf addonOpts;
@@ -203,6 +231,11 @@ in
package = pkgs.firefox-extensions.ether-metamask; package = pkgs.firefox-extensions.ether-metamask;
enable = lib.mkDefault false; # until i can disable the first-run notification enable = lib.mkDefault false; # until i can disable the first-run notification
}; };
firefox-xdg-open = {
# test: `xdg-open xdg-open:https://uninsane.org`
package = pkgs.firefox-extensions.firefox-xdg-open;
enable = lib.mkDefault true;
};
i2p-in-private-browsing = { i2p-in-private-browsing = {
package = pkgs.firefox-extensions.i2p-in-private-browsing; package = pkgs.firefox-extensions.i2p-in-private-browsing;
enable = lib.mkDefault config.services.i2p.enable; enable = lib.mkDefault config.services.i2p.enable;
@@ -214,7 +247,7 @@ in
open-in-mpv = { open-in-mpv = {
# test: `open-in-mpv 'mpv:///open?url=https://www.youtube.com/watch?v=dQw4w9WgXcQ'` # test: `open-in-mpv 'mpv:///open?url=https://www.youtube.com/watch?v=dQw4w9WgXcQ'`
package = pkgs.firefox-extensions.open-in-mpv; package = pkgs.firefox-extensions.open-in-mpv;
enable = lib.mkDefault config.sane.programs.open-in-mpv.enabled; enable = lib.mkDefault false;
}; };
sidebery = { sidebery = {
package = pkgs.firefox-extensions.sidebery; package = pkgs.firefox-extensions.sidebery;
@@ -263,13 +296,15 @@ in
# TODO: find a way to not expose ~/.ssh to firefox # TODO: find a way to not expose ~/.ssh to firefox
# - unlock sops at login (or before firefox launch)? # - unlock sops at login (or before firefox launch)?
# - see if ssh has a more formal type of subkey system? # - see if ssh has a more formal type of subkey system?
".ssh/id_ed25519" # ".ssh/id_ed25519"
# ".config/sops" # ".config/sops"
"knowledge/secrets/accounts" "knowledge/secrets/accounts"
]; ];
fs.".config/sops".dir = lib.mkIf cfg.addons.browserpass-extension.enable {}; #< needs to be created, not *just* added to the sandbox fs.".config/sops".dir = lib.mkIf cfg.addons.browserpass-extension.enable {}; #< needs to be created, not *just* added to the sandbox
suggestedPrograms = [ suggestedPrograms = lib.optionals cfg.addons.firefox-xdg-open.enable [
"firefox-xdg-open"
] ++ lib.optionals cfg.addons.open-in-mpv.enable [
"open-in-mpv" "open-in-mpv"
]; ];
@@ -341,13 +376,11 @@ in
// configure which extensions are visible by default (TODO: requires a lot of trial and error) // configure which extensions are visible by default (TODO: requires a lot of trial and error)
// defaultPref("browser.uiCustomization.state", ...); // defaultPref("browser.uiCustomization.state", ...);
// auto-open mpv:// URIs without prompting. // auto-open specific URI schemes without prompting:
// can do this with other protocols too (e.g. matrix?). see about:config for common handlers. defaultPref("network.protocol-handler.external.xdg-open", true); // for firefox-xdg-open extension
defaultPref("network.protocol-handler.external.mpv", true); defaultPref("network.protocol-handler.external.mpv", true); // for open-in-mpv extension
// element:// for Element matrix client defaultPref("network.protocol-handler.external.element", true); // for Element matrix client
defaultPref("network.protocol-handler.external.element", true); defaultPref("network.protocol-handler.external.matrix", true); // for Nheko matrix client
// matrix: for Nheko matrix client
defaultPref("network.protocol-handler.external.matrix", true);
''; '';
# instruct Firefox to put the profile in a predictable directory (so we can do things like persist just it). # instruct Firefox to put the profile in a predictable directory (so we can do things like persist just it).
# XXX: the directory *must* exist, even if empty; Firefox will not create the directory itself. # XXX: the directory *must* exist, even if empty; Firefox will not create the directory itself.
@@ -372,14 +405,14 @@ in
if (cfg.persistData != null) then if (cfg.persistData != null) then
cfg.persistData cfg.persistData
else else
"cryptClearOnBoot" "ephemeral"
; ;
persist.byPath."${cfg.browser.dotDir}/default".store = persist.byPath."${cfg.browser.dotDir}/default".store =
if (cfg.persistData != null) then if (cfg.persistData != null) then
cfg.persistData cfg.persistData
else else
"cryptClearOnBoot" "ephemeral"
; ;
}; };

View File

@@ -1,12 +1,16 @@
# Flare is a 3rd-party GTK4 Signal app. # Flare is a 3rd-party GTK4 Signal app.
# UI is effectively a clone of Fractal. # UI is effectively a clone of Fractal.
# #
### compatibility: ### compatibility (2023-10-30):
# - desko: works fine. pairs, and exchanges contact list (but not message history) with the paired device. exchanges future messages fine. # - desko: works fine. pairs, and exchanges contact list (but not message history) with the paired device. exchanges future messages fine.
# - moby (cross compiled flare-signal-nixified): nope. it pairs, but can only *receive* messages and never *send* them. # - moby (cross compiled flare-signal-nixified): nope. it pairs, but can only *receive* messages and never *send* them.
# - even `rsync`ing the data and keyrings from desko -> moby, still fails in that same manner. # - even `rsync`ing the data and keyrings from desko -> moby, still fails in that same manner.
# - console shows error messages. quite possibly an endianness mismatch somewhere # - console shows error messages. quite possibly an endianness mismatch somewhere
# - moby (partially-emulated flare-signal): works! pairs and can send/receive messages, same as desko. # - moby (partially-emulated flare-signal): works! pairs and can send/receive messages, same as desko.
### compatibility (2024-08-07):
# - linking flare to iOS signal "works", but neither side can exchange messages nor contacts
# in iOS i see "A message from Colin could not be delivered"
# - registering as primary device does not work ("you are not authorized", or some such)
# #
### debugging: ### debugging:
# - `RUST_LOG=flare=trace flare` # - `RUST_LOG=flare=trace flare`
@@ -18,7 +22,7 @@
# ERROR presage::manager] Error opening envelope: ProtobufDecodeError(DecodeError { description: "invalid tag value: 0", stack: [("Content", "data_message")] }), message will be skipped! # ERROR presage::manager] Error opening envelope: ProtobufDecodeError(DecodeError { description: "invalid tag value: 0", stack: [("Content", "data_message")] }), message will be skipped!
# ERROR presage::manager] Error opening envelope: ProtobufDecodeError(DecodeError { description: "invalid tag value: 0", stack: [("Content", "data_message")] }), message will be skipped! # ERROR presage::manager] Error opening envelope: ProtobufDecodeError(DecodeError { description: "invalid tag value: 0", stack: [("Content", "data_message")] }), message will be skipped!
# ``` # ```
# - this occurs on moby, desko, `flare-signal` and `flare-signal-nixified` # - this occurs on moby, desko, `flare-signal` and `flare-signal-nixified` (2023-12-14)
# - the Websocket error seems to be unrelated, occurs during normal/good operation # - the Websocket error seems to be unrelated, occurs during normal/good operation
# - related issues: <https://github.com/whisperfish/presage/issues/152> # - related issues: <https://github.com/whisperfish/presage/issues/152>
# #
@@ -28,7 +32,7 @@
# No current session # No current session
# ERROR presage::manager] Error opening envelope: SignalProtocolError(InvalidKyberPreKeyId), message will be skipped! # ERROR presage::manager] Error opening envelope: SignalProtocolError(InvalidKyberPreKeyId), message will be skipped!
# ``` # ```
# - but signal iOS will still read it. # - but signal iOS will still read it (2023-12-14).
# #
#### HTTP 405 when linking flare to iOS signal: #### HTTP 405 when linking flare to iOS signal:
# [DEBUG libsignal_service_hyper::push_service] HTTP request PUT https://chat.signal.org/v1/devices/{uuid}.{timestamp?}:{b64-string} # [DEBUG libsignal_service_hyper::push_service] HTTP request PUT https://chat.signal.org/v1/devices/{uuid}.{timestamp?}:{b64-string}
@@ -43,7 +47,7 @@
# ), # ),
# ), # ),
# ) # )
# flare matrix suggests the signal endpoint has changed: # flare matrix suggests the signal endpoint has changed (2023-12-14):
# - "/v1/device/link instead of confirming via /v1/devices/{I'd}" # - "/v1/device/link instead of confirming via /v1/devices/{I'd}"
# - this endpoint is declared in libsignal-service-rs (used both by flare and presage) # - this endpoint is declared in libsignal-service-rs (used both by flare and presage)
# - libsignal-service/src/provisioning/manager.rs # - libsignal-service/src/provisioning/manager.rs
@@ -73,5 +77,13 @@
# and it persists some dconf settings (e.g. device name). reset with: # and it persists some dconf settings (e.g. device name). reset with:
# - `dconf reset -f /de/schmidhuberj/Flare/`. # - `dconf reset -f /de/schmidhuberj/Flare/`.
]; ];
#VVV flare complains if its data directory is a symlink, so put it in a subdirectory behind my persistence symlink.
env.FLARE_DATA_PATH = "$HOME/.local/share/flare/data";
# sandbox.method = "bwrap";
# sandbox.net = "clearnet";
# sandbox.whitelistWayland = true;
# sandbox.whitelistDbus = [
# "user" # so i can click on links, at least
# ];
}; };
} }

View File

@@ -0,0 +1,42 @@
# foliate: <https://johnfactotum.github.io/foliate/>
{ ... }:
{
sane.programs.foliate = {
sandbox.method = "bwrap";
sandbox.net = "clearnet"; #< for dictionary, wikipedia, online book libraries
sandbox.whitelistDbus = [ "user" ]; #< when clicking on links
sandbox.whitelistDri = true; # reduces startup time and subjective page flip time
sandbox.whitelistWayland = true;
sandbox.extraHomePaths = [
"Books/local"
"Books/servo"
"tmp" #< for downloaded files
];
sandbox.extraPaths = [
# foliate sandboxes itself with bwrap, which needs these.
# but it actually only cares that /sys/{block,bus,class/block} *exist*: it doesn't care if there's anything in them.
# so bind empty (sub)directories
# and it looks like i might need to keep IPC namespace if i want TTS.
"/sys/block/loop7"
"/sys/bus/container/devices"
"/sys/class/block/loop7"
];
sandbox.autodetectCliPaths = "existing";
persist.byStore.plaintext = [
".local/share/com.github.johnfactotum.Foliate" #< books added, reading position
".cache/com.github.johnfactotum.Foliate" #< webkit cache
];
buildCost = 2; #< webkitgtk 6.0
# these associations were taken from its .desktop file
mime.associations."application/epub+zip" = "com.github.johnfactotum.Foliate.desktop";
mime.associations."application/x-mobipocket-ebook" = "com.github.johnfactotum.Foliate.desktop";
mime.associations."application/vnd.amazon.mobi8-ebook" = "com.github.johnfactotum.Foliate.desktop";
mime.associations."application/x-fictionbook+xml" = "com.github.johnfactotum.Foliate.desktop";
mime.associations."application/x-zip-compressed-fb2" = "com.github.johnfactotum.Foliate.desktop";
mime.associations."application/vnd.comicbook+zip" = "com.github.johnfactotum.Foliate.desktop"; # .cbz
mime.associations."x-scheme-handler/opds" = "com.github.johnfactotum.Foliate.desktop";
mime.priority = 120; #< default is 100; fallback to more specialized cbz handlers, e.g., but keep specializations for epub
};
}

View File

@@ -65,6 +65,9 @@ in
suggestedPrograms = [ "gnome-keyring" ]; suggestedPrograms = [ "gnome-keyring" ];
# direct room links opened from other programs, to fractal.
mime.urlAssociations."^https?://matrix.to/#/.+$" = "org.gnome.Fractal.desktop";
services.fractal = { services.fractal = {
description = "fractal Matrix client"; description = "fractal Matrix client";
partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ]; partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ];

View File

@@ -1,7 +1,7 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
sane.programs.free = { sane.programs.free = {
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.procps "bin/free"; packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.procps "free";
sandbox.method = "bwrap"; sandbox.method = "bwrap";
sandbox.isolatePids = false; sandbox.isolatePids = false;
}; };

View File

@@ -1,7 +1,7 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
sane.programs.gdbus = { sane.programs.gdbus = {
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.glib "bin/gdbus"; packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.glib "gdbus";
sandbox.method = "bwrap"; sandbox.method = "bwrap";
sandbox.whitelistDbus = [ "user" ]; #< XXX: maybe future users will also want system access sandbox.whitelistDbus = [ "user" ]; #< XXX: maybe future users will also want system access

View File

@@ -23,6 +23,13 @@ in
sandbox.net = "clearnet"; sandbox.net = "clearnet";
sandbox.whitelistDbus = [ "user" ]; # notifications sandbox.whitelistDbus = [ "user" ]; # notifications
sandbox.whitelistWayland = true; sandbox.whitelistWayland = true;
sandbox.extraHomePaths = [
# it shouldn't need these, but portal integration seems incomplete?
"tmp"
"Pictures/from"
"Pictures/Photos"
"Pictures/Screenshots"
];
sandbox.extraPaths = [ sandbox.extraPaths = [
# geary sandboxes *itself* with bwrap, and dbus-proxy which, confusingly, causes it to *require* these paths. # geary sandboxes *itself* with bwrap, and dbus-proxy which, confusingly, causes it to *require* these paths.
# TODO: these could maybe be mounted empty. or maybe there's an env-var to disable geary's dbus-proxy. # TODO: these could maybe be mounted empty. or maybe there's an env-var to disable geary's dbus-proxy.

View File

@@ -10,7 +10,7 @@
]; ];
sandbox.capabilities = [ sandbox.capabilities = [
# ipc_lock: used to `mlock` the secrets so they don't get swapped out. # ipc_lock: used to `mlock` the secrets so they don't get swapped out.
# this is optional, and systemd likely doesn't propagate it anyway # this is optional, and user namespacing (bwrap) likely doesn't propagate it anyway
"ipc_lock" "ipc_lock"
]; ];

View File

@@ -10,6 +10,12 @@
# TIPS: # TIPS:
# - use "Northwest" instead of "NW", and "Street" instead of "St", etc. # - use "Northwest" instead of "NW", and "Street" instead of "St", etc.
# otherwise, it might not find your destination! # otherwise, it might not find your destination!
#
# TODO:
# - get gnome-maps to access location services via the xdg-desktop-portal.
# with it not using the portal, it can't open links via the web browser.
# additionally, that prevents OpenStreetMap sign-in.
# even temporarily enabling the portal for OSM doesn't work *after* the portal has been disabled -- because then gnome-maps can't access its passwords (?)
{ pkgs, ... }: { pkgs, ... }:
{ {
sane.programs."gnome.gnome-maps" = { sane.programs."gnome.gnome-maps" = {

View File

@@ -0,0 +1,23 @@
{ ... }:
{
sane.programs.gocryptfs = {
sandbox.method = "landlock";
sandbox.autodetectCliPaths = "existing";
sandbox.capabilities = [
# CAP_SYS_ADMIN is only required if directly invoking gocryptfs
# i.e. not leverage a mount helper like `mount.fuse3-sane`.
"sys_admin"
"chown"
"dac_override"
"dac_read_search"
"fowner"
"lease"
"mknod"
"setgid"
"setuid"
];
suggestedPrograms = [
"util-linux" #< gocryptfs complains that it can't exec `logger`, otherwise
];
};
}

View File

@@ -25,6 +25,12 @@ in
"jq" "jq"
# and systemd, for udevadm # and systemd, for udevadm
]; ];
sandbox.method = "bwrap";
sandbox.net = "all";
sandbox.autodetectCliPaths = "existing"; #< N.B.: `test -f /dev/ttyUSB1` fails, we can't use `existingFile`
sandbox.whitelistDbus = [ "system" ]; #< to register with Avahi
services.gps-share = { services.gps-share = {
description = "gps-share: make local GPS serial readings available over Avahi"; description = "gps-share: make local GPS serial readings available over Avahi";
# usage: # usage:
@@ -41,14 +47,11 @@ in
echo "using $dev for GPS NMEA" echo "using $dev for GPS NMEA"
gps-share "$dev" gps-share "$dev"
''; '';
# TODO: this should be `partOf = [ "gps" ]`: # N.B.: it fails to launch if the NMEA device doesn't yet exist, so don't launch by default; only launch as part of GPS
# it fails to launch if the NMEA device doesn't yet exist, and so restart loop when modem is not booted # dependencyOf = [ "geoclue-agent" ];
dependencyOf = [ "geoclue-agent" ]; partOf = [ "gps" ];
depends = [ "eg25-control-powered" ];
}; };
sandbox.method = "bwrap";
sandbox.net = "all";
sandbox.autodetectCliPaths = "existingFile";
}; };
# TODO: restrict this to just LAN devices!! # TODO: restrict this to just LAN devices!!

View File

@@ -5,10 +5,9 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
sane.programs.gst-device-monitor = { sane.programs.gst-device-monitor = {
packageUnwrapped = (pkgs.linkIntoOwnPackage pkgs.gst_all_1.gst-plugins-base [ packageUnwrapped = (
"bin/gst-device-monitor-1.0" pkgs.linkBinIntoOwnPackage pkgs.gst_all_1.gst-plugins-base "gst-device-monitor-1.0"
"share/man/man1/gst-device-monitor-1.0.1.gz" ).overrideAttrs (base: {
]).overrideAttrs (base: {
# XXX the binaries need `GST_PLUGIN_SYSTEM_PATH_1_0` set to function, # XXX the binaries need `GST_PLUGIN_SYSTEM_PATH_1_0` set to function,
# but nixpkgs doesn't set those (TODO: upstream this!) # but nixpkgs doesn't set those (TODO: upstream this!)
nativeBuildInputs = (base.nativeBuildInputs or []) ++ [ nativeBuildInputs = (base.nativeBuildInputs or []) ++ [

View File

@@ -1,13 +1,6 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
sane.programs.kdenlive = { sane.programs.kdenlive = {
packageUnwrapped = pkgs.kdenlive.override {
ffmpeg-full = pkgs.ffmpeg-full.override {
# avoid expensive samba build for a feature i don't use
withSamba = false;
};
};
buildCost = 1; buildCost = 1;
sandbox.method = "bwrap"; sandbox.method = "bwrap";

View File

@@ -3,10 +3,10 @@
sane.programs.komikku = { sane.programs.komikku = {
packageUnwrapped = pkgs.komikku.overrideAttrs (upstream: { packageUnwrapped = pkgs.komikku.overrideAttrs (upstream: {
preFixup = '' preFixup = ''
# 2024/02/21: render bug which affects only moby: # 2024/07/25: Komikku uses XDG_SESSION_TYPE in the webkitgtk useragent, and errors if it's empty.
# large images render blank in several gtk applications. # XDG_SESSION_DESKTOP is used similarly in debug_info.py.
# may resolve itself as gtk or mesa are updated. # TODO: patch/upstream Komikku
gappsWrapperArgs+=(--set GSK_RENDERER cairo) gappsWrapperArgs+=(--set-default XDG_SESSION_TYPE "unknown" --set-default XDG_SESSION_DESKTOP "unknown")
'' + (upstream.preFixup or ""); '' + (upstream.preFixup or "");
}); });
@@ -16,7 +16,7 @@
sandbox.whitelistDri = true; #< required sandbox.whitelistDri = true; #< required
sandbox.whitelistWayland = true; sandbox.whitelistWayland = true;
buildCost = 2; buildCost = 2; # webkitgtk
secrets.".local/share/komikku/keyrings/plaintext.keyring" = ../../../secrets/common/komikku_accounts.json.bin; secrets.".local/share/komikku/keyrings/plaintext.keyring" = ../../../secrets/common/komikku_accounts.json.bin;
# downloads end up here, and without the toplevel database komikku doesn't know they exist. # downloads end up here, and without the toplevel database komikku doesn't know they exist.
@@ -24,5 +24,11 @@
# also writes to ~/.cache/komikku # also writes to ~/.cache/komikku
".local/share/komikku" ".local/share/komikku"
]; ];
persist.byStore.ephemeral = [
".cache/komikku"
];
# XXX(2024-08-08): komikku can handle URLs from sources it understands (maybe), but not files (even if encoded as file:// URI)
# mime.associations."application/vnd.comicbook+zip" = "info.febvre.Komikku.desktop"; # .cbz
}; };
} }

View File

@@ -4,5 +4,15 @@
sandbox.method = "bwrap"; sandbox.method = "bwrap";
sandbox.autodetectCliPaths = "existingFile"; sandbox.autodetectCliPaths = "existingFile";
env.PAGER = "less"; env.PAGER = "less";
# LESS flags:
# - F = quit if output fits on one screen
# - K = exit on ctrl+c
# - M = "long prompt"
# - R = output raw control characters
# - S = chop long lines instead of wrapping
# - X = Don't use termcap init/deinit strings (hence, `less` output is visible on the terminal even after exiting)
# SYSTEMD_LESS defaults to FRSXMK
env.LESS = "FRMK";
env.SYSTEMD_LESS = "FRMK"; #< used by journalctl
}; };
} }

View File

@@ -9,5 +9,6 @@
"Videos/servo" "Videos/servo"
"tmp" "tmp"
]; ];
sandbox.whitelistPwd = true; #< it's very common to upload/DL to/from the current folder
}; };
} }

View File

@@ -0,0 +1,26 @@
{ ... }:
{
sane.programs.lgtrombetta-compass = {
# example compass.conf, calibrated well
# [settings]
# version = 0.4.0
# theme = dark
#
# [device]
# name = AF8133J
# magn_x_offset = 281
# magn_y_offset = -35
# magn_z_offset = 537
#
persist.byStore.plaintext = [
".config/compass"
];
fs.".config/compass.conf".symlink.target = "compass/compass.conf";
sandbox.method = "bwrap";
sandbox.extraPaths = [
"/sys/bus/iio/devices"
"/sys/devices"
];
};
}

View File

@@ -2,14 +2,15 @@
{ {
sane.programs.loupe = { sane.programs.loupe = {
# loupe is marked "dbus activatable", which does not seem to actually work (at least when launching from Firefox or Nautilus) # loupe is marked "dbus activatable", which does not seem to actually work (at least when launching from Firefox or Nautilus)
packageUnwrapped = pkgs.rmDbusServicesInPlace (pkgs.loupe.overrideAttrs (upstream: { packageUnwrapped = pkgs.rmDbusServicesInPlace pkgs.loupe;
preFixup = (upstream.preFixup or "") + '' # .overrideAttrs (upstream: {
# 2024/02/21: render bug which affects only moby: # preFixup = (upstream.preFixup or "") + ''
# large images render blank in several gtk applications. # # 2024/02/21: render bug which affects only moby:
# may resolve itself as gtk or mesa are updated. # # large images render blank in several gtk applications.
gappsWrapperArgs+=(--set GSK_RENDERER cairo) # # may resolve itself as gtk or mesa are updated.
''; # gappsWrapperArgs+=(--set GSK_RENDERER cairo)
})); # '';
# }));
sandbox.method = "bwrap"; sandbox.method = "bwrap";
sandbox.whitelistWayland = true; sandbox.whitelistWayland = true;

View File

@@ -0,0 +1,8 @@
{ pkgs, ... }:
{
sane.programs.mimetype = {
packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.perlPackages.FileMimeInfo "mimetype";
sandbox.method = "bwrap";
sandbox.autodetectCliPaths = "existing";
};
}

View File

@@ -149,8 +149,9 @@ in
pkgs.mpvScripts.mpris pkgs.mpvScripts.mpris
pkgs.mpvScripts.mpv-playlistmanager pkgs.mpvScripts.mpv-playlistmanager
pkgs.mpvScripts.mpv-webm pkgs.mpvScripts.mpv-webm
pkgs.mpvScripts.sponsorblock
uosc uosc
visualizer # visualizer #< XXX(2024-07-23): `visualizer` breaks auto-play-next-track (only when visualizations are disabled)
# pkgs.mpv-uosc-latest # pkgs.mpv-uosc-latest
]; ];
# extraMakeWrapperArgs = lib.optionals (cfg.config.vo != null) [ # extraMakeWrapperArgs = lib.optionals (cfg.config.vo != null) [
@@ -223,12 +224,13 @@ in
fs.".config/mpv/scripts/sane_sysvol/non_blocking_popen.lua".symlink.target = ./sane_sysvol/non_blocking_popen.lua; fs.".config/mpv/scripts/sane_sysvol/non_blocking_popen.lua".symlink.target = ./sane_sysvol/non_blocking_popen.lua;
fs.".config/mpv/input.conf".symlink.target = ./input.conf; fs.".config/mpv/input.conf".symlink.target = ./input.conf;
fs.".config/mpv/mpv.conf".symlink.target = ./mpv.conf; fs.".config/mpv/mpv.conf".symlink.target = ./mpv.conf;
fs.".config/mpv/script-opts/osc.conf".symlink.target = ./osc.conf;
fs.".config/mpv/script-opts/console.conf".symlink.target = ./console.conf; fs.".config/mpv/script-opts/console.conf".symlink.target = ./console.conf;
fs.".config/mpv/script-opts/uosc.conf".symlink.target = ./uosc.conf; fs.".config/mpv/script-opts/osc.conf".symlink.target = ./osc.conf;
fs.".config/mpv/script-opts/playlistmanager.conf".symlink.target = ./playlistmanager.conf; fs.".config/mpv/script-opts/playlistmanager.conf".symlink.target = ./playlistmanager.conf;
fs.".config/mpv/script-opts/webm.conf".symlink.target = ./webm.conf; fs.".config/mpv/script-opts/sponsorblock.conf".symlink.target = ./sponsorblock.conf;
fs.".config/mpv/script-opts/uosc.conf".symlink.target = ./uosc.conf;
fs.".config/mpv/script-opts/visualizer.conf".symlink.target = ./visualizer.conf; fs.".config/mpv/script-opts/visualizer.conf".symlink.target = ./visualizer.conf;
fs.".config/mpv/script-opts/webm.conf".symlink.target = ./webm.conf;
# mime.priority = 200; # default = 100; 200 means to yield to other apps # mime.priority = 200; # default = 100; 200 means to yield to other apps
mime.priority = 50; # default = 100; 50 in order to take precedence over vlc. mime.priority = 50; # default = 100; 50 in order to take precedence over vlc.
@@ -241,10 +243,16 @@ in
mime.associations."video/webm" = "mpv.desktop"; mime.associations."video/webm" = "mpv.desktop";
mime.associations."video/x-flv" = "mpv.desktop"; mime.associations."video/x-flv" = "mpv.desktop";
mime.associations."video/x-matroska" = "mpv.desktop"; mime.associations."video/x-matroska" = "mpv.desktop";
mime.urlAssociations."^https?://(m\.)?(www\.)?youtu.be/.+" = "mpv.desktop"; #v be the opener for YouTube videos
mime.urlAssociations."^https?://(m\.)?(www\.)?youtube.com/shorts/.+" = "mpv.desktop"; mime.urlAssociations."^https?://(m\.)?(www\.)?youtu.be/.+$" = "mpv.desktop";
mime.urlAssociations."^https?://(m\.)?(www\.)?youtube.com/v/" = "mpv.desktop"; mime.urlAssociations."^https?://(m\.)?(www\.)?youtube.com/embed/.+$" = "mpv.desktop";
mime.urlAssociations."^https?://(m\.)?(www\.)?youtube.com/watch\?.*v=" = "mpv.desktop"; mime.urlAssociations."^https?://(m\.)?(www\.)?youtube.com/playlist\?.*list=.+$" = "mpv.desktop";
mime.urlAssociations."^https?://(m\.)?(www\.)?youtube.com/shorts/.+$" = "mpv.desktop";
mime.urlAssociations."^https?://(m\.)?(www\.)?youtube.com/v/.+$" = "mpv.desktop";
mime.urlAssociations."^https?://(m\.)?(www\.)?youtube.com/watch\?.*v=.+$" = "mpv.desktop";
#v be the opener for A/V, generally. useful for e.g. feed readers like News Flash which open content through the portal
mime.urlAssociations."^https?://.*\.(mp3|mp4|ogg|ogv|opus|webm)(\\?.*)?$" = "mpv.desktop";
#v Loupe image viewer can't open URIs, so use mpv instead
mime.urlAssociations."^https?://i\.imgur.com/.+$" = "mpv.desktop";
}; };
} }

View File

@@ -16,25 +16,27 @@ MBTN_LEFT_DBL ignore
# text after the shebang is parsed by uosc to construct the menu and names # text after the shebang is parsed by uosc to construct the menu and names
menu script-binding uosc/menu menu script-binding uosc/menu
s script-binding uosc/subtitles #! Subtitles s script-binding uosc/subtitles #! Subtitles
a script-binding uosc/audio #! Audio tracks a script-binding uosc/audio #! Audio track
q script-binding uosc/stream-quality #! Stream quality q script-binding uosc/stream-quality #! Stream quality
p script-binding uosc/items #! Playlist # script-binding uosc/audio-device #! Audio device
# c script-binding uosc/chapters #! Chapters
> script-binding uosc/next #! Navigation > Next
< script-binding uosc/prev #! Navigation > Prev
o script-binding uosc/open-file #! Navigation > Open file
# set video-aspect-override "-1" #! Utils > Aspect ratio > Default
# set video-aspect-override "16:9" #! Utils > Aspect ratio > 16:9
# set video-aspect-override "4:3" #! Utils > Aspect ratio > 4:3
# set video-aspect-override "2.35:1" #! Utils > Aspect ratio > 2.35:1
# script-binding uosc/audio-device #! Utils > Audio devices
# script-binding uosc/editions #! Utils > Editions
ctrl+s async screenshot #! Utils > Screenshot
alt+i script-binding uosc/keybinds #! Utils > Key bindings
O script-binding uosc/show-in-directory #! Utils > Show in directory
# script-binding uosc/open-config-directory #! Utils > Open config directory
ctrl+r script-binding sane_cast/blast #! Audiocast ctrl+r script-binding sane_cast/blast #! Audiocast
ctrl+t script-binding sane_cast/sane-cast #! Cast ctrl+t script-binding sane_cast/sane-cast #! Cast
ctrl+s async screenshot #! Screenshot
O script-binding uosc/show-in-directory #! Open folder
# reserved: it uses this internally, isn't externally callable # uosc defaults, kept here but unused
p script-binding uosc/items # Playlist
# script-binding uosc/chapters # Chapters
> script-binding uosc/next # Navigation > Next
< script-binding uosc/prev # Navigation > Prev
o script-binding uosc/open-file # Navigation > Open file
# set video-aspect-override "-1" # Utils > Aspect ratio > Default
# set video-aspect-override "16:9" # Utils > Aspect ratio > 16:9
# set video-aspect-override "4:3" # Utils > Aspect ratio > 4:3
# set video-aspect-override "2.35:1" # Utils > Aspect ratio > 2.35:1
# script-binding uosc/editions # Utils > Editions
# script-binding uosc/open-config-directory # Utils > Open config directory
alt+i script-binding uosc/keybinds # Utils > Key bindings
#
# mpv-visualizer: reserved: it uses this internally, isn't externally callable
# v script-binding cycle-visualizer # v script-binding cycle-visualizer

View File

@@ -0,0 +1,19 @@
## options: <https://github.com/po5/mpv_sponsorblock/blob/master/sponsorblock.lua#L8>
audio_fade=yes
### audio_fade_step: 0 - 100
### how rapidly to fade the volume into/out of sponsor segments (%/100ms).
### note that this doesn't impact the time at which the fade starts: that's fixed to 1.0s before the transitions
# audio_fade_step=2
# local_pattern uses lua's string matching, an excepts to yield a 11 character ID: <https://www.lua.org/manual/5.3/manual.html#6.4.1>
# local_pattern=-([%w-_]+)%.[mw][kpe][v4b]m?$ #< default; broken
# local_pattern=%[([%w-_]+)%]%..* #< described by tomasklaen <https://github.com/po5/mpv_sponsorblock/issues/67>
# local_pattern=[ %p]([%w-_]+)%p.webm$ #< works; only webm
# local_pattern=[ %p]([%w-_]+)%p.[mw][kpe][v4b]m?$ #< works, by merging the above
local_pattern=%[([%w-_]+)%]%..*
min_duration=10
report_views=no
# XXX(2024-07-22) local_database/server_fallback are unmaintained <https://github.com/po5/mpv_sponsorblock/commit/d05c6e7a5675ef6582e60abe853e9aec535c3ea3>
# local_database=yes
# server_fallback=no
# skip_categories=sponsor,intro,outro,interaction,selfpromo,filler
skip_categories=sponsor,intro

View File

@@ -5,14 +5,15 @@
timeline_style=bar timeline_style=bar
timeline_line_width=4 timeline_line_width=4
timeline_size=36 timeline_size=36
timeline_persistency=paused,audio # persistency options (comma-separated): paused, audio, image, video, idle, windowed, fullscreen
controls_persistency=paused,audio timeline_persistency=audio,paused
controls_persistency=audio,paused,windowed
volume_persistency=audio volume_persistency=audio
# speed_persistency=paused,audio # speed_persistency=paused,audio
# vvv want a close button? # vvv want a close button?
top_bar=always top_bar=always
top_bar_persistency=paused,audio top_bar_persistency=paused,audio,windowed
controls=menu,<video>subtitles,<has_many_audio>audio,<has_many_video>video,<has_many_edition>editions,<stream>stream-quality,space,command:replay_10:seek -10,cycle:play_arrow:pause:no=pause/yes=play_arrow,command:forward_30:seek 30,space,speed:1.0,gap,<video>fullscreen controls=menu,<video>subtitles,<has_many_audio>audio,<has_many_video>video,<has_many_edition>editions,<stream>stream-quality,space,command:replay_10:seek -10,cycle:play_arrow:pause:no=pause/yes=play_arrow,command:forward_30:seek 30,space,speed:1.0,gap,<video>fullscreen
@@ -30,3 +31,6 @@ color=foreground=ff968b,background_text=ff968b
opacity=timeline=0.8,position=1,chapters=0.8,slider=0.8,slider_gauge=0.8,controls=0,speed=0.8,menu=1,submenu=0.4,border=1,title=0.8,tooltip=1,thumbnail=1,curtain=0.8,idle_indicator=0.8,audio_indicator=0.5,buffering_indicator=0.3,playlist_position=0.8 opacity=timeline=0.8,position=1,chapters=0.8,slider=0.8,slider_gauge=0.8,controls=0,speed=0.8,menu=1,submenu=0.4,border=1,title=0.8,tooltip=1,thumbnail=1,curtain=0.8,idle_indicator=0.8,audio_indicator=0.5,buffering_indicator=0.3,playlist_position=0.8
stream_quality_options=1440,1080,720,480,360,240,144 stream_quality_options=1440,1080,720,480,360,240,144
# default open-file menu directory
default_directory=~/Music

View File

@@ -22,8 +22,17 @@
"/" "/"
".persist/ephemeral" ".persist/ephemeral"
".persist/plaintext" ".persist/plaintext"
"Pictures/Photos"
"Pictures/Screenshots"
"Pictures/albums"
"Pictures/cat"
"Pictures/from"
"Videos/local"
"archive"
"knowledge" "knowledge"
"nixos" "nixos"
"records"
"tmp"
]; ];
sandbox.extraPaths = [ sandbox.extraPaths = [
"/boot" "/boot"

View File

@@ -1,8 +1,10 @@
# news-flash RSS viewer # news-flash RSS viewer (exe: `io.gitlab.news_flash.NewsFlash`)
# - feeds have to be manually imported: # - feeds have to be manually imported:
# - Local RSS -> Import OPML -> ~/.config/newsflashFeeds.opml # - Local RSS -> Import OPML -> ~/.config/newsflashFeeds.opml
# - clicking article-embedded links doesn't work because of xdg portal stuff # option may be greyed out on first run: just restart it.
# - need to either run unsandboxed, or install a org.freedesktop.portal.OpenURI handler # takes about 20 minutes to import results from scratch.
# TODO: auto-import feeds
# - `newsflash -s` might allow importing individual feeds; not removing them, though
{ config, sane-lib, ... }: { config, sane-lib, ... }:
let let
@@ -13,8 +15,31 @@ let
wanted-feeds = feeds.filterByFormat [ "text" "image" "podcast" "video" ] all-feeds; wanted-feeds = feeds.filterByFormat [ "text" "image" "podcast" "video" ] all-feeds;
in { in {
sane.programs.newsflash = { sane.programs.newsflash = {
sandbox.method = "bwrap";
sandbox.net = "clearnet";
sandbox.whitelistAudio = true; #< for embedded videos
sandbox.whitelistDbus = [ "user" ];
sandbox.whitelistDri = true;
sandbox.whitelistWayland = true;
sandbox.extraPaths = [
# the app sandboxes itself with bwrap, which needs these.
# but it actually only cares that /sys/{block,bus,class/block} *exist*: it doesn't care if there's anything in them.
# so bind empty (sub)directories
"/sys/block/loop7"
"/sys/bus/container/devices"
"/sys/class/block/loop7"
];
buildCost = 2; # mainly for desktop: webkitgtk-6.0 buildCost = 2; # mainly for desktop: webkitgtk-6.0
persist.byStore.plaintext = [ ".local/share/news-flash" ]; persist.byStore.plaintext = [
".local/share/news-flash" #< sqlite database, the actually important stuff
# ".local/share/news_flash" #< device IDs (?)
".config/news-flash" #< includes `"backend": "local_rss"`
];
persist.byStore.ephemeral = [
".cache/news_flash" #< WebKit cache
];
#v for *manual* use:
fs.".config/newsflashFeeds.opml".symlink.text = fs.".config/newsflashFeeds.opml".symlink.text =
feeds.feedsToOpml wanted-feeds feeds.feedsToOpml wanted-feeds
; ;

View File

@@ -1,13 +1,35 @@
# soulseek filesharing GUI app # soulseek music sharing GUI app
{ pkgs, ... }: { pkgs, ... }:
{ {
sane.programs.nicotine-plus = { sane.programs.nicotine-plus = {
packageUnwrapped = pkgs.nicotine-plus.overrideAttrs (upstream: {
# nicotine gets confused by permissions. it needs a *writeable* config or config.old to use either.
# but the secrets are not writable.
# so, copy config (the secret) to config.old on launch & make it writeable.
postInstall = ''
wrapProgramShell $out/bin/nicotine \
--run "cp --update=none ~/.config/nicotine/config ~/.config/nicotine/config.old" \
--run "chmod u+w ~/.config/nicotine/config.old"
${upstream.postInstall}
'';
});
sandbox.method = "bwrap"; sandbox.method = "bwrap";
sandbox.whitelistDri = true; #< required, else it fails to launch the gui
sandbox.whitelistWayland = true; sandbox.whitelistWayland = true;
sandbox.net = "vpn"; sandbox.net = "vpn";
sandbox.extraHomePaths = [
"Music"
# on run, nicotine will try to move the initial config to `config.old`
# and then update the config on disk. it errors if it can't `mv` it like that.
".config/nicotine"
];
# ".config/nicotine": contains the config file, with plaintext creds. # the config has loooads of options, but the only critical one is auth/creds.
# TODO: define this as a secret instead of persisting it. # run with ~/.config/nicotine in the sandbox and nicotine will derive the whole config
persist.byStore.private = [ ".config/nicotine" ]; # and write back *all* options for you to then edit further.
secrets.".config/nicotine/config" = ../../../secrets/common/nicotine-config.bin;
persist.byStore.plaintext = [
".local/share/nicotine/downloads"
];
}; };
} }

View File

@@ -0,0 +1,10 @@
{ ... }:
{
sane.programs.nix = {
env.NIXPKGS_ALLOW_UNFREE = "1"; #< FUCK OFF YOU'RE SO ANNOYING
persist.byStore.plaintext = [
# ~/.cache/nix can become several GB; persisted to save RAM
".cache/nix"
];
};
}

View File

@@ -147,7 +147,6 @@ in
suggestedPrograms = [ suggestedPrograms = [
"brightnessctl" "brightnessctl"
"pactl" # pactl required by `per-app-volume` component. "pactl" # pactl required by `per-app-volume` component.
"sane-die-with-parent"
] ++ lib.optionals (cfg.config.torch != null) [ ] ++ lib.optionals (cfg.config.torch != null) [
"torch-toggle" "torch-toggle"
]; ];
@@ -205,6 +204,7 @@ in
"/sys/devices" "/sys/devices"
]; ];
sandbox.extraRuntimePaths = [ "sway" ]; sandbox.extraRuntimePaths = [ "sway" ];
sandbox.isolatePids = false; #< nwg-panel restarts itself on display dis/connect, by killing all other instances.
services.nwg-panel = { services.nwg-panel = {
description = "nwg-panel status/topbar for wayland"; description = "nwg-panel status/topbar for wayland";
@@ -214,7 +214,7 @@ in
# N.B.: G_MESSAGES_DEBUG=all causes the swaync icon to not render # N.B.: G_MESSAGES_DEBUG=all causes the swaync icon to not render
# command = "env G_MESSAGES_DEBUG=all nwg-panel"; # command = "env G_MESSAGES_DEBUG=all nwg-panel";
# XXX: try `nwg-panel & ; kill $$`. the inner nwg-panel doesn't die (without sane-die-with-parent), and hence the service would be prone to maintaining _multiple_ bars. # XXX: try `nwg-panel & ; kill $$`. the inner nwg-panel doesn't die (without sane-die-with-parent), and hence the service would be prone to maintaining _multiple_ bars.
command = "sane-die-with-parent --descendants --signal SIGKILL nwg-panel"; command = "nwg-panel";
}; };
}; };
} }

View File

@@ -3,7 +3,7 @@
sane.programs.objdump = { sane.programs.objdump = {
# binutils-unwrapped is like 80 MiB, just for this one binary; # binutils-unwrapped is like 80 MiB, just for this one binary;
# dynamic linking means copying the binary doesn't reduce the closure much at all compared to just symlinking it. # dynamic linking means copying the binary doesn't reduce the closure much at all compared to just symlinking it.
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.binutils-unwrapped "bin/objdump"; packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.binutils-unwrapped "objdump";
sandbox.method = "bwrap"; sandbox.method = "bwrap";
sandbox.autodetectCliPaths = "existingFile"; sandbox.autodetectCliPaths = "existingFile";
}; };

View File

@@ -1,7 +1,7 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
sane.programs.pactl = { sane.programs.pactl = {
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.pulseaudio "bin/pactl"; packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.pulseaudio "pactl";
sandbox.method = "bwrap"; sandbox.method = "bwrap";
sandbox.whitelistAudio = true; sandbox.whitelistAudio = true;
}; };

View File

@@ -1,7 +1,7 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
sane.programs.pidof = { sane.programs.pidof = {
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.procps "bin/pidof"; packageUnwrapped = pkgs.linkBinIntoOwnPackage pkgs.procps "pidof";
sandbox.method = "bwrap"; sandbox.method = "bwrap";
sandbox.isolatePids = false; sandbox.isolatePids = false;
}; };

View File

@@ -0,0 +1,191 @@
# Headphone surround sink
#
# source: <repo:pipewire/pipewire:src/daemon/filter-chain/spatializer-7.1.conf>
# but modified:
# - applied a gain to the mixer.
context.modules = [
{ name = libpipewire-module-filter-chain
flags = [ nofail ]
args = {
node.description = "Spatial Sink"
media.name = "Spatial Sink"
filter.graph = {
nodes = [
{
type = sofa
label = spatializer
name = spFL
config = {
filename = "/etc/profiles/per-user/colin/share/libmysofa/default.sofa"
}
control = {
"Azimuth" = 30.0
"Elevation" = 0.0
"Radius" = 3.0
}
}
{
type = sofa
label = spatializer
name = spFR
config = {
filename = "/etc/profiles/per-user/colin/share/libmysofa/default.sofa"
}
control = {
"Azimuth" = 330.0
"Elevation" = 0.0
"Radius" = 3.0
}
}
{
type = sofa
label = spatializer
name = spFC
config = {
filename = "/etc/profiles/per-user/colin/share/libmysofa/default.sofa"
}
control = {
"Azimuth" = 0.0
"Elevation" = 0.0
"Radius" = 3.0
}
}
{
type = sofa
label = spatializer
name = spRL
config = {
filename = "/etc/profiles/per-user/colin/share/libmysofa/default.sofa"
}
control = {
"Azimuth" = 150.0
"Elevation" = 0.0
"Radius" = 3.0
}
}
{
type = sofa
label = spatializer
name = spRR
config = {
filename = "/etc/profiles/per-user/colin/share/libmysofa/default.sofa"
}
control = {
"Azimuth" = 210.0
"Elevation" = 0.0
"Radius" = 3.0
}
}
{
type = sofa
label = spatializer
name = spSL
config = {
filename = "/etc/profiles/per-user/colin/share/libmysofa/default.sofa"
}
control = {
"Azimuth" = 90.0
"Elevation" = 0.0
"Radius" = 3.0
}
}
{
type = sofa
label = spatializer
name = spSR
config = {
filename = "/etc/profiles/per-user/colin/share/libmysofa/default.sofa"
}
control = {
"Azimuth" = 270.0
"Elevation" = 0.0
"Radius" = 3.0
}
}
{
type = sofa
label = spatializer
name = spLFE
config = {
filename = "/etc/profiles/per-user/colin/share/libmysofa/default.sofa"
}
control = {
"Azimuth" = 0.0
"Elevation" = -60.0
"Radius" = 3.0
}
}
{
type = builtin
label = mixer
name = mixL
control = {
# gains are derived experimentally:
# - find a source mixed for stereo, and also 5.1
# - tune these gains until the mix sounds about equally loud
# i expect this gain should actually be lower (e.g. 0.33 instead of 0.50), since i define a 7.1 stage here
# so my 5.1 test probably left 1/3 of the virtual speakers "silent"
"Gain 1" = 0.50
"Gain 2" = 0.50
"Gain 3" = 0.50
"Gain 4" = 0.50
"Gain 5" = 0.50
"Gain 6" = 0.50
"Gain 7" = 0.50
"Gain 8" = 0.50
}
}
{
type = builtin
label = mixer
name = mixR
control = {
"Gain 1" = 0.50
"Gain 2" = 0.50
"Gain 3" = 0.50
"Gain 4" = 0.50
"Gain 5" = 0.50
"Gain 6" = 0.50
"Gain 7" = 0.50
"Gain 8" = 0.50
}
}
]
links = [
# output
{ output = "spFL:Out L" input="mixL:In 1" }
{ output = "spFL:Out R" input="mixR:In 1" }
{ output = "spFR:Out L" input="mixL:In 2" }
{ output = "spFR:Out R" input="mixR:In 2" }
{ output = "spFC:Out L" input="mixL:In 3" }
{ output = "spFC:Out R" input="mixR:In 3" }
{ output = "spRL:Out L" input="mixL:In 4" }
{ output = "spRL:Out R" input="mixR:In 4" }
{ output = "spRR:Out L" input="mixL:In 5" }
{ output = "spRR:Out R" input="mixR:In 5" }
{ output = "spSL:Out L" input="mixL:In 6" }
{ output = "spSL:Out R" input="mixR:In 6" }
{ output = "spSR:Out L" input="mixL:In 7" }
{ output = "spSR:Out R" input="mixR:In 7" }
{ output = "spLFE:Out L" input="mixL:In 8" }
{ output = "spLFE:Out R" input="mixR:In 8" }
]
inputs = [ "spFL:In" "spFR:In" "spFC:In" "spLFE:In" "spRL:In" "spRR:In", "spSL:In", "spSR:In" ]
outputs = [ "mixL:Out" "mixR:Out" ]
}
capture.props = {
node.name = "effect_input.spatializer"
media.class = Audio/Sink
audio.channels = 8
audio.position = [ FL FR FC LFE RL RR SL SR ]
}
playback.props = {
node.name = "effect_output.spatializer"
node.passive = true
audio.channels = 2
audio.position = [ FL FR ]
}
}
}
]

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