Compare commits
610 Commits
wip-mpv-sy
...
master
Author | SHA1 | Date | |
---|---|---|---|
62dbad3486 | |||
4287ecf0ed | |||
b13ca92b72 | |||
45e121eb1c | |||
53bbd611da | |||
f0128b9496 | |||
368169d48d | |||
cb1d5d53c6 | |||
a5a635f00b | |||
6fe3d26b30 | |||
8340cf059f | |||
e0da3ece60 | |||
8ea379d53b | |||
c7dd49af91 | |||
e8b900c722 | |||
36f4fa3018 | |||
d8d11de9bc | |||
07194d062a | |||
24c49df75f | |||
9f7e143d5e | |||
0a382ae8a3 | |||
96f177ceb2 | |||
2aa3fa35b8 | |||
8657cf1fcf | |||
f875db916d | |||
e3e86a43a9 | |||
05986d363d | |||
539d9e45a2 | |||
a380bd04c4 | |||
f296d8df93 | |||
326bf045b0 | |||
a1181a10ea | |||
9bb6a903bb | |||
214f963d89 | |||
c7eb4b66a5 | |||
452543e6f3 | |||
d692ac9851 | |||
5cba283859 | |||
7a701f92eb | |||
3c3a32e436 | |||
07aec3ca3c | |||
58d5f11c7a | |||
ed2d4ef488 | |||
e8f8866032 | |||
a2dfd8f08e | |||
c7fd3d2217 | |||
0fcc3f8d5d | |||
0bb887158b | |||
6570c5ed84 | |||
820fdecfd5 | |||
8d43565f31 | |||
18364761dd | |||
d3937487e6 | |||
3fdeacc336 | |||
847414ac1f | |||
84f2006115 | |||
7f5e12da8d | |||
afa8a3c52e | |||
bfbcb4789b | |||
2531cc1cf6 | |||
e55b75c333 | |||
adb54657d4 | |||
6eefb9ce20 | |||
2233622bb7 | |||
274a7821a7 | |||
4c84d1a727 | |||
175acf6442 | |||
0761b6135a | |||
66c899d099 | |||
4aeb3360d3 | |||
0c456d11d8 | |||
3b73773169 | |||
9ba8ff738b | |||
f1d397940f | |||
fa94fa8e6c | |||
4b9c125c8c | |||
0f7d25d8a5 | |||
140641729e | |||
32124d76bf | |||
c5c174f988 | |||
29bc1608aa | |||
635ca1e5d8 | |||
2789868703 | |||
c40ec1990a | |||
d4dfcd6510 | |||
d865be952a | |||
7c8a18ecbd | |||
35ff7de06e | |||
00d06db66a | |||
c570b7bf5d | |||
770fc2e574 | |||
0ed7eb24fb | |||
ad8e75b6a3 | |||
e8dbe0750d | |||
1378988f21 | |||
b88467771e | |||
4309d887da | |||
1ee21c4795 | |||
fb7bcbb5f5 | |||
0013e8305e | |||
7dedfcebb9 | |||
753b97ffb4 | |||
247fc1f887 | |||
3c2ca46ef9 | |||
95dc395925 | |||
cefd6c0534 | |||
05efec8fd7 | |||
e8846b2d6b | |||
be38d56717 | |||
7d242ab02c | |||
47611eaa26 | |||
9719f0f785 | |||
8042ea76e6 | |||
c59236509b | |||
50e5206b0e | |||
4ba0343315 | |||
cbe6072c03 | |||
bea1fd95e5 | |||
ae544c0649 | |||
b571f70988 | |||
e6498ad152 | |||
976b8ae45e | |||
ab7c4d7410 | |||
d2c3bec98e | |||
3c5e5632ee | |||
dcedb8d3f0 | |||
8586db59f1 | |||
1f4d500b02 | |||
56b846023b | |||
747d6c876d | |||
f38d2d52d2 | |||
04bbf54385 | |||
f2271180dd | |||
60b1ab1429 | |||
db3636641d | |||
54a891504d | |||
8ea5061bef | |||
b6d19a7a09 | |||
439be20be7 | |||
a024f685c3 | |||
9c20cef6ea | |||
abb65e55c6 | |||
a2d385708f | |||
f6f1a6e136 | |||
7941a8b1ed | |||
bbcf8841ea | |||
063b0be5b6 | |||
7e490f5c07 | |||
10a985e7f9 | |||
f3c3df2ca7 | |||
f477604063 | |||
d46fa8a242 | |||
62b2eb874c | |||
133c1b3699 | |||
1b4300dbeb | |||
a1c1a87dd8 | |||
92b9a56894 | |||
b159240b7f | |||
8a9f96eefc | |||
af5aa15c23 | |||
a03099569c | |||
b1c7061b21 | |||
c528bb3ec9 | |||
002639cc76 | |||
45967fde7b | |||
ed97a81ef3 | |||
f158842c70 | |||
90d428be7f | |||
9d7b68eeb4 | |||
8951df2e2c | |||
3a045f4d88 | |||
57d6a9a4c3 | |||
2ee39ca0cc | |||
9d9211c5fa | |||
9ce7dcd57a | |||
af72f312d3 | |||
efa1ee6c69 | |||
6a15434cc6 | |||
59e4256dd8 | |||
6365bb7594 | |||
8cb73687ce | |||
73f5c9608e | |||
b035d312aa | |||
a5e1a804c9 | |||
7c6813ff37 | |||
7b1bc210fd | |||
118ed5f950 | |||
ffe599e5cb | |||
fc52860dfc | |||
377b1a21a8 | |||
a7881ecfce | |||
692bc89cbb | |||
842651efd5 | |||
27b4d4da16 | |||
e407467e55 | |||
30c677fafc | |||
ac59083e01 | |||
49b48b24fc | |||
4bc6a4fc67 | |||
844a128d60 | |||
d25fb31767 | |||
309797fe23 | |||
a6b10244eb | |||
18ec5505c4 | |||
e6dbf2d530 | |||
a9e31539ea | |||
2ccb4d94c5 | |||
ca57fd692f | |||
e6a8f5bae8 | |||
d9922f8aa8 | |||
c51dcb30a2 | |||
03dab63042 | |||
293af36d25 | |||
0a1b1ae52f | |||
5952c275a0 | |||
ea8eaaa91a | |||
14a92b3f64 | |||
c5e7ef7b0c | |||
b6d31e127d | |||
7f71a47d3b | |||
2640253424 | |||
42d11998e8 | |||
d0734947bf | |||
41b385b6ca | |||
2e07797065 | |||
b8a7ac8c95 | |||
cda70b2a16 | |||
4834b61188 | |||
134b27f70e | |||
a47102e152 | |||
6eb75b3841 | |||
3d295e8757 | |||
e3a20477f7 | |||
7fd527c9d6 | |||
c21ddca1fd | |||
f7cc3fc5d9 | |||
875fe315c0 | |||
47da8e55f3 | |||
3b99bb497b | |||
cfedcc91bd | |||
ce663b1346 | |||
9873353d00 | |||
d58bdf82d9 | |||
9c2cc9641b | |||
5a92b07f5d | |||
f20a0ac409 | |||
87c84f0e2e | |||
c0a6313023 | |||
26e347f38c | |||
2d67b78ca4 | |||
38c2db0333 | |||
631e0db7b4 | |||
5619bb3334 | |||
e9d94f2c71 | |||
67f0d22ec6 | |||
0fc4f83fc9 | |||
1b24bd50f9 | |||
f481ef077c | |||
1952e210f0 | |||
58ef2cf863 | |||
da4c71d5f6 | |||
41bc4ac7b4 | |||
6365a58c3e | |||
3361f2bbe7 | |||
c987f13ef0 | |||
ee36f2f052 | |||
09457bee5a | |||
278631b59e | |||
4d09cce1aa | |||
b2f2f88dc6 | |||
cbbddee152 | |||
68275eeb85 | |||
7bb7a24b22 | |||
795786f46b | |||
26aa68ee59 | |||
85c0e72bf1 | |||
bf98da0061 | |||
76434b6970 | |||
0698d4be24 | |||
afb9d273ab | |||
0003d79324 | |||
e9bfc6cebd | |||
aeed9ffd5b | |||
9c27b8e864 | |||
af34d395fc | |||
008b659a10 | |||
1ce2839df9 | |||
022d15c2c7 | |||
908a2ca6c3 | |||
614eebfdc0 | |||
42fb79b025 | |||
4265ea9b99 | |||
a7d376778e | |||
157af52112 | |||
c7838486d3 | |||
1ac5b56f34 | |||
5924d092f4 | |||
63cbcb0896 | |||
7cff078698 | |||
a5f6aae6f5 | |||
fd94422982 | |||
55a7119e3f | |||
d258d4ddd5 | |||
c39aab34e0 | |||
9d725a0974 | |||
4a15339e0e | |||
df4ef0ce5a | |||
3bb5546aaf | |||
4de3c6d664 | |||
b5502ea401 | |||
1211023c55 | |||
b4229ecb1e | |||
348837ff4a | |||
17eaa7446a | |||
530664294a | |||
b649071d98 | |||
ea2653b7ce | |||
d97f0f7300 | |||
ee43fcdb89 | |||
4c1b1282d6 | |||
bc73a16475 | |||
adfaa7f9c1 | |||
f9a6873ee9 | |||
66f73c92bd | |||
d5e8974a4a | |||
e040a5b0c5 | |||
d2ac88d66d | |||
b534af5203 | |||
b06b75441c | |||
1f405fb2ba | |||
ffe9dcedf7 | |||
fc649de64c | |||
1210696e3a | |||
47ced34c84 | |||
ae7034d942 | |||
f3cf9e0bed | |||
3a7c9022af | |||
2a199bf373 | |||
53198128e8 | |||
bee3eea040 | |||
1e202baa8a | |||
39eb1d150a | |||
68e6666819 | |||
447e1feb9c | |||
26e3c3e5b7 | |||
38c038f4f7 | |||
3557994cbb | |||
f3106ee316 | |||
bef0099eec | |||
67434caf45 | |||
be84ab1f45 | |||
43d32641f3 | |||
9bf0dbabae | |||
8c7880774e | |||
5774aa4a8f | |||
6c6d11578e | |||
f33e960bdf | |||
14202a5bcc | |||
3d2babf2bb | |||
9d51b2ecc7 | |||
0b855efb5f | |||
2ae286ff75 | |||
a05fa53ee1 | |||
46d95805e9 | |||
9346a066d1 | |||
567531727e | |||
6c65e4b313 | |||
e6b13adb61 | |||
bd3e06982b | |||
660ba94c7c | |||
11ddce043d | |||
980fe6b33c | |||
016df3ff74 | |||
d827235d31 | |||
f7a25d1421 | |||
d148b19767 | |||
89135d08cb | |||
15a5afd2c4 | |||
e63e359417 | |||
3c1a74998e | |||
eadf85f66d | |||
536eb2154a | |||
e62365436c | |||
4b04c283b6 | |||
def5816003 | |||
6f2ae56126 | |||
a40f05260a | |||
2b539fafcd | |||
954c5c8344 | |||
2a8ecf0423 | |||
a056ca84be | |||
8d8bf00a34 | |||
f58bcb4767 | |||
4f56acc316 | |||
fdf1b20368 | |||
c12691a3a0 | |||
06bfa05ec1 | |||
32e06ce998 | |||
c0a7b831cd | |||
8c04023eba | |||
cf3cfc5249 | |||
a1625ea41d | |||
2cedd2beb4 | |||
6544b9aca4 | |||
08a9b838e5 | |||
b7dd40e558 | |||
7f2abf7e6e | |||
825812e511 | |||
69e5495cc9 | |||
b422f15b59 | |||
889b332ade | |||
46d1a49f0f | |||
1b156dcb0a | |||
efd2f14a13 | |||
d4d06d037c | |||
9525c09c41 | |||
e5876a1e5b | |||
1757ea4492 | |||
39d31c3ffd | |||
c50ef59102 | |||
5fc4ca6dad | |||
35c7527946 | |||
7e8a014f37 | |||
4ce951bbed | |||
f784550b9b | |||
1f2bbd4aec | |||
2389757581 | |||
9021ab9f05 | |||
547d71c19a | |||
79bba42768 | |||
8dd4fe06f3 | |||
19115dfb65 | |||
4c0ae75b00 | |||
34842c00fe | |||
46a513b263 | |||
6129fbf2b3 | |||
242541304e | |||
f3d2dee470 | |||
3d207ab7bb | |||
95447eb765 | |||
593268f620 | |||
5c98a51cd6 | |||
4453bde815 | |||
7843f9650a | |||
82dce71b9c | |||
8a981c3ca9 | |||
9c00c2c5cc | |||
aad645f2c5 | |||
d01e49f566 | |||
7447d4879e | |||
215864e3d4 | |||
0cbb81cfea | |||
9d7816a1cd | |||
461aa5ede0 | |||
b5874f4b49 | |||
10fc7bbb84 | |||
87e3f2a9ef | |||
5006692594 | |||
9481131daf | |||
ae418fb2d1 | |||
c174eddddf | |||
6d74c6616c | |||
7db40fbf47 | |||
152a5d4c92 | |||
e33b7d7701 | |||
01e176d902 | |||
fd771cdb2c | |||
243e8b831b | |||
9a8b4395f1 | |||
4c7cd06212 | |||
d0de6a9254 | |||
12f2798140 | |||
bd92076291 | |||
9cbe774c5a | |||
b4653b20a2 | |||
2c011df252 | |||
9d472bb290 | |||
95b21cbed9 | |||
82007c9b40 | |||
50c72de4f9 | |||
36237a3201 | |||
eb9df628e6 | |||
6e04e288ea | |||
a92960d778 | |||
ef9b0e9309 | |||
350e00e0cd | |||
e924363dfb | |||
b12f31652c | |||
b77e811ad4 | |||
a000a722ba | |||
4dde01245e | |||
f50c0a98c2 | |||
0625bfdd10 | |||
4dfee58d09 | |||
a7b8eb179b | |||
f10bb6c86c | |||
a59a7b5346 | |||
1bd715e57e | |||
b7d2020f10 | |||
317996b609 | |||
e197f6f54d | |||
135f63480b | |||
d9ffa5bb5a | |||
f59f13588f | |||
c668a895d4 | |||
9442a87311 | |||
3bd56fb565 | |||
bdc3b1ed0e | |||
40af93a7fb | |||
cd4fc97bde | |||
a36ff517e7 | |||
3642ead646 | |||
60c370df3f | |||
d80852c6c1 | |||
62b3047fff | |||
de2c3a30ff | |||
c08280589d | |||
9a9ffcbea9 | |||
733efcfaf7 | |||
b34d984572 | |||
e2b58e1b77 | |||
b7e5bc5972 | |||
831b4ad72a | |||
54cefa247a | |||
e3898449b7 | |||
e5bad6a74c | |||
254343a6af | |||
28bfd75114 | |||
b7fd5e78cc | |||
79985ff009 | |||
62f5b9276f | |||
276844af0b | |||
13c1f01a6b | |||
5f281f57de | |||
089e434e3f | |||
b068b50d7c | |||
14911868e4 | |||
539fe48947 | |||
259c3af526 | |||
6b5e0e57bc | |||
b55c903a81 | |||
4f06f0dc5e | |||
c0dde0e540 | |||
6779063578 | |||
2eea562d1f | |||
0385c09f23 | |||
bd57b95598 | |||
465da7c939 | |||
44f76e656a | |||
824046aca1 | |||
827c50ff43 | |||
0230291bb2 | |||
3d3618256d | |||
590cb2dd7f | |||
d9dcab544c | |||
4ee0f0c659 | |||
7692ab0b3e | |||
2af5bb3d78 | |||
e72a0a4300 | |||
6b0cbf684f | |||
62af314238 | |||
e8745b4312 | |||
5a10173ba3 | |||
2d8fe1d3e5 | |||
0741d87bcb | |||
2587c27f89 | |||
2d74d0725d | |||
b0d1d2e1af | |||
61dc79a2ea | |||
7804236499 | |||
f908762cf8 | |||
feb36d19ac | |||
06185ac870 | |||
a8915661a7 | |||
d57aa473ac | |||
a28b7d5616 | |||
dd58ba8b00 | |||
a21508b6ba | |||
94cff99f53 | |||
8aa8d773de | |||
0a888e205e | |||
898dc89c8f | |||
4b22fd95bf | |||
527a9e7612 | |||
3686e6e508 | |||
cda50db23b | |||
344e24fcd2 | |||
9be6960bbf | |||
a45aabfb72 | |||
602bf59843 | |||
895d7f6f20 | |||
876103ff7b | |||
46cda87d5e | |||
d728dfcd70 | |||
19fcd0318c | |||
030f6d1a99 | |||
86b495cb9f | |||
c897f4fa4b | |||
8181a0664d | |||
c37e94493f | |||
b9e107510d | |||
976ae65529 | |||
0f4c1ccfe3 | |||
9d9413c790 | |||
64c28ae657 | |||
d221625eb3 | |||
1f4c885748 | |||
0545b178af | |||
fe4b6c36c4 | |||
fce3436c88 |
|
@ -16,13 +16,12 @@ building [hosts/](./hosts/) will require [sops][sops].
|
||||||
|
|
||||||
you might specifically be interested in these files (elaborated further in #key-points-of-interest):
|
you might specifically be interested in these files (elaborated further in #key-points-of-interest):
|
||||||
- ~~[`sxmo-utils`](./pkgs/additional/sxmo-utils/default.nix)~~
|
- ~~[`sxmo-utils`](./pkgs/additional/sxmo-utils/default.nix)~~
|
||||||
- ~~[example SXMO deployment](./hosts/modules/gui/sxmo/default.nix)~~
|
|
||||||
- these files will remain until my config settles down, but i no longer use or maintain SXMO.
|
- these files will remain until my config settles down, but i no longer use or maintain SXMO.
|
||||||
- [my implementation of impermanence](./modules/persist/default.nix)
|
- [my implementation of impermanence](./modules/persist/default.nix)
|
||||||
- my way of deploying dotfiles/configuring programs per-user:
|
- my way of deploying dotfiles/configuring programs per-user:
|
||||||
- [modules/fs/](./modules/fs/default.nix)
|
- [modules/fs/](./modules/fs/default.nix)
|
||||||
- [modules/programs/](./modules/programs/default.nix)
|
- [modules/programs/](./modules/programs/default.nix)
|
||||||
- [modules/users.nix](./modules/users.nix)
|
- [modules/users/](./modules/users/default.nix)
|
||||||
|
|
||||||
[nixpkgs]: https://github.com/NixOS/nixpkgs
|
[nixpkgs]: https://github.com/NixOS/nixpkgs
|
||||||
[sops]: https://github.com/Mic92/sops-nix
|
[sops]: https://github.com/Mic92/sops-nix
|
||||||
|
@ -109,9 +108,10 @@ i.e. you might find value in using these in your own config:
|
||||||
- `sane.programs.firefox.sandbox.whitelistWayland = true; # allow it to render a wayland window`
|
- `sane.programs.firefox.sandbox.whitelistWayland = true; # allow it to render a wayland window`
|
||||||
- `sane.programs.firefox.sandbox.extraHomePaths = [ "Downloads" ]; # allow it read/write access to ~/Downloads`
|
- `sane.programs.firefox.sandbox.extraHomePaths = [ "Downloads" ]; # allow it read/write access to ~/Downloads`
|
||||||
- integrated with `fs` and `persist` modules so that programs' config files and persisted data stores are linked into the sandbox w/o any extra involvement.
|
- integrated with `fs` and `persist` modules so that programs' config files and persisted data stores are linked into the sandbox w/o any extra involvement.
|
||||||
- `modules/users.nix`
|
- `modules/users/`
|
||||||
- convenience layer atop the above modules so that you can just write
|
- convenience layer atop the above modules so that you can just write
|
||||||
`fs.".config/git"` instead of `fs."/home/colin/.config/git"`
|
`fs.".config/git"` instead of `fs."/home/colin/.config/git"`
|
||||||
|
- per-user services managed by [s6-rc](https://www.skarnet.org/software/s6-rc/)
|
||||||
|
|
||||||
some things in here could easily find broader use. if you would find benefit in
|
some things in here could easily find broader use. if you would find benefit in
|
||||||
them being factored out of my config, message me and we could work to make that happen.
|
them being factored out of my config, message me and we could work to make that happen.
|
||||||
|
|
54
TODO.md
54
TODO.md
|
@ -1,10 +1,33 @@
|
||||||
## BUGS
|
## BUGS
|
||||||
|
- `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.
|
||||||
|
- `rmDbusServicesInPlace` is not affected
|
||||||
|
- moby: touchscreen input is still enabled when screen is off
|
||||||
|
- when moby wlan is explicitly set down (via ip link set wlan0 down), /var/lib/trust-dns/dhcp-configs doesn't get reset
|
||||||
|
- `ip monitor` can detect those manual link state changes (NM-dispatcher it seems cannot)
|
||||||
|
- or try dnsmasq?
|
||||||
|
- trust-dns: can't recursively resolve api.mangadex.org
|
||||||
|
- and *sometimes* apple.com fails
|
||||||
|
- sandbox: link cache means that if i update ~/.config/... files inline, sandboxed programs still see the old version
|
||||||
|
- 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
|
||||||
|
- Signal restart loop drains battery
|
||||||
|
- decrease s6 restart time?
|
||||||
|
- `ssh` access doesn't grant same linux capabilities as login
|
||||||
- ringer (i.e. dino incoming call) doesn't prevent moby from sleeping
|
- ringer (i.e. dino incoming call) doesn't prevent moby from sleeping
|
||||||
- sway mouse/kb hotplug doesn't work
|
- sysvol (volume overlay): when casting with `blast`, sysvol doesn't react to volume changes
|
||||||
- `nix` operations from lappy hang when `desko` is unreachable
|
- moby: kaslr is effectively disabled
|
||||||
- could at least direct the cache to `http://desko-hn:5001`
|
- `dmesg | grep "KASLR disabled due to lack of seed"`
|
||||||
|
- fix by adding `kaslrseed` to uboot script before `booti`
|
||||||
|
- <https://github.com/armbian/build/pull/4352>
|
||||||
|
- not sure how that's supposed to work with tow-boot; maybe i should just update tow-boot
|
||||||
|
- moby: bpf is effectively disabled?
|
||||||
|
- `dmesg | grep 'systemd[1]: bpf-lsm: Failed to load BPF object: No such process'`
|
||||||
|
- `dmesg | grep 'hid_bpf: error while preloading HID BPF dispatcher: -22'`
|
||||||
|
|
||||||
## REFACTORING:
|
## REFACTORING:
|
||||||
|
- 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
|
||||||
|
@ -21,13 +44,19 @@
|
||||||
|
|
||||||
### upstreaming
|
### upstreaming
|
||||||
- add updateScripts to all my packages in nixpkgs
|
- add updateScripts to all my packages in nixpkgs
|
||||||
- REVIEW/integrate jellyfin dataDir config: <https://github.com/NixOS/nixpkgs/pull/233617>
|
|
||||||
|
|
||||||
#### upstreaming to non-nixpkgs repos
|
#### upstreaming to non-nixpkgs repos
|
||||||
- gtk: build schemas even on cross compilation: <https://github.com/NixOS/nixpkgs/pull/247844>
|
- gtk: build schemas even on cross compilation: <https://github.com/NixOS/nixpkgs/pull/247844>
|
||||||
|
|
||||||
|
|
||||||
## 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
|
||||||
|
- 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
|
||||||
|
- mpv: add media looping controls (e.g. loop song, loop playlist)
|
||||||
|
|
||||||
### security/resilience
|
### security/resilience
|
||||||
- validate duplicity backups!
|
- validate duplicity backups!
|
||||||
- encrypt more ~ dirs (~/archives, ~/records, ..?)
|
- encrypt more ~ dirs (~/archives, ~/records, ..?)
|
||||||
|
@ -45,17 +74,19 @@
|
||||||
- <https://github.com/flatpak/xdg-dbus-proxy>
|
- <https://github.com/flatpak/xdg-dbus-proxy>
|
||||||
- remove `.ssh` access from Firefox!
|
- 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
|
- limit access to `~/knowledge/secrets` through an agent that requires GUI approval, so a firefox exploit can't steal all my logins
|
||||||
- port sane-sandboxed 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.
|
||||||
- remove /run/wrappers from the sandbox path
|
|
||||||
- they're mostly useless when using no-new-privs, just an opportunity to forget to specify deps
|
|
||||||
- make dconf stuff less monolithic
|
- make dconf stuff less monolithic
|
||||||
- i.e. per-app dconf profiles for those which need it. possible static config.
|
- i.e. per-app dconf profiles for those which need it. possible static config.
|
||||||
- canaries for important services
|
- canaries for important services
|
||||||
- e.g. daily email checks; daily backup checks
|
- e.g. daily email checks; daily backup checks
|
||||||
- integrate `nix check` into Gitea actions?
|
- integrate `nix check` into Gitea actions?
|
||||||
|
|
||||||
|
#### sudo-free world
|
||||||
|
- `systemctl restart FOO`: needs `sudo`
|
||||||
|
|
||||||
### user experience
|
### user experience
|
||||||
|
- rofi: sort items case-insensitively
|
||||||
- xdg-desktop-portal shouldn't kill children on exit
|
- xdg-desktop-portal shouldn't kill children on exit
|
||||||
- *maybe* a job for `setsid -f`?
|
- *maybe* a job for `setsid -f`?
|
||||||
- replace starship prompt with something more efficient
|
- replace starship prompt with something more efficient
|
||||||
|
@ -68,7 +99,7 @@
|
||||||
- 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)? Gnome Maps is improved in 45)
|
- 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/>
|
||||||
- OSK overlay specifically for mobile gaming
|
- OSK overlay specifically for mobile gaming
|
||||||
- i.e. mock joysticks, for use with SuperTux and SuperTuxKart
|
- i.e. mock joysticks, for use with SuperTux and SuperTuxKart
|
||||||
|
@ -80,6 +111,8 @@
|
||||||
- numberlink (generic name for Flow Free). not packaged in Nix
|
- numberlink (generic name for Flow Free). not packaged in Nix
|
||||||
- Neverball (https://neverball.org/screenshots.php). nix: as `neverball`
|
- Neverball (https://neverball.org/screenshots.php). nix: as `neverball`
|
||||||
- blurble (https://linuxphoneapps.org/games/app.drey.blurble/). nix: not as of 2024-02-05
|
- blurble (https://linuxphoneapps.org/games/app.drey.blurble/). nix: not as of 2024-02-05
|
||||||
|
- Trivia Quiz (https://linuxphoneapps.org/games/io.github.nokse22.trivia-quiz/)
|
||||||
|
- sane-sync-music: remove empty dirs
|
||||||
|
|
||||||
#### 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>
|
||||||
|
@ -95,6 +128,7 @@
|
||||||
- direct mepo to prefer gpsd, with fallback to geoclue, for better accuracy?
|
- direct mepo to prefer gpsd, with fallback to geoclue, for better accuracy?
|
||||||
- configure geoclue to do some smoothing?
|
- configure geoclue to do some smoothing?
|
||||||
- manually do smoothing, as some layer between mepo and geoclue/gpsd?
|
- manually do smoothing, as some layer between mepo and geoclue/gpsd?
|
||||||
|
- moby: port `freshen-agps` timer service to s6 (maybe i want some `s6-cron` or something)
|
||||||
- moby: show battery state on ssh login
|
- 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)
|
||||||
|
@ -123,6 +157,10 @@
|
||||||
|
|
||||||
### perf
|
### perf
|
||||||
- debug nixos-rebuild times
|
- debug nixos-rebuild times
|
||||||
|
- use `systemctl list-jobs` to show what's being waited on
|
||||||
|
- i think it's `systemd-networkd-wait-online.service` that's blocking this?
|
||||||
|
- i wonder what interface it's waiting for. i should use `--ignore=...` to ignore interfaces i don't care about.
|
||||||
|
- also `wireguard-wg-home.target` when net is offline
|
||||||
- add `pkgs.impure-cached.<foo>` package set to build things with ccache enabled
|
- add `pkgs.impure-cached.<foo>` package set to build things with ccache enabled
|
||||||
- every package here can be auto-generated, and marked with some env var so that it doesn't pollute the pure package set
|
- every package here can be auto-generated, and marked with some env var so that it doesn't pollute the pure package set
|
||||||
- would be super handy for package prototyping!
|
- would be super handy for package prototyping!
|
||||||
|
|
80
flake.lock
80
flake.lock
|
@ -24,11 +24,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1701473968,
|
"lastModified": 1712014858,
|
||||||
"narHash": "sha256-YcVE5emp1qQ8ieHUnxt1wCZCC3ZfAS+SRRWZ2TMda7E=",
|
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
|
||||||
"owner": "hercules-ci",
|
"owner": "hercules-ci",
|
||||||
"repo": "flake-parts",
|
"repo": "flake-parts",
|
||||||
"rev": "34fed993f1674c8d06d58b37ce1e0fe5eebcb9f5",
|
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -61,11 +61,11 @@
|
||||||
"nixpkgs-lib": "nixpkgs-lib"
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1711886936,
|
"lastModified": 1716725378,
|
||||||
"narHash": "sha256-D2WENp9GuaCostvNcQ7vElekk0V5cuMdnFZ7NfRhVrQ=",
|
"narHash": "sha256-bNTVDAVBLFSSTU+q54cJnntmFKBi+F/D8sSqlZwBGiM=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "lib-aggregate",
|
"repo": "lib-aggregate",
|
||||||
"rev": "9c06929b83e57c18d125f1105ba6a423f24083d2",
|
"rev": "dbc9130fe1455e0f6ee4d8f5f799f9be551f866b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -99,11 +99,11 @@
|
||||||
"treefmt-nix": "treefmt-nix"
|
"treefmt-nix": "treefmt-nix"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1705242886,
|
"lastModified": 1715804156,
|
||||||
"narHash": "sha256-TLj334vRwFtSym3m+NnKcNCnKKPNoTC/TDZL40vmOso=",
|
"narHash": "sha256-GtIHP86Cz1kD9xZO/cKbNQACHKdoT9WFbLJAq6W2EDY=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nix-eval-jobs",
|
"repo": "nix-eval-jobs",
|
||||||
"rev": "6b03a93296faf174b97546fd573c8b379f523a8d",
|
"rev": "bb95091f6c6f38f6cfc215a1797a2dd466312c8b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -121,11 +121,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1701208414,
|
"lastModified": 1703863825,
|
||||||
"narHash": "sha256-xrQ0FyhwTZK6BwKhahIkUVZhMNk21IEI1nUcWSONtpo=",
|
"narHash": "sha256-rXwqjtwiGKJheXB43ybM8NwWB8rO2dSRrEqes0S7F5Y=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nix-github-actions",
|
"repo": "nix-github-actions",
|
||||||
"rev": "93e39cc1a087d65bcf7a132e75a650c44dd2b734",
|
"rev": "5163432afc817cf8bd1f031418d1869e4c9d5547",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -136,11 +136,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1703134684,
|
"lastModified": 1715037484,
|
||||||
"narHash": "sha256-SQmng1EnBFLzS7WSRyPM9HgmZP2kLJcPAz+Ug/nug6o=",
|
"narHash": "sha256-OUt8xQFmBU96Hmm4T9tOWTu4oCswCzoVl+pxSq/kiFc=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "d6863cbcbbb80e71cecfc03356db1cda38919523",
|
"rev": "ad7efee13e0d216bf29992311536fce1d3eefbef",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -152,11 +152,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs-lib": {
|
"nixpkgs-lib": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1711846064,
|
"lastModified": 1716684580,
|
||||||
"narHash": "sha256-cqfX0QJNEnge3a77VnytM0Q6QZZ0DziFXt6tSCV8ZSc=",
|
"narHash": "sha256-sIbMJWJr4hl2PWd9/iWlh89QfVzBn1NJ3u5RjeZADuM=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nixpkgs.lib",
|
"repo": "nixpkgs.lib",
|
||||||
"rev": "90b1a963ff84dc532db92f678296ff2499a60a87",
|
"rev": "d0d27192931680482081aa1c38389da2af84a651",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -167,11 +167,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs-next-unpatched": {
|
"nixpkgs-next-unpatched": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712383280,
|
"lastModified": 1717243271,
|
||||||
"narHash": "sha256-YL8miM11o/jMqOwt5DsdyhPgh/JgCl1kOIzvX7ukniY=",
|
"narHash": "sha256-M3VxP6DtREz5Lq6MKg1gQ2EeVdIbq6AEp/N1tDSrvoc=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "7c74352f2f7eca1925729f5c9c80cb89df8e74a2",
|
"rev": "f7de25c01e4c073c06e0525226a0c2311d530cee",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -183,11 +183,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs-stable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1711819797,
|
"lastModified": 1716655032,
|
||||||
"narHash": "sha256-tNeB6emxj74Y6ctwmsjtMlzUMn458sBmwnD35U5KIM4=",
|
"narHash": "sha256-kQ25DAiCGigsNR/Quxm3v+JGXAEXZ8I7RAF4U94bGzE=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "2b4e3ca0091049c6fbb4908c66b05b77eaef9f0c",
|
"rev": "59a450646ec8ee0397f5fa54a08573e8240eb91f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -199,11 +199,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs-unpatched": {
|
"nixpkgs-unpatched": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712398506,
|
"lastModified": 1717242134,
|
||||||
"narHash": "sha256-oopwPeBKBXQEw2BlyK2jEs2farZ5uMjAZU7H4FpGuGE=",
|
"narHash": "sha256-2X835ZESUaQ/KZEuG9HkoEB7h0USG5uvkSUmLzFkxAE=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "c58702222e0a29fd01cc42d70737d699995f6389",
|
"rev": "61c1d282153dbfcb5fe413c228d172d0fe7c2a7e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -223,11 +223,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712237761,
|
"lastModified": 1717175759,
|
||||||
"narHash": "sha256-NoMBBCADTms3yx5BL+sbc7vfDivNiYULO6t9GBAsPt0=",
|
"narHash": "sha256-KiM5ue/UNQt8ktoqCV4yFqhHxM31U94Mf/piKW9dZ4c=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nixpkgs-wayland",
|
"repo": "nixpkgs-wayland",
|
||||||
"rev": "9b77653338f52da4b498abdf4835efb6ff6e453e",
|
"rev": "93b225ddba91179248b378913a91defbc6aeb899",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -254,11 +254,11 @@
|
||||||
"nixpkgs-stable": "nixpkgs-stable"
|
"nixpkgs-stable": "nixpkgs-stable"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1711855048,
|
"lastModified": 1716692524,
|
||||||
"narHash": "sha256-HxegAPnQJSC4cbEbF4Iq3YTlFHZKLiNTk8147EbLdGg=",
|
"narHash": "sha256-sALodaA7Zkp/JD6ehgwc0UCBrSBfB4cX66uFGTsqeFU=",
|
||||||
"owner": "Mic92",
|
"owner": "Mic92",
|
||||||
"repo": "sops-nix",
|
"repo": "sops-nix",
|
||||||
"rev": "99b1e37f9fc0960d064a7862eb7adfb92e64fa10",
|
"rev": "962797a8d7f15ed7033031731d0bb77244839960",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -291,11 +291,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1702979157,
|
"lastModified": 1711963903,
|
||||||
"narHash": "sha256-RnFBbLbpqtn4AoJGXKevQMCGhra4h6G2MPcuTSZZQ+g=",
|
"narHash": "sha256-N3QDhoaX+paWXHbEXZapqd1r95mdshxToGowtjtYkGI=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "treefmt-nix",
|
"repo": "treefmt-nix",
|
||||||
"rev": "2961375283668d867e64129c22af532de8e77734",
|
"rev": "49dc4a92b02b8e68798abd99184f228243b6e3ac",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -311,11 +311,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1711371733,
|
"lastModified": 1715894399,
|
||||||
"narHash": "sha256-+brjlMyLVnVADY31sN82Ap0IsPE2WZEwHUd94sY6BXI=",
|
"narHash": "sha256-h1EdA/h74zgNPNEYbH+0mgOMlJgLVcxuZ8/ewsZlgEc=",
|
||||||
"ref": "refs/heads/master",
|
"ref": "refs/heads/master",
|
||||||
"rev": "b9502e6f190752d327f8cee7fa4b139094bd7c16",
|
"rev": "e6f88f563bdd1700c04018951de4f69862646dd1",
|
||||||
"revCount": 237,
|
"revCount": 240,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.uninsane.org/colin/uninsane"
|
"url": "https://git.uninsane.org/colin/uninsane"
|
||||||
},
|
},
|
||||||
|
|
43
flake.nix
43
flake.nix
|
@ -108,20 +108,22 @@
|
||||||
nixpkgs' = patchNixpkgs "master" nixpkgs-unpatched;
|
nixpkgs' = patchNixpkgs "master" nixpkgs-unpatched;
|
||||||
nixpkgsCompiledBy = system: nixpkgs'.legacyPackages."${system}";
|
nixpkgsCompiledBy = system: nixpkgs'.legacyPackages."${system}";
|
||||||
|
|
||||||
evalHost = { name, local, target, light ? false, nixpkgs ? nixpkgs' }: nixpkgs.lib.nixosSystem {
|
evalHost = { name, local, target, variant ? null, nixpkgs ? nixpkgs' }: nixpkgs.lib.nixosSystem {
|
||||||
system = target;
|
system = target;
|
||||||
modules = [
|
modules = [
|
||||||
{
|
{
|
||||||
nixpkgs.buildPlatform.system = local;
|
nixpkgs.buildPlatform.system = local;
|
||||||
# nixpkgs.config.replaceStdenv = { pkgs }: pkgs.ccacheStdenv;
|
|
||||||
}
|
}
|
||||||
(optionalAttrs (local != target) {
|
(optionalAttrs (local != target) {
|
||||||
# XXX(2023/12/11): cache.nixos.org uses `system = ...` instead of `hostPlatform.system`, and that choice impacts the closure of every package.
|
# XXX(2023/12/11): cache.nixos.org uses `system = ...` instead of `hostPlatform.system`, and that choice impacts the closure of every package.
|
||||||
# so avoid specifying hostPlatform.system on non-cross builds, so i can use upstream caches.
|
# so avoid specifying hostPlatform.system on non-cross builds, so i can use upstream caches.
|
||||||
nixpkgs.hostPlatform.system = target;
|
nixpkgs.hostPlatform.system = target;
|
||||||
})
|
})
|
||||||
(optionalAttrs light {
|
(optionalAttrs (variant == "light") {
|
||||||
sane.enableSlowPrograms = false;
|
sane.maxBuildCost = 2;
|
||||||
|
})
|
||||||
|
(optionalAttrs (variant == "min") {
|
||||||
|
sane.maxBuildCost = 0;
|
||||||
})
|
})
|
||||||
(import ./hosts/instantiate.nix { hostName = name; })
|
(import ./hosts/instantiate.nix { hostName = name; })
|
||||||
self.nixosModules.default
|
self.nixosModules.default
|
||||||
|
@ -139,11 +141,13 @@
|
||||||
hosts = {
|
hosts = {
|
||||||
servo = { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
servo = { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||||
desko = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
desko = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||||
desko-light = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; light = true; };
|
desko-light = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; variant = "light"; };
|
||||||
lappy = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
lappy = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||||
lappy-light = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; light = true; };
|
lappy-light = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; variant = "light"; };
|
||||||
|
lappy-min = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; variant = "min"; };
|
||||||
moby = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
|
moby = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
|
||||||
moby-light = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; light = true; };
|
moby-light = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; variant = "light"; };
|
||||||
|
moby-min = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; variant = "min"; };
|
||||||
rescue = { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
rescue = { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||||
};
|
};
|
||||||
hostsNext = mapAttrs' (h: v: {
|
hostsNext = mapAttrs' (h: v: {
|
||||||
|
@ -285,7 +289,7 @@
|
||||||
# - sandbox friendliness (especially: `git` doesn't have to be run as root)
|
# - sandbox friendliness (especially: `git` doesn't have to be run as root)
|
||||||
|
|
||||||
if [ -n "$addr" ]; then
|
if [ -n "$addr" ]; then
|
||||||
sudo nix store sign -r -k /run/secrets/nix_serve_privkey "$storePath"
|
sudo nix store sign -r -k /run/secrets/nix_signing_key "$storePath"
|
||||||
# add more `-v` for more verbosity (up to 5).
|
# add more `-v` for more verbosity (up to 5).
|
||||||
# builders-use-substitutes false: optimizes so that the remote machine doesn't try to get paths from its substituters.
|
# builders-use-substitutes false: optimizes so that the remote machine doesn't try to get paths from its substituters.
|
||||||
# we already have all paths here, and the remote substitution is slow to check and SERIOUSLY flaky on moby in particular.
|
# we already have all paths here, and the remote substitution is slow to check and SERIOUSLY flaky on moby in particular.
|
||||||
|
@ -313,11 +317,8 @@
|
||||||
commandArgv = pkg.updateScript.command or pkg.updateScript;
|
commandArgv = pkg.updateScript.command or pkg.updateScript;
|
||||||
command = pkgs.lib.escapeShellArgs commandArgv;
|
command = pkgs.lib.escapeShellArgs commandArgv;
|
||||||
in builtins.toString (pkgs.writeShellScript "update-${strAttrPath}" ''
|
in builtins.toString (pkgs.writeShellScript "update-${strAttrPath}" ''
|
||||||
export UPDATE_NIX_NAME=${pkg.name}
|
set -x
|
||||||
export UPDATE_NIX_PNAME=${pkg.pname}
|
env UPDATE_NIX_NAME=${pkg.name} UPDATE_NIX_PNAME=${pkg.pname} UPDATE_NIX_OLD_VERSION=${pkg.version} UPDATE_NIX_ATTR_PATH=${strAttrPath} ${command}
|
||||||
export UPDATE_NIX_OLD_VERSION=${pkg.version}
|
|
||||||
export UPDATE_NIX_ATTR_PATH=${strAttrPath}
|
|
||||||
${command}
|
|
||||||
'');
|
'');
|
||||||
};
|
};
|
||||||
mkUpdatersNoAliases = opts: basePath: pkgs.lib.concatMapAttrs
|
mkUpdatersNoAliases = opts: basePath: pkgs.lib.concatMapAttrs
|
||||||
|
@ -408,14 +409,17 @@
|
||||||
desko-light = deployApp "desko-light" "desko" "switch";
|
desko-light = deployApp "desko-light" "desko" "switch";
|
||||||
lappy = deployApp "lappy" "lappy" "switch";
|
lappy = deployApp "lappy" "lappy" "switch";
|
||||||
lappy-light = deployApp "lappy-light" "lappy" "switch";
|
lappy-light = deployApp "lappy-light" "lappy" "switch";
|
||||||
|
lappy-min = deployApp "lappy-min" "lappy" "switch";
|
||||||
moby = deployApp "moby" "moby" "switch";
|
moby = deployApp "moby" "moby" "switch";
|
||||||
moby-light = deployApp "moby-light" "moby" "switch";
|
moby-light = deployApp "moby-light" "moby" "switch";
|
||||||
|
moby-min = deployApp "moby-min" "moby" "switch";
|
||||||
moby-test = deployApp "moby" "moby" "test";
|
moby-test = deployApp "moby" "moby" "test";
|
||||||
servo = deployApp "servo" "servo" "switch";
|
servo = deployApp "servo" "servo" "switch";
|
||||||
|
|
||||||
# like `nixos-rebuild --flake . switch`
|
# like `nixos-rebuild --flake . switch`
|
||||||
self = deployApp "$(hostname)" "" "switch";
|
self = deployApp "$(hostname)" "" "switch";
|
||||||
self-light = deployApp "$(hostname)-light" "" "switch";
|
self-light = deployApp "$(hostname)-light" "" "switch";
|
||||||
|
self-min = deployApp "$(hostname)-min" "" "switch";
|
||||||
|
|
||||||
type = "app";
|
type = "app";
|
||||||
program = builtins.toString (pkgs.writeShellScript "deploy-all" ''
|
program = builtins.toString (pkgs.writeShellScript "deploy-all" ''
|
||||||
|
@ -431,12 +435,16 @@
|
||||||
desko-light = deployApp "desko-light" "desko" null;
|
desko-light = deployApp "desko-light" "desko" null;
|
||||||
lappy = deployApp "lappy" "lappy" null;
|
lappy = deployApp "lappy" "lappy" null;
|
||||||
lappy-light = deployApp "lappy-light" "lappy" null;
|
lappy-light = deployApp "lappy-light" "lappy" null;
|
||||||
|
lappy-min = deployApp "lappy-min" "lappy" null;
|
||||||
moby = deployApp "moby" "moby" null;
|
moby = deployApp "moby" "moby" null;
|
||||||
moby-light = deployApp "moby-light" "moby" null;
|
moby-light = deployApp "moby-light" "moby" null;
|
||||||
|
moby-min = deployApp "moby-min" "moby" null;
|
||||||
servo = deployApp "servo" "servo" null;
|
servo = deployApp "servo" "servo" null;
|
||||||
type = "app";
|
type = "app";
|
||||||
program = builtins.toString (pkgs.writeShellScript "predeploy-all" ''
|
program = builtins.toString (pkgs.writeShellScript "predeploy-all" ''
|
||||||
# copy the -light variants first; this might be run while waiting on a full build. or the full build failed.
|
# copy the -min/-light variants first; this might be run while waiting on a full build. or the full build failed.
|
||||||
|
nix run '.#preDeploy.moby-min' -- "$@"
|
||||||
|
nix run '.#preDeploy.lappy-min' -- "$@"
|
||||||
nix run '.#preDeploy.moby-light' -- "$@"
|
nix run '.#preDeploy.moby-light' -- "$@"
|
||||||
nix run '.#preDeploy.lappy-light' -- "$@"
|
nix run '.#preDeploy.lappy-light' -- "$@"
|
||||||
nix run '.#preDeploy.desko-light' -- "$@"
|
nix run '.#preDeploy.desko-light' -- "$@"
|
||||||
|
@ -541,6 +549,9 @@
|
||||||
''
|
''
|
||||||
# build minimally-usable hosts first, then their full image.
|
# build minimally-usable hosts first, then their full image.
|
||||||
# this gives me a minimal image i can deploy or copy over, early.
|
# this gives me a minimal image i can deploy or copy over, early.
|
||||||
|
${checkHost "lappy-min"}
|
||||||
|
${checkHost "moby-min"}
|
||||||
|
|
||||||
${checkHost "desko-light"}
|
${checkHost "desko-light"}
|
||||||
${checkHost "moby-light"}
|
${checkHost "moby-light"}
|
||||||
${checkHost "lappy-light"}
|
${checkHost "lappy-light"}
|
||||||
|
|
|
@ -1,39 +1,37 @@
|
||||||
{ config, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./fs.nix
|
./fs.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
sane.services.trust-dns.asSystemResolver = false; # TEMPORARY: TODO: re-enable trust-dns
|
||||||
|
# sane.programs.devPkgs.enableFor.user.colin = true;
|
||||||
# sane.guest.enable = true;
|
# sane.guest.enable = true;
|
||||||
|
|
||||||
# services.distccd.enable = true;
|
# don't enable wifi by default: it messes with connectivity.
|
||||||
# sane.programs.distcc.enableFor.user.guest = true;
|
# systemd.services.iwd.enable = false;
|
||||||
|
# systemd.services.wpa_supplicant.enable = false;
|
||||||
# TODO: remove emulation, but need to fix nixos-rebuild to moby for that.
|
sane.programs.wpa_supplicant.enableFor.user.colin = lib.mkForce false;
|
||||||
# sane.roles.build-machine.emulation = true;
|
sane.programs.wpa_supplicant.enableFor.system = lib.mkForce false;
|
||||||
|
|
||||||
sops.secrets.colin-passwd.neededForUsers = true;
|
sops.secrets.colin-passwd.neededForUsers = true;
|
||||||
|
|
||||||
sane.ports.openFirewall = true; # for e.g. nix-serve
|
|
||||||
|
|
||||||
sane.roles.build-machine.enable = true;
|
sane.roles.build-machine.enable = true;
|
||||||
sane.roles.client = true;
|
sane.roles.client = true;
|
||||||
sane.roles.dev-machine = true;
|
sane.roles.dev-machine = true;
|
||||||
sane.roles.pc = true;
|
sane.roles.pc = true;
|
||||||
sane.services.wg-home.enable = true;
|
sane.services.wg-home.enable = true;
|
||||||
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.addrV6 = "fd00:0000:1337:cafe:1111:1111:20c1:a73c";
|
||||||
sane.services.duplicity.enable = true;
|
sane.services.duplicity.enable = true;
|
||||||
sane.services.nixserve.secretKeyFile = config.sops.secrets.nix_serve_privkey.path;
|
|
||||||
|
|
||||||
sane.nixcache.substituters.desko = false;
|
|
||||||
sane.nixcache.remote-builders.desko = false;
|
sane.nixcache.remote-builders.desko = false;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
# sane.programs.devPkgs.enableFor.user.colin = true;
|
|
||||||
|
|
||||||
sane.programs."gnome.geary".config.autostart = true;
|
sane.programs."gnome.geary".config.autostart = true;
|
||||||
sane.programs.signal-desktop.config.autostart = true;
|
sane.programs.signal-desktop.config.autostart = true;
|
||||||
|
|
||||||
|
@ -43,10 +41,6 @@
|
||||||
# needed to use libimobiledevice/ifuse, for iphone sync
|
# needed to use libimobiledevice/ifuse, for iphone sync
|
||||||
services.usbmuxd.enable = true;
|
services.usbmuxd.enable = true;
|
||||||
|
|
||||||
# don't enable wifi by default: it messes with connectivity.
|
|
||||||
systemd.services.iwd.enable = false;
|
|
||||||
systemd.services.wpa_supplicant.enable = false;
|
|
||||||
|
|
||||||
# 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
|
||||||
|
|
|
@ -9,15 +9,18 @@
|
||||||
sane.roles.pc = true;
|
sane.roles.pc = true;
|
||||||
sane.services.wg-home.enable = true;
|
sane.services.wg-home.enable = true;
|
||||||
sane.services.wg-home.ip = config.sane.hosts.by-name."lappy".wg-home.ip;
|
sane.services.wg-home.ip = config.sane.hosts.by-name."lappy".wg-home.ip;
|
||||||
|
sane.ovpn.addrV4 = "172.23.119.72";
|
||||||
|
# sane.ovpn.addrV6 = "fd00:0000:1337:cafe:1111:1111:0332:aa96/128";
|
||||||
|
|
||||||
# sane.guest.enable = true;
|
# sane.guest.enable = true;
|
||||||
boot.loader.efi.canTouchEfiVariables = false;
|
boot.loader.efi.canTouchEfiVariables = false;
|
||||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||||
|
|
||||||
|
sane.programs.stepmania.enableFor.user.colin = true;
|
||||||
sane.programs.sway.enableFor.user.colin = true;
|
sane.programs.sway.enableFor.user.colin = true;
|
||||||
|
|
||||||
sane.programs."gnome.geary".config.autostart = true;
|
sane.programs."gnome.geary".config.autostart = true;
|
||||||
sane.programs.signal-desktop.config.autostart = true;
|
sane.programs.signal-desktop.config.autostart = true;
|
||||||
sane.programs.stepmania.enableFor.user.colin = true;
|
|
||||||
|
|
||||||
sops.secrets.colin-passwd.neededForUsers = true;
|
sops.secrets.colin-passwd.neededForUsers = true;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
# Pinephone
|
# Pinephone
|
||||||
# other setups to reference:
|
|
||||||
# - <https://hamblingreen.gitlab.io/2022/03/02/my-pinephone-setup.html>
|
|
||||||
# - sxmo Arch user. lots of app recommendations
|
|
||||||
#
|
#
|
||||||
# wikis, resources, ...:
|
# wikis, resources, ...:
|
||||||
# - Linux Phone Apps: <https://linuxphoneapps.org/>
|
# - Linux Phone Apps: <https://linuxphoneapps.org/>
|
||||||
|
@ -21,13 +18,11 @@
|
||||||
|
|
||||||
sane.roles.client = true;
|
sane.roles.client = true;
|
||||||
sane.roles.handheld = true;
|
sane.roles.handheld = true;
|
||||||
sane.zsh.showDeadlines = false; # unlikely to act on them when in shell
|
sane.programs.zsh.config.showDeadlines = false; # unlikely to act on them when in shell
|
||||||
sane.services.wg-home.enable = true;
|
sane.services.wg-home.enable = true;
|
||||||
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;
|
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;
|
||||||
|
sane.ovpn.addrV4 = "172.24.87.255";
|
||||||
# for some reason desko -> moby deploys are super flaky when desko is also a nixcache (not true of desko -> lappy deploys, though!)
|
# sane.ovpn.addrV6 = "fd00:0000:1337:cafe:1111:1111:18cd:a72b";
|
||||||
# > unable to download 'http://desko:5001/<hash>.narinfo': Server returned nothing (no headers, no data) (52)
|
|
||||||
sane.nixcache.substituters.desko = false;
|
|
||||||
|
|
||||||
# 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
|
||||||
|
@ -36,7 +31,6 @@
|
||||||
|
|
||||||
sops.secrets.colin-passwd.neededForUsers = true;
|
sops.secrets.colin-passwd.neededForUsers = true;
|
||||||
|
|
||||||
# sane.gui.sxmo.enable = true;
|
|
||||||
sane.programs.sway.enableFor.user.colin = true;
|
sane.programs.sway.enableFor.user.colin = true;
|
||||||
sane.programs.swaylock.enableFor.user.colin = false; #< not usable on touch
|
sane.programs.swaylock.enableFor.user.colin = false; #< not usable on touch
|
||||||
sane.programs.schlock.enableFor.user.colin = true;
|
sane.programs.schlock.enableFor.user.colin = true;
|
||||||
|
@ -62,18 +56,8 @@
|
||||||
# HACK/TODO: make `programs.P.env.VAR` behave according to `mime.priority`
|
# HACK/TODO: make `programs.P.env.VAR` behave according to `mime.priority`
|
||||||
sane.programs.firefox.env = lib.mkForce {};
|
sane.programs.firefox.env = lib.mkForce {};
|
||||||
sane.programs.epiphany.env.BROWSER = "epiphany";
|
sane.programs.epiphany.env.BROWSER = "epiphany";
|
||||||
|
sane.programs.pipewire.config = {
|
||||||
# note the .conf.d approach: using ~/.config/pipewire/pipewire.conf directly breaks all audio,
|
# tune so Dino doesn't drop audio
|
||||||
# presumably because that deletes the defaults entirely whereas the .conf.d approach selectively overrides defaults
|
|
||||||
sane.user.fs.".config/pipewire/pipewire.conf.d/10-fix-dino-mic-cutout.conf".symlink.text = ''
|
|
||||||
# config docs: <https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-PipeWire#properties>
|
|
||||||
# useful to run `pw-top` to see that these settings are actually having effect,
|
|
||||||
# and `pw-metadata` to see if any settings conflict (e.g. max-quantum < min-quantum)
|
|
||||||
#
|
|
||||||
# restart pipewire after editing these files:
|
|
||||||
# - `systemctl --user restart pipewire`
|
|
||||||
# - pipewire users will likely stop outputting audio until they are also restarted
|
|
||||||
#
|
|
||||||
# there's seemingly two buffers for the mic (see: <https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/FAQ#pipewire-buffering-explained>)
|
# there's seemingly two buffers for the mic (see: <https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/FAQ#pipewire-buffering-explained>)
|
||||||
# 1. Pipewire buffering out of the driver and into its own member.
|
# 1. Pipewire buffering out of the driver and into its own member.
|
||||||
# 2. Pipewire buffering into Dino.
|
# 2. Pipewire buffering into Dino.
|
||||||
|
@ -84,11 +68,9 @@
|
||||||
# `pw-metadata -n settings 0 clock.force-quantum 1024` reduces to about 1 error per second.
|
# `pw-metadata -n settings 0 clock.force-quantum 1024` reduces to about 1 error per second.
|
||||||
# `pw-metadata -n settings 0 clock.force-quantum 2048` reduces to 1 error every < 10s.
|
# `pw-metadata -n settings 0 clock.force-quantum 2048` reduces to 1 error every < 10s.
|
||||||
# pipewire default config includes `clock.power-of-two-quantum = true`
|
# pipewire default config includes `clock.power-of-two-quantum = true`
|
||||||
context.properties = {
|
min-quantum = 2048;
|
||||||
default.clock.min-quantum = 2048
|
max-quantum = 8192;
|
||||||
default.clock.max-quantum = 8192
|
};
|
||||||
}
|
|
||||||
'';
|
|
||||||
|
|
||||||
boot.loader.efi.canTouchEfiVariables = false;
|
boot.loader.efi.canTouchEfiVariables = false;
|
||||||
# /boot space is at a premium. default was 20.
|
# /boot space is at a premium. default was 20.
|
||||||
|
@ -126,15 +108,7 @@
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# enable rotation sensor
|
# enable rotation sensor
|
||||||
hardware.sensor.iio.enable = true;
|
# hardware.sensor.iio.enable = true;
|
||||||
|
|
||||||
# TODO: move elsewhere...
|
|
||||||
systemd.services.ModemManager.serviceConfig = {
|
|
||||||
# N.B.: the extra "" in ExecStart serves to force upstream ExecStart to be ignored
|
|
||||||
ExecStart = [ "" "${pkgs.modemmanager}/bin/ModemManager --debug" ];
|
|
||||||
# --debug sets DEBUG level logging: so reset
|
|
||||||
ExecStartPost = [ "${pkgs.modemmanager}/bin/mmcli --set-logging=INFO" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.udev.extraRules = let
|
services.udev.extraRules = let
|
||||||
chmod = "${pkgs.coreutils}/bin/chmod";
|
chmod = "${pkgs.coreutils}/bin/chmod";
|
||||||
|
|
|
@ -64,6 +64,5 @@
|
||||||
"dialout" # TODO: figure out if dialout is required. that's for /dev/ttyUSB1, but geoclue probably doesn't read that?
|
"dialout" # TODO: figure out if dialout is required. that's for /dev/ttyUSB1, but geoclue probably doesn't read that?
|
||||||
];
|
];
|
||||||
|
|
||||||
sane.services.eg25-control.enable = true;
|
|
||||||
sane.programs.where-am-i.enableFor.user.colin = true;
|
sane.programs.where-am-i.enableFor.user.colin = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,35 +40,213 @@ let
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-megous;
|
# kernel compatibility (2024/05/22: 03dab630)
|
||||||
|
# - linux-megous: boots to ssh, desktop
|
||||||
|
# - camera apps: megapixels (no cameras found), snapshot (no cameras found)
|
||||||
|
# - linux-postmarketos: boots to ssh. desktop ONLY if "anx7688" is in the initrd.availableKernelModules.
|
||||||
|
# - camera apps: megapixels (both rear and front cameras work), `cam -l` (finds only the rear camera), snapshot (no cameras found)
|
||||||
|
# - linux-megous.override { withMegiPinephoneConfig = true; }: NO SSH, NO SIGNS OF LIFE
|
||||||
|
# - linux-megous.override { withFullConfig = false; }: boots to ssh, no desktop
|
||||||
|
#
|
||||||
|
boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux-postmarketos.override {
|
||||||
|
withModemPower = true;
|
||||||
|
});
|
||||||
|
# boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-megous;
|
||||||
|
# boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux-megous.override {
|
||||||
|
# withFullConfig = false;
|
||||||
|
# });
|
||||||
|
# boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux-megous.override {
|
||||||
|
# withMegiPinephoneConfig = true; #< N.B.: does not boot as of 2024/05/22!
|
||||||
|
# });
|
||||||
# boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-manjaro;
|
# boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-manjaro;
|
||||||
# boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux_latest;
|
# boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux_latest;
|
||||||
|
|
||||||
# alternatively, apply patches directly to stock nixos kernel:
|
# nixpkgs.hostPlatform.linux-kernel becomes stdenv.hostPlatform.linux-kernel
|
||||||
# boot.kernelPatches = manjaroPatches ++ [
|
|
||||||
# (patchDefconfig kernelConfig)
|
|
||||||
# ];
|
|
||||||
|
|
||||||
# configure nixos to build a compressed kernel image, since it doesn't usually do that for aarch64 target.
|
|
||||||
# without this i run out of /boot space in < 10 generations
|
|
||||||
nixpkgs.hostPlatform.linux-kernel = {
|
nixpkgs.hostPlatform.linux-kernel = {
|
||||||
# defaults:
|
# defaults:
|
||||||
name = "aarch64-multiplatform";
|
name = "aarch64-multiplatform";
|
||||||
baseConfig = "defconfig";
|
# baseConfig: defaults to "defconfig";
|
||||||
DTB = true;
|
# baseConfig = "pinephone_defconfig"; #< N.B.: ignored by `pkgs.linux-megous`
|
||||||
autoModules = true;
|
DTB = true; #< DTB: compile device tree blobs
|
||||||
preferBuiltin = true;
|
# autoModules (default: true): for config options not manually specified, answer `m` to anything which supports it.
|
||||||
# extraConfig = ...
|
# - this effectively builds EVERY MODULE SUPPORTED.
|
||||||
# ^-- raspberry pi stuff: we don't need it.
|
autoModules = true; #< N.B.: ignored by `pkgs.linux-megous`
|
||||||
|
# preferBuiltin (default: false; true for rpi): for config options which default to `Y` upstream, build them as `Y` (overriding `autoModules`)
|
||||||
|
# preferBuiltin = false;
|
||||||
|
|
||||||
|
# build a compressed kernel image: without this i run out of /boot space in < 10 generations
|
||||||
# target = "Image"; # <-- default
|
# target = "Image"; # <-- default
|
||||||
target = "Image.gz"; # <-- compress the kernel image
|
target = "Image.gz"; # <-- compress the kernel image
|
||||||
# target = "zImage"; # <-- confuses other parts of nixos :-(
|
# target = "zImage"; # <-- confuses other parts of nixos :-(
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# boot.initrd.kernelModules = [
|
||||||
|
# "drm" #< force drm to be plugged
|
||||||
|
# ];
|
||||||
|
boot.initrd.availableKernelModules = [
|
||||||
|
# see <repo:postmarketOS/pmaports:device/main/device-pine64-pinephone/modules-initfs>
|
||||||
|
# - they include sun6i_mipi_dsi sun4i_drm pwm_sun4i sun8i_mixer anx7688 gpio_vibra pinephone_keyboard
|
||||||
|
"anx7688" #< required for display initialization and functional cameras
|
||||||
|
# full list of modules active post-boot with the linux-megous kernel + autoModules=true:
|
||||||
|
# - `lsmod | sort | cut -d ' ' -f 1`
|
||||||
|
# "8723cs"
|
||||||
|
# "axp20x_adc" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "axp20x_battery"
|
||||||
|
# "axp20x_pek"
|
||||||
|
# "axp20x_usb_power"
|
||||||
|
# "backlight"
|
||||||
|
# "blake2b_generic"
|
||||||
|
# "bluetooth"
|
||||||
|
# "bridge"
|
||||||
|
# "btbcm"
|
||||||
|
# "btqca"
|
||||||
|
# "btrfs"
|
||||||
|
# "btrtl"
|
||||||
|
# "cec"
|
||||||
|
# "cfg80211"
|
||||||
|
# "chacha_neon"
|
||||||
|
# "crc_ccitt"
|
||||||
|
# "crct10dif_ce"
|
||||||
|
# "crypto_engine"
|
||||||
|
# "display_connector" #< NOT FOUND in pmos
|
||||||
|
# "drm"
|
||||||
|
# "drm_display_helper"
|
||||||
|
# "drm_dma_helper"
|
||||||
|
# "drm_kms_helper"
|
||||||
|
# "drm_shmem_helper"
|
||||||
|
# "dw_hdmi"
|
||||||
|
# "dw_hdmi_cec" #< NOT FOUND in pmos
|
||||||
|
# "dw_hdmi_i2s_audio"
|
||||||
|
# "ecc"
|
||||||
|
# "ecdh_generic"
|
||||||
|
# "fuse"
|
||||||
|
# "gc2145" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "goodix_ts"
|
||||||
|
# "gpio_vibra" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "gpu_sched"
|
||||||
|
# "hci_uart"
|
||||||
|
# "i2c_gpio"
|
||||||
|
# "inv_mpu6050" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "inv_mpu6050_i2c" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "inv_sensors_timestamp" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "ip6t_rpfilter"
|
||||||
|
# "ip6_udp_tunnel"
|
||||||
|
# "ip_set"
|
||||||
|
# "ip_set_hash_ipport"
|
||||||
|
# "ip_tables"
|
||||||
|
# "ipt_rpfilter"
|
||||||
|
# "joydev"
|
||||||
|
# "led_class_flash" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "leds_sgm3140" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "ledtrig_pattern" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "libarc4"
|
||||||
|
# "libchacha"
|
||||||
|
# "libchacha20poly1305"
|
||||||
|
# "libcrc32c"
|
||||||
|
# "libcurve25519_generic"
|
||||||
|
# "lima"
|
||||||
|
# "llc"
|
||||||
|
# "mac80211"
|
||||||
|
# "macvlan"
|
||||||
|
# "mc"
|
||||||
|
# "modem_power"
|
||||||
|
# "mousedev"
|
||||||
|
# "nf_conntrack"
|
||||||
|
# "nf_defrag_ipv4"
|
||||||
|
# "nf_defrag_ipv6"
|
||||||
|
# "nf_log_syslog"
|
||||||
|
# "nf_nat"
|
||||||
|
# "nfnetlink"
|
||||||
|
# "nf_tables"
|
||||||
|
# "nft_chain_nat"
|
||||||
|
# "nft_compat"
|
||||||
|
# "nls_cp437"
|
||||||
|
# "nls_iso8859_1"
|
||||||
|
# "nvmem_reboot_mode"
|
||||||
|
# "ov5640"
|
||||||
|
# "panel_sitronix_st7703"
|
||||||
|
# "phy_sun6i_mipi_dphy"
|
||||||
|
# "pinctrl_axp209" #< NOT FOUND in pmos
|
||||||
|
# "pinephone_keyboard" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "poly1305_neon"
|
||||||
|
# "polyval_ce"
|
||||||
|
# "polyval_generic"
|
||||||
|
# "ppkb_manager" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "pwm_bl"
|
||||||
|
# "pwm_sun4i"
|
||||||
|
# "qrtr"
|
||||||
|
# "raid6_pq"
|
||||||
|
# "rfkill"
|
||||||
|
# "rtw88_8703b"
|
||||||
|
# "rtw88_8723cs"
|
||||||
|
# "rtw88_8723x"
|
||||||
|
# "rtw88_core"
|
||||||
|
# "rtw88_sdio"
|
||||||
|
# "sch_fq_codel"
|
||||||
|
# "sm4"
|
||||||
|
# "snd_soc_bt_sco"
|
||||||
|
# "snd_soc_ec25" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "snd_soc_hdmi_codec"
|
||||||
|
# "snd_soc_simple_amplifier"
|
||||||
|
# "snd_soc_simple_card"
|
||||||
|
# "snd_soc_simple_card_utils"
|
||||||
|
# "stk3310" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "st_magn"
|
||||||
|
# "st_magn_i2c"
|
||||||
|
# "st_magn_spi" #< NOT FOUND in pmos
|
||||||
|
# "stp"
|
||||||
|
# "st_sensors"
|
||||||
|
# "st_sensors_i2c"
|
||||||
|
# "st_sensors_spi" #< NOT FOUND in pmos
|
||||||
|
# "sun4i_drm"
|
||||||
|
# "sun4i_i2s"
|
||||||
|
# "sun4i_lradc_keys" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "sun4i_tcon"
|
||||||
|
# "sun50i_codec_analog"
|
||||||
|
# "sun6i_csi"
|
||||||
|
# "sun6i_dma"
|
||||||
|
# "sun6i_mipi_dsi"
|
||||||
|
# "sun8i_a33_mbus" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "sun8i_adda_pr_regmap"
|
||||||
|
# "sun8i_ce" #< NOT FOUND in pmos
|
||||||
|
# "sun8i_codec" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "sun8i_di" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "sun8i_drm_hdmi"
|
||||||
|
# "sun8i_mixer"
|
||||||
|
# "sun8i_rotate" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "sun8i_tcon_top"
|
||||||
|
# "sun9i_hdmi_audio" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "sunxi_wdt" #< NOT FOUND in pmos
|
||||||
|
# "tap"
|
||||||
|
# "typec" #< NOT FOUND in pmos
|
||||||
|
# "udp_tunnel"
|
||||||
|
# "uio" #< NOT FOUND in pmos
|
||||||
|
# "uio_pdrv_genirq"
|
||||||
|
# "v4l2_async"
|
||||||
|
# "v4l2_cci" #< NOT FOUND in pmos
|
||||||
|
# "v4l2_flash_led_class" #< NOT FOUND in megous-no-autoModules
|
||||||
|
# "v4l2_fwnode"
|
||||||
|
# "v4l2_mem2mem"
|
||||||
|
# "videobuf2_common"
|
||||||
|
# "videobuf2_dma_contig"
|
||||||
|
# "videobuf2_memops"
|
||||||
|
# "videobuf2_v4l2"
|
||||||
|
# "videodev"
|
||||||
|
# "wireguard"
|
||||||
|
# "xor"
|
||||||
|
# "x_tables"
|
||||||
|
# "xt_conntrack"
|
||||||
|
# "xt_LOG"
|
||||||
|
# "xt_nat"
|
||||||
|
# "xt_pkttype"
|
||||||
|
# "xt_set"
|
||||||
|
# "xt_tcpudp"
|
||||||
|
# "zram"
|
||||||
|
];
|
||||||
|
|
||||||
# disable proximity sensor.
|
# disable proximity sensor.
|
||||||
# the filtering/calibration is bad that it causes the screen to go fully dark at times.
|
# the filtering/calibration is bad that it causes the screen to go fully dark at times.
|
||||||
boot.blacklistedKernelModules = [ "stk3310" ];
|
# boot.blacklistedKernelModules = [ "stk3310" ];
|
||||||
|
|
||||||
boot.kernelParams = [
|
boot.kernelParams = [
|
||||||
# without this some GUI apps fail: `DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory`
|
# without this some GUI apps fail: `DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory`
|
||||||
|
@ -78,14 +256,16 @@ in
|
||||||
#
|
#
|
||||||
# the default CMA seems to be 32M.
|
# the default CMA seems to be 32M.
|
||||||
# i was running fine with 256MB from 2022/07-ish through 2022/12-ish, but then the phone quit reliably coming back from sleep (phosh): maybe a memory leak?
|
# i was running fine with 256MB from 2022/07-ish through 2022/12-ish, but then the phone quit reliably coming back from sleep (phosh): maybe a memory leak?
|
||||||
|
# bumped to 512M on 2023/01
|
||||||
|
# bumped to 1536M on 2024/05
|
||||||
# `cat /proc/meminfo` to see CmaTotal/CmaFree if interested in tuning this.
|
# `cat /proc/meminfo` to see CmaTotal/CmaFree if interested in tuning this.
|
||||||
"cma=512M"
|
# kernel param mentioned here: <https://cateee.net/lkddb/web-lkddb/CMA_SIZE_PERCENTAGE.html>
|
||||||
|
# i think cma mem isn't exclusive -- it can be used as ordinary `malloc`, still. i heard someone suggest the OS default should just be 50% memory to CMA.
|
||||||
|
"cma=1536M"
|
||||||
# 2023/10/20: potential fix for the lima (GPU) timeout bugs:
|
# 2023/10/20: potential fix for the lima (GPU) timeout bugs:
|
||||||
# - <https://gitlab.com/postmarketOS/pmaports/-/issues/805#note_890467824>
|
# - <https://gitlab.com/postmarketOS/pmaports/-/issues/805#note_890467824>
|
||||||
"lima.sched_timeout_ms=2000"
|
"lima.sched_timeout_ms=2000"
|
||||||
];
|
];
|
||||||
|
|
||||||
# services.xserver.displayManager.job.preStart = ensureHWReady;
|
|
||||||
# systemd.services.greetd.preStart = ensureHWReady;
|
|
||||||
systemd.services.unl0kr.preStart = ensureHWReady;
|
systemd.services.unl0kr.preStart = ensureHWReady;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,20 +15,21 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.roles.build-machine.enable = true;
|
sane.roles.build-machine.enable = true;
|
||||||
sane.zsh.showDeadlines = false; # ~/knowledge doesn't always exist
|
sane.programs.zsh.config.showDeadlines = 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.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;
|
||||||
sane.services.wg-home.routeThroughServo = false;
|
sane.services.wg-home.routeThroughServo = false;
|
||||||
sane.services.wg-home.ip = config.sane.hosts.by-name."servo".wg-home.ip;
|
sane.services.wg-home.ip = config.sane.hosts.by-name."servo".wg-home.ip;
|
||||||
sane.nixcache.substituters.servo = false;
|
sane.ovpn.addrV4 = "172.23.174.114";
|
||||||
sane.nixcache.substituters.desko = false;
|
# 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.duplicity.enable = true; # TODO: re-enable after HW upgrade
|
||||||
|
|
|
@ -38,6 +38,39 @@ in
|
||||||
# FallbackDNS=1.1.1.1 9.9.9.9
|
# FallbackDNS=1.1.1.1 9.9.9.9
|
||||||
# '';
|
# '';
|
||||||
|
|
||||||
|
# tun-sea config
|
||||||
|
sane.dns.zones."uninsane.org".inet.A."doof.tunnel" = "205.201.63.12";
|
||||||
|
sane.dns.zones."uninsane.org".inet.AAAA."doof.tunnel" = "2602:fce8:106::51";
|
||||||
|
networking.wireguard.interfaces.wg-doof = let
|
||||||
|
ip = "${pkgs.iproute2}/bin/ip";
|
||||||
|
in {
|
||||||
|
privateKeyFile = config.sops.secrets.wg_doof_privkey.path;
|
||||||
|
# wg is active only in this namespace.
|
||||||
|
# run e.g. ip netns exec doof <some command like ping/curl/etc, it'll go through wg>
|
||||||
|
# sudo ip netns exec doof ping www.google.com
|
||||||
|
interfaceNamespace = "doof";
|
||||||
|
ips = [
|
||||||
|
"205.201.63.12/32"
|
||||||
|
"2602:fce8:106::51/128"
|
||||||
|
];
|
||||||
|
peers = [
|
||||||
|
{
|
||||||
|
publicKey = "nuESyYEJ3YU0hTZZgAd7iHBz1ytWBVM5PjEL1VEoTkU=";
|
||||||
|
# TODO: configure DNS within the doof ns and use tun-sea.doof.net endpoint
|
||||||
|
# endpoint = "tun-sea.doof.net:53263";
|
||||||
|
endpoint = "205.201.63.44:53263";
|
||||||
|
allowedIPs = [ "0.0.0.0/0" "::/0" ];
|
||||||
|
persistentKeepalive = 25; #< keep the NAT alive
|
||||||
|
}
|
||||||
|
];
|
||||||
|
preSetup = ''
|
||||||
|
${ip} netns add doof || (test -e /run/netns/doof && echo "doof already exists")
|
||||||
|
'';
|
||||||
|
postShutdown = ''
|
||||||
|
${ip} netns delete doof || echo "couldn't delete doof"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
# OVPN CONFIG (https://www.ovpn.com):
|
# OVPN CONFIG (https://www.ovpn.com):
|
||||||
# DOCS: https://nixos.wiki/wiki/WireGuard
|
# DOCS: https://nixos.wiki/wiki/WireGuard
|
||||||
# if you `systemctl restart wireguard-wg-ovpns`, make sure to also restart any other services in `NetworkNamespacePath = .../ovpns`.
|
# if you `systemctl restart wireguard-wg-ovpns`, make sure to also restart any other services in `NetworkNamespacePath = .../ovpns`.
|
||||||
|
|
|
@ -24,7 +24,7 @@ lib.mkIf false
|
||||||
# services.calibre-web.options.calibreLibrary = svc-dir;
|
# services.calibre-web.options.calibreLibrary = svc-dir;
|
||||||
|
|
||||||
services.nginx.virtualHosts."calibre.uninsane.org" = {
|
services.nginx.virtualHosts."calibre.uninsane.org" = {
|
||||||
addSSL = true;
|
forceSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://${ip}:${builtins.toString port}";
|
proxyPass = "http://${ip}:${builtins.toString port}";
|
||||||
|
|
|
@ -24,50 +24,64 @@
|
||||||
# that is NOT the case when the STUN server and client A are on the same LAN
|
# that is NOT the case when the STUN server and client A are on the same LAN
|
||||||
# even if client A contacts the STUN server via its WAN address with port reflection enabled.
|
# even if client A contacts the STUN server via its WAN address with port reflection enabled.
|
||||||
# hence, there's no obvious way to put the STUN server on the same LAN as either client and expect the rest to work.
|
# hence, there's no obvious way to put the STUN server on the same LAN as either client and expect the rest to work.
|
||||||
|
# - there an old version which *half worked*, which is:
|
||||||
|
# - run the turn server in the root namespace.
|
||||||
|
# - bind the turn server to the veth connecting it to the VPN namespace (so it sends outgoing traffic to the right place).
|
||||||
|
# - NAT the turn port range from VPN into root namespace (so it receives incomming traffic).
|
||||||
|
# - this approach would fail the prosody conversations.im check, but i didn't notice *obvious* call routing errors.
|
||||||
|
#
|
||||||
|
# debugging:
|
||||||
|
# - log messages like 'usage: realm=<turn.uninsane.org>, username=<1715915193>, rp=14, rb=1516, sp=8, sb=684'
|
||||||
|
# - rp = received packets
|
||||||
|
# - rb = received bytes
|
||||||
|
# - sp = sent packets
|
||||||
|
# - sb = sent bytes
|
||||||
{ lib, ... }:
|
{ lib, ... }:
|
||||||
let
|
let
|
||||||
# TODO: this range could be larger, but right now that's costly because each element is its own UPnP forward
|
# TURN port range (inclusive).
|
||||||
# TURN port range (inclusive)
|
# default coturn behavior is to use the upper quarter of all ports. i.e. 49152 - 65535.
|
||||||
turnPortLow = 49152;
|
# i believe TURN allocations expire after either 5 or 10 minutes of inactivity.
|
||||||
turnPortHigh = 49167;
|
turnPortLow = 49152; # 49152 = 0xc000
|
||||||
|
turnPortHigh = turnPortLow + 256;
|
||||||
turnPortRange = lib.range turnPortLow turnPortHigh;
|
turnPortRange = lib.range turnPortLow turnPortHigh;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
sane.ports.ports = lib.mkMerge ([
|
# the port definitions are only needed if running in the root net namespace
|
||||||
{
|
# sane.ports.ports = lib.mkMerge ([
|
||||||
"3478" = {
|
# {
|
||||||
# this is the "control" port.
|
# "3478" = {
|
||||||
# i.e. no client data is forwarded through it, but it's where clients request tunnels.
|
# # this is the "control" port.
|
||||||
protocol = [ "tcp" "udp" ];
|
# # i.e. no client data is forwarded through it, but it's where clients request tunnels.
|
||||||
# visibleTo.lan = true;
|
# protocol = [ "tcp" "udp" ];
|
||||||
# visibleTo.wan = true;
|
# # visibleTo.lan = true;
|
||||||
visibleTo.ovpn = true;
|
# # visibleTo.wan = true;
|
||||||
description = "colin-stun-turn";
|
# visibleTo.ovpn = true; # forward traffic from the VPN to the root NS
|
||||||
};
|
# description = "colin-stun-turn";
|
||||||
"5349" = {
|
# };
|
||||||
# the other port 3478 also supports TLS/DTLS, but presumably clients wanting TLS will default 5349
|
# "5349" = {
|
||||||
protocol = [ "tcp" ];
|
# # the other port 3478 also supports TLS/DTLS, but presumably clients wanting TLS will default 5349
|
||||||
# visibleTo.lan = true;
|
# protocol = [ "tcp" ];
|
||||||
# visibleTo.wan = true;
|
# # visibleTo.lan = true;
|
||||||
visibleTo.ovpn = true;
|
# # visibleTo.wan = true;
|
||||||
description = "colin-stun-turn-over-tls";
|
# visibleTo.ovpn = true;
|
||||||
};
|
# description = "colin-stun-turn-over-tls";
|
||||||
}
|
# };
|
||||||
] ++ (builtins.map
|
# }
|
||||||
(port: {
|
# ] ++ (builtins.map
|
||||||
"${builtins.toString port}" = let
|
# (port: {
|
||||||
count = port - turnPortLow + 1;
|
# "${builtins.toString port}" = let
|
||||||
numPorts = turnPortHigh - turnPortLow + 1;
|
# count = port - turnPortLow + 1;
|
||||||
in {
|
# numPorts = turnPortHigh - turnPortLow + 1;
|
||||||
protocol = [ "tcp" "udp" ];
|
# in {
|
||||||
# visibleTo.lan = true;
|
# protocol = [ "tcp" "udp" ];
|
||||||
# visibleTo.wan = true;
|
# # visibleTo.lan = true;
|
||||||
visibleTo.ovpn = true;
|
# # visibleTo.wan = true;
|
||||||
description = "colin-turn-${builtins.toString count}-of-${builtins.toString numPorts}";
|
# visibleTo.ovpn = true;
|
||||||
};
|
# description = "colin-turn-${builtins.toString count}-of-${builtins.toString numPorts}";
|
||||||
})
|
# };
|
||||||
turnPortRange
|
# })
|
||||||
));
|
# turnPortRange
|
||||||
|
# ));
|
||||||
|
|
||||||
services.nginx.virtualHosts."turn.uninsane.org" = {
|
services.nginx.virtualHosts."turn.uninsane.org" = {
|
||||||
# allow ACME to procure a cert via nginx for this domain
|
# allow ACME to procure a cert via nginx for this domain
|
||||||
|
@ -103,22 +117,28 @@ in
|
||||||
services.coturn.realm = "turn.uninsane.org";
|
services.coturn.realm = "turn.uninsane.org";
|
||||||
services.coturn.cert = "/var/lib/acme/turn.uninsane.org/fullchain.pem";
|
services.coturn.cert = "/var/lib/acme/turn.uninsane.org/fullchain.pem";
|
||||||
services.coturn.pkey = "/var/lib/acme/turn.uninsane.org/key.pem";
|
services.coturn.pkey = "/var/lib/acme/turn.uninsane.org/key.pem";
|
||||||
|
|
||||||
|
#v disable to allow unauthenticated access (or set `services.coturn.no-auth = true`)
|
||||||
services.coturn.use-auth-secret = true;
|
services.coturn.use-auth-secret = true;
|
||||||
services.coturn.static-auth-secret-file = "/var/lib/coturn/shared_secret.bin";
|
services.coturn.static-auth-secret-file = "/var/lib/coturn/shared_secret.bin";
|
||||||
services.coturn.lt-cred-mech = true;
|
services.coturn.lt-cred-mech = true; #< XXX: use-auth-secret overrides lt-cred-mech
|
||||||
|
|
||||||
services.coturn.min-port = turnPortLow;
|
services.coturn.min-port = turnPortLow;
|
||||||
services.coturn.max-port = turnPortHigh;
|
services.coturn.max-port = turnPortHigh;
|
||||||
# services.coturn.secure-stun = true;
|
# services.coturn.secure-stun = true;
|
||||||
services.coturn.extraConfig = lib.concatStringsSep "\n" [
|
services.coturn.extraConfig = lib.concatStringsSep "\n" [
|
||||||
"verbose"
|
"verbose"
|
||||||
# "Verbose" #< even MORE verbosity than "verbose"
|
# "Verbose" #< even MORE verbosity than "verbose" (it's TOO MUCH verbosity really)
|
||||||
# "no-multicast-peers" # disables sending to IPv4 broadcast addresses (e.g. 224.0.0.0/3)
|
"no-multicast-peers" # disables sending to IPv4 broadcast addresses (e.g. 224.0.0.0/3)
|
||||||
"listening-ip=10.0.1.5"
|
# "listening-ip=10.0.1.5" "external-ip=185.157.162.178" #< 2024/04/25: works, if running in root namespace
|
||||||
|
"listening-ip=185.157.162.178" "external-ip=185.157.162.178"
|
||||||
|
|
||||||
|
# old attempts:
|
||||||
# "external-ip=185.157.162.178/10.0.1.5"
|
# "external-ip=185.157.162.178/10.0.1.5"
|
||||||
"external-ip=185.157.162.178"
|
|
||||||
# "listening-ip=10.78.79.51" # can be specified multiple times; omit for *
|
# "listening-ip=10.78.79.51" # can be specified multiple times; omit for *
|
||||||
# "external-ip=97.113.128.229/10.78.79.51"
|
# "external-ip=97.113.128.229/10.78.79.51"
|
||||||
# "external-ip=97.113.128.229"
|
# "external-ip=97.113.128.229"
|
||||||
# "mobility" # "mobility with ICE (MICE) specs support" (?)
|
# "mobility" # "mobility with ICE (MICE) specs support" (?)
|
||||||
];
|
];
|
||||||
|
systemd.services.coturn.serviceConfig.NetworkNamespacePath = "/run/netns/ovpns";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,22 @@
|
||||||
#!/usr/bin/env nix-shell
|
#!/usr/bin/env nix-shell
|
||||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.pyln-client ])"
|
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.pyln-client ])"
|
||||||
|
|
||||||
|
"""
|
||||||
|
clightning-sane: helper to perform common Lightning node admin operations:
|
||||||
|
- view channel balances
|
||||||
|
- rebalance channels
|
||||||
|
|
||||||
|
COMMON OPERATIONS:
|
||||||
|
- view channel balances: `clightning-sane status`
|
||||||
|
- rebalance channels to improve routability (without paying any fees): `clightning-sane autobalance`
|
||||||
|
|
||||||
|
FULL OPERATION:
|
||||||
|
- `clightning-sane status --full`
|
||||||
|
- `P$`: represents how many msats i've captured in fees from this channel.
|
||||||
|
- `COST`: rough measure of how much it's "costing" me to let my channel partner hold funds on his side of the channel.
|
||||||
|
this is based on the notion that i only capture fees from outbound transactions, and so the channel partner holding all liquidity means i can't capture fees on that liquidity.
|
||||||
|
"""
|
||||||
|
|
||||||
# pyln-client docs: <https://github.com/ElementsProject/lightning/tree/master/contrib/pyln-client>
|
# pyln-client docs: <https://github.com/ElementsProject/lightning/tree/master/contrib/pyln-client>
|
||||||
# terminology:
|
# terminology:
|
||||||
# - "scid": "Short Channel ID", e.g. 123456x7890x0
|
# - "scid": "Short Channel ID", e.g. 123456x7890x0
|
||||||
|
@ -726,7 +742,7 @@ def main():
|
||||||
logging.basicConfig()
|
logging.basicConfig()
|
||||||
logger.setLevel(logging.INFO)
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="rebalance lightning channel balances")
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
parser.add_argument("--verbose", action="store_true", help="more logging")
|
parser.add_argument("--verbose", action="store_true", help="more logging")
|
||||||
parser.add_argument("--min-msat", default="999", help="min transaction size")
|
parser.add_argument("--min-msat", default="999", help="min transaction size")
|
||||||
parser.add_argument("--max-msat", default="1000000", help="max transaction size")
|
parser.add_argument("--max-msat", default="1000000", help="max transaction size")
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
./navidrome.nix
|
./navidrome.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./nixos-prebuild.nix
|
./nixos-prebuild.nix
|
||||||
./nixserve.nix
|
|
||||||
./ntfy
|
./ntfy
|
||||||
./pict-rs.nix
|
./pict-rs.nix
|
||||||
./pleroma.nix
|
./pleroma.nix
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./nfs.nix
|
./nfs.nix
|
||||||
./sftpgo.nix
|
./sftpgo
|
||||||
];
|
];
|
||||||
|
|
||||||
users.groups.export = {};
|
users.groups.export = {};
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
# - could maybe be done with some mount option?
|
# - could maybe be done with some mount option?
|
||||||
|
|
||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
|
lib.mkIf false #< TODO: remove nfs altogether! it's not exactly the most secure
|
||||||
{
|
{
|
||||||
services.nfs.server.enable = true;
|
services.nfs.server.enable = true;
|
||||||
|
|
||||||
|
|
|
@ -9,24 +9,33 @@
|
||||||
|
|
||||||
{ config, lib, pkgs, sane-lib, ... }:
|
{ config, lib, pkgs, sane-lib, ... }:
|
||||||
let
|
let
|
||||||
sftpgo_external_auth_hook = pkgs.static-nix-shell.mkPython3Bin {
|
external_auth_hook = pkgs.static-nix-shell.mkPython3Bin {
|
||||||
pname = "sftpgo_external_auth_hook";
|
pname = "external_auth_hook";
|
||||||
srcRoot = ./.;
|
srcRoot = ./.;
|
||||||
|
pyPkgs = [ "passlib" ];
|
||||||
};
|
};
|
||||||
in
|
|
||||||
{
|
|
||||||
# Client initiates a FTP "control connection" on port 21.
|
# Client initiates a FTP "control connection" on port 21.
|
||||||
# - this handles the client -> server commands, and the server -> client status, but not the actual data
|
# - this handles the client -> server commands, and the server -> client status, but not the actual data
|
||||||
# - file data, directory listings, etc need to be transferred on an ephemeral "data port".
|
# - file data, directory listings, etc need to be transferred on an ephemeral "data port".
|
||||||
# - 50000-50100 is a common port range for this.
|
# - 50000-50100 is a common port range for this.
|
||||||
# 50000 is used by soulseek.
|
# 50000 is used by soulseek.
|
||||||
|
passiveStart = 50050;
|
||||||
|
passiveEnd = 50070;
|
||||||
|
in
|
||||||
|
{
|
||||||
sane.ports.ports = {
|
sane.ports.ports = {
|
||||||
"21" = {
|
"21" = {
|
||||||
protocol = [ "tcp" ];
|
protocol = [ "tcp" ];
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
visibleTo.wan = true;
|
# visibleTo.wan = true;
|
||||||
description = "colin-FTP server";
|
description = "colin-FTP server";
|
||||||
};
|
};
|
||||||
|
"990" = {
|
||||||
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.lan = true;
|
||||||
|
visibleTo.wan = true;
|
||||||
|
description = "colin-FTPS server";
|
||||||
|
};
|
||||||
} // (sane-lib.mapToAttrs
|
} // (sane-lib.mapToAttrs
|
||||||
(port: {
|
(port: {
|
||||||
name = builtins.toString port;
|
name = builtins.toString port;
|
||||||
|
@ -37,12 +46,32 @@ in
|
||||||
description = "colin-FTP server data port range";
|
description = "colin-FTP server data port range";
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
(lib.range 50050 50100)
|
(lib.range passiveStart passiveEnd)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
# use nginx/acme to produce a cert for FTPS
|
||||||
|
services.nginx.virtualHosts."ftp.uninsane.org" = {
|
||||||
|
addSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
};
|
||||||
|
sane.dns.zones."uninsane.org".inet.CNAME."ftp" = "native";
|
||||||
|
|
||||||
services.sftpgo = {
|
services.sftpgo = {
|
||||||
enable = true;
|
enable = true;
|
||||||
group = "export";
|
group = "export";
|
||||||
|
|
||||||
|
package = pkgs.sftpgo.overrideAttrs (upstream: {
|
||||||
|
patches = (upstream.patches or []) ++ [
|
||||||
|
# fix for compatibility with kodi:
|
||||||
|
# ftp LIST operation returns entries over-the-wire like:
|
||||||
|
# - dgrwxrwxr-x 1 ftp ftp 9 Apr 9 15:05 Videos
|
||||||
|
# however not all clients understand all mode bits (like that `g`, indicating SGID / group sticky bit).
|
||||||
|
# instead, only send mode bits which are well-understood.
|
||||||
|
# the full set of bits, from which i filter, is found here: <https://pkg.go.dev/io/fs#FileMode>
|
||||||
|
./safe_fileinfo.patch
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
ftpd = {
|
ftpd = {
|
||||||
bindings = [
|
bindings = [
|
||||||
|
@ -58,16 +87,33 @@ in
|
||||||
port = 21;
|
port = 21;
|
||||||
debug = true;
|
debug = true;
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
# binding this means any wireguard client can connect
|
||||||
|
address = "10.0.10.5";
|
||||||
|
port = 990;
|
||||||
|
debug = true;
|
||||||
|
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 = 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
|
||||||
disable_active_mode = true;
|
disable_active_mode = true;
|
||||||
hash_support = true;
|
hash_support = true;
|
||||||
passive_port_range = {
|
passive_port_range = {
|
||||||
start = 50050;
|
start = passiveStart;
|
||||||
end = 50100;
|
end = passiveEnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
certificate_file = "/var/lib/acme/ftp.uninsane.org/full.pem";
|
||||||
|
certificate_key_file = "/var/lib/acme/ftp.uninsane.org/key.pem";
|
||||||
|
|
||||||
banner = ''
|
banner = ''
|
||||||
Welcome, friends, to Colin's FTP server! Also available via NFS on the same host, but LAN-only.
|
Welcome, friends, to Colin's FTP server! Also available via NFS on the same host, but LAN-only.
|
||||||
|
|
||||||
|
@ -75,14 +121,14 @@ in
|
||||||
Username: "anonymous"
|
Username: "anonymous"
|
||||||
Password: "anonymous"
|
Password: "anonymous"
|
||||||
|
|
||||||
CONFIGURE YOUR CLIENT FOR "PASSIVE" mode, e.g. `ftp --passive uninsane.org`.
|
CONFIGURE YOUR CLIENT FOR "PASSIVE" MODE, e.g. `ftp --passive ftp.uninsane.org`.
|
||||||
Please let me know if anything's broken or not as it should be. Otherwise, browse and transfer freely :)
|
Please let me know if anything's broken or not as it should be. Otherwise, browse and transfer freely :)
|
||||||
'';
|
'';
|
||||||
|
|
||||||
};
|
};
|
||||||
data_provider = {
|
data_provider = {
|
||||||
driver = "memory";
|
driver = "memory";
|
||||||
external_auth_hook = "${sftpgo_external_auth_hook}/bin/sftpgo_external_auth_hook";
|
external_auth_hook = "${external_auth_hook}/bin/external_auth_hook";
|
||||||
# track_quota:
|
# track_quota:
|
||||||
# - 0: disable quota tracking
|
# - 0: disable quota tracking
|
||||||
# - 1: quota is updated on every upload/delete, even if user has no quota restriction
|
# - 1: quota is updated on every upload/delete, even if user has no quota restriction
|
||||||
|
@ -95,6 +141,7 @@ in
|
||||||
users.users.sftpgo.extraGroups = [
|
users.users.sftpgo.extraGroups = [
|
||||||
"export"
|
"export"
|
||||||
"media"
|
"media"
|
||||||
|
"nginx" # to access certs
|
||||||
];
|
];
|
||||||
|
|
||||||
systemd.services.sftpgo = {
|
systemd.services.sftpgo = {
|
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env nix-shell
|
#!/usr/bin/env nix-shell
|
||||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])"
|
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.passlib ])"
|
||||||
# vim: set filetype=python :
|
# vim: set filetype=python :
|
||||||
#
|
#
|
||||||
# available environment variables:
|
# available environment variables:
|
||||||
|
@ -37,9 +37,9 @@
|
||||||
# - it seems (empirically) that a user can't cd above their home directory.
|
# - it seems (empirically) that a user can't cd above their home directory.
|
||||||
# though i don't have a reference for that in the docs.
|
# though i don't have a reference for that in the docs.
|
||||||
|
|
||||||
import crypt
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import passlib.hosts
|
||||||
|
|
||||||
from hmac import compare_digest
|
from hmac import compare_digest
|
||||||
|
|
||||||
|
@ -112,10 +112,8 @@ def isWireguard(ip: str) -> bool:
|
||||||
|
|
||||||
def isTrustedCred(password: str) -> bool:
|
def isTrustedCred(password: str) -> bool:
|
||||||
for cred in TRUSTED_CREDS:
|
for cred in TRUSTED_CREDS:
|
||||||
_, method, salt, hash_ = cred.split("$")
|
if passlib.hosts.linux_context.verify(password, cred):
|
||||||
# assert method == "6", f"unrecognized crypt entry: {cred}"
|
return True
|
||||||
if crypt.crypt(password, f"${method}${salt}") == cred:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
diff --git a/internal/ftpd/handler.go b/internal/ftpd/handler.go
|
||||||
|
index 036c3977..33211261 100644
|
||||||
|
--- a/internal/ftpd/handler.go
|
||||||
|
+++ b/internal/ftpd/handler.go
|
||||||
|
@@ -169,7 +169,7 @@ func (c *Connection) Stat(name string) (os.FileInfo, error) {
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
- return fi, nil
|
||||||
|
+ return vfs.NewFileInfo(name, fi.IsDir(), fi.Size(), fi.ModTime(), false), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the name of this connection
|
||||||
|
@@ -315,7 +315,17 @@ func (c *Connection) ReadDir(name string) (ftpserver.DirLister, error) {
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
- return c.ListDir(name)
|
||||||
|
+ lister, err := c.ListDir(name)
|
||||||
|
+ if err != nil {
|
||||||
|
+ return nil, err
|
||||||
|
+ }
|
||||||
|
+ return &patternDirLister{
|
||||||
|
+ DirLister: lister,
|
||||||
|
+ pattern: "*",
|
||||||
|
+ lastCommand: c.clientContext.GetLastCommand(),
|
||||||
|
+ dirName: name,
|
||||||
|
+ connectionPath: c.clientContext.Path(),
|
||||||
|
+ }, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHandle implements ClientDriverExtentionFileTransfer
|
|
@ -90,6 +90,8 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
services.openssh.settings.UsePAM = true; #< required for `git` user to authenticate
|
||||||
|
|
||||||
# hosted git (web view and for `git <cmd>` use
|
# hosted git (web view and for `git <cmd>` use
|
||||||
# TODO: enable publog?
|
# TODO: enable publog?
|
||||||
services.nginx.virtualHosts."git.uninsane.org" = {
|
services.nginx.virtualHosts."git.uninsane.org" = {
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
--ignore-panel=HOSTS \
|
--ignore-panel=HOSTS \
|
||||||
--ws-url=wss://sink.uninsane.org:443/ws \
|
--ws-url=wss://sink.uninsane.org:443/ws \
|
||||||
--port=7890 \
|
--port=7890 \
|
||||||
-o /var/lib/uninsane/sink/index.html
|
-o /var/lib/goaccess/index.html
|
||||||
'';
|
'';
|
||||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||||
Type = "simple";
|
Type = "simple";
|
||||||
|
@ -28,17 +28,19 @@
|
||||||
RestartSec = "10s";
|
RestartSec = "10s";
|
||||||
|
|
||||||
# hardening
|
# hardening
|
||||||
WorkingDirectory = "/tmp";
|
# TODO: run as `goaccess` user and add `goaccess` user to group `nginx`.
|
||||||
NoNewPrivileges = true;
|
NoNewPrivileges = true;
|
||||||
|
PrivateDevices = "yes";
|
||||||
PrivateTmp = true;
|
PrivateTmp = true;
|
||||||
ProtectHome = "read-only";
|
ProtectHome = "read-only";
|
||||||
ProtectSystem = "strict";
|
|
||||||
SystemCallFilter = "~@clock @cpu-emulation @debug @keyring @memlock @module @mount @obsolete @privileged @reboot @resources @setuid @swap @raw-io";
|
|
||||||
ReadOnlyPaths = "/";
|
|
||||||
ReadWritePaths = [ "/proc/self" "/var/lib/uninsane/sink" ];
|
|
||||||
PrivateDevices = "yes";
|
|
||||||
ProtectKernelModules = "yes";
|
ProtectKernelModules = "yes";
|
||||||
ProtectKernelTunables = "yes";
|
ProtectKernelTunables = "yes";
|
||||||
|
ProtectSystem = "strict";
|
||||||
|
ReadOnlyPaths = [ "/var/log/nginx" ];
|
||||||
|
ReadWritePaths = [ "/proc/self" "/var/lib/goaccess" ];
|
||||||
|
StateDirectory = "goaccess";
|
||||||
|
SystemCallFilter = "~@clock @cpu-emulation @debug @keyring @memlock @module @mount @obsolete @privileged @reboot @resources @setuid @swap @raw-io";
|
||||||
|
WorkingDirectory = "/var/lib/goaccess";
|
||||||
};
|
};
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
@ -49,7 +51,7 @@
|
||||||
addSSL = true;
|
addSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
# inherit kTLS;
|
# inherit kTLS;
|
||||||
root = "/var/lib/uninsane/sink";
|
root = "/var/lib/goaccess";
|
||||||
|
|
||||||
locations."/ws" = {
|
locations."/ws" = {
|
||||||
proxyPass = "http://127.0.0.1:7890";
|
proxyPass = "http://127.0.0.1:7890";
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{ ... }:
|
{ lib, pkgs, ... }:
|
||||||
|
|
||||||
|
lib.mkIf false #< TODO: re-enable once confident of sandboxing
|
||||||
{
|
{
|
||||||
sane.persist.sys.byStore.plaintext = [
|
sane.persist.sys.byStore.plaintext = [
|
||||||
# TODO: mode? we only need this to save Indexer creds ==> migrate to config?
|
# TODO: mode? we only need this to save Indexer creds ==> migrate to config?
|
||||||
|
@ -12,6 +13,8 @@
|
||||||
systemd.services.jackett.serviceConfig = {
|
systemd.services.jackett.serviceConfig = {
|
||||||
# run this behind the OVPN static VPN
|
# run this behind the OVPN static VPN
|
||||||
NetworkNamespacePath = "/run/netns/ovpns";
|
NetworkNamespacePath = "/run/netns/ovpns";
|
||||||
|
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect 185.157.162.178" ]; # abort if public IP is not as expected
|
||||||
|
|
||||||
# patch jackett to listen on the public interfaces
|
# patch jackett to listen on the public interfaces
|
||||||
# ExecStart = lib.mkForce "${pkgs.jackett}/bin/Jackett --NoUpdates --DataFolder /var/lib/jackett/.config/Jackett --ListenPublic";
|
# ExecStart = lib.mkForce "${pkgs.jackett}/bin/Jackett --NoUpdates --DataFolder /var/lib/jackett/.config/Jackett --ListenPublic";
|
||||||
};
|
};
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
# Jellyfin multimedia server
|
# Jellyfin multimedia server
|
||||||
# this is mostly taken from the official jellfin.org docs
|
# this is mostly taken from the official jellfin.org docs
|
||||||
services.nginx.virtualHosts."jelly.uninsane.org" = {
|
services.nginx.virtualHosts."jelly.uninsane.org" = {
|
||||||
addSSL = true;
|
forceSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
# inherit kTLS;
|
# inherit kTLS;
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ in
|
||||||
services.komga.port = 11319; # chosen at random
|
services.komga.port = 11319; # chosen at random
|
||||||
|
|
||||||
services.nginx.virtualHosts."komga.uninsane.org" = {
|
services.nginx.virtualHosts."komga.uninsane.org" = {
|
||||||
addSSL = true;
|
forceSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
||||||
|
|
|
@ -22,7 +22,7 @@ let
|
||||||
# # "Change commandline flag to allow disabling video, since it is enabled by default"
|
# # "Change commandline flag to allow disabling video, since it is enabled by default"
|
||||||
# postPatch = (upstream.postPatch or "") + ''
|
# postPatch = (upstream.postPatch or "") + ''
|
||||||
# substituteInPlace src/validate.rs \
|
# substituteInPlace src/validate.rs \
|
||||||
# --replace 'if transcode_options.needs_reencode() {' 'if false {'
|
# --replace-fail 'if transcode_options.needs_reencode() {' 'if false {'
|
||||||
# '';
|
# '';
|
||||||
# });
|
# });
|
||||||
in {
|
in {
|
||||||
|
|
|
@ -89,6 +89,16 @@ in
|
||||||
disable_symlinks on;
|
disable_symlinks on;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
locations."/share/Milkbags/" = {
|
||||||
|
alias = "/var/media/Videos/Milkbags/";
|
||||||
|
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 =
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
{ config, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
services.nginx.virtualHosts."nixcache.uninsane.org" = {
|
|
||||||
addSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
# inherit kTLS;
|
|
||||||
# serverAliases = [ "nixcache" ];
|
|
||||||
locations."/".extraConfig = ''
|
|
||||||
proxy_pass http://localhost:${toString config.services.nix-serve.port};
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."nixcache" = "native";
|
|
||||||
|
|
||||||
sane.services.nixserve.enable = true;
|
|
||||||
sane.services.nixserve.secretKeyFile = config.sops.secrets.nix_serve_privkey.path;
|
|
||||||
}
|
|
|
@ -25,7 +25,7 @@ in
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
url: [host: "fed.uninsane.org", scheme: "https", port: 443],
|
url: [host: "fed.uninsane.org", scheme: "https", port: 443],
|
||||||
http: [ip: {127, 0, 0, 1}, port: 4000]
|
http: [ip: {127, 0, 0, 1}, port: 4040]
|
||||||
# secret_key_base: "{secrets.pleroma.secret_key_base}",
|
# secret_key_base: "{secrets.pleroma.secret_key_base}",
|
||||||
# signing_salt: "{secrets.pleroma.signing_salt}"
|
# signing_salt: "{secrets.pleroma.signing_salt}"
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ in
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
# inherit kTLS;
|
# inherit kTLS;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://127.0.0.1:4000";
|
proxyPass = "http://127.0.0.1:4040";
|
||||||
recommendedProxySettings = true;
|
recommendedProxySettings = true;
|
||||||
# documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx
|
# documented: https://git.pleroma.social/pleroma/pleroma/-/blob/develop/installation/pleroma.nginx
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
# debugging:
|
# debugging:
|
||||||
# - soulseek is just *flaky*. if you see e.g. DNS errors, even though you can't replicate them via `dig` or `getent ahostsv4`, just give it 10 minutes to work out:
|
# - soulseek is just *flaky*. if you see e.g. DNS errors, even though you can't replicate them via `dig` or `getent ahostsv4`, just give it 10 minutes to work out:
|
||||||
# - "Soulseek.AddressException: Failed to resolve address 'vps.slsknet.org': Resource temporarily unavailable"
|
# - "Soulseek.AddressException: Failed to resolve address 'vps.slsknet.org': Resource temporarily unavailable"
|
||||||
{ config, lib, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
sane.persist.sys.byStore.plaintext = [
|
sane.persist.sys.byStore.plaintext = [
|
||||||
{ user = "slskd"; group = "media"; path = "/var/lib/slskd"; method = "bind"; }
|
{ user = "slskd"; group = "media"; path = "/var/lib/slskd"; method = "bind"; }
|
||||||
|
@ -68,12 +69,12 @@
|
||||||
# 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 = {
|
systemd.services.slskd.serviceConfig = {
|
||||||
serviceConfig = {
|
# run this behind the OVPN static VPN
|
||||||
# run this behind the OVPN static VPN
|
NetworkNamespacePath = "/run/netns/ovpns";
|
||||||
NetworkNamespacePath = "/run/netns/ovpns";
|
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect 185.157.162.178" ]; # abort if public IP is not as expected
|
||||||
Restart = lib.mkForce "always"; # exits "success" when it fails to connect to soulseek server
|
|
||||||
RestartSec = "60s";
|
Restart = lib.mkForce "always"; # exits "success" when it fails to connect to soulseek server
|
||||||
};
|
RestartSec = "60s";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,9 @@ let
|
||||||
torrent-done = pkgs.writeShellApplication {
|
torrent-done = pkgs.writeShellApplication {
|
||||||
name = "torrent-done";
|
name = "torrent-done";
|
||||||
runtimeInputs = with pkgs; [
|
runtimeInputs = with pkgs; [
|
||||||
|
acl
|
||||||
|
coreutils
|
||||||
|
findutils
|
||||||
rsync
|
rsync
|
||||||
util-linux
|
util-linux
|
||||||
];
|
];
|
||||||
|
@ -52,12 +55,34 @@ let
|
||||||
|
|
||||||
destructive mkdir -p "$(dirname "$MEDIA_DIR")"
|
destructive mkdir -p "$(dirname "$MEDIA_DIR")"
|
||||||
destructive rsync -arv "$TR_TORRENT_DIR/" "$MEDIA_DIR/"
|
destructive rsync -arv "$TR_TORRENT_DIR/" "$MEDIA_DIR/"
|
||||||
|
# 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 chmod g+rw,a+rx {} \;
|
||||||
|
|
||||||
|
# if there's a single directory inside the media dir, then inline that
|
||||||
|
subdirs=("$MEDIA_DIR"/*)
|
||||||
|
if [ ''${#subdirs} -eq 1 ]; then
|
||||||
|
dirname="''${subdirs[0]}"
|
||||||
|
if [ -d "$dirname" ]; then
|
||||||
|
mv "$dirname"/* "$MEDIA_DIR/" && rmdir "$dirname"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# remove noisy files:
|
||||||
|
find "$MEDIA_DIR/" -type f \(\
|
||||||
|
-iname 'www.YTS.*.jpg' \
|
||||||
|
-o -iname 'WWW.YIFY*.COM.jpg' \
|
||||||
|
-o -iname 'YIFY*.com.txt' \
|
||||||
|
-o -iname 'YTS*.com.txt' \
|
||||||
|
\) -exec rm {} \;
|
||||||
|
|
||||||
# dedupe the whole media library.
|
# dedupe the whole media library.
|
||||||
# yeah, a bit excessive: move this to a cron job if that's problematic.
|
# yeah, a bit excessive: move this to a cron job if that's problematic.
|
||||||
destructive hardlink /var/media --reflink=always --ignore-time --verbose
|
destructive hardlink /var/media --reflink=always --ignore-time --verbose
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
|
lib.mkIf false #< TODO: re-enable once confident of sandboxing
|
||||||
{
|
{
|
||||||
sane.persist.sys.byStore.plaintext = [
|
sane.persist.sys.byStore.plaintext = [
|
||||||
# TODO: mode? we need this specifically for the stats tracking in .config/
|
# TODO: mode? we need this specifically for the stats tracking in .config/
|
||||||
|
@ -81,8 +106,8 @@ in
|
||||||
# DOCUMENTATION/options list: <https://github.com/transmission/transmission/blob/main/docs/Editing-Configuration-Files.md#options>
|
# DOCUMENTATION/options list: <https://github.com/transmission/transmission/blob/main/docs/Editing-Configuration-Files.md#options>
|
||||||
|
|
||||||
# message-level = 3; #< enable for debug logging. 0-3, default is 2.
|
# message-level = 3; #< enable for debug logging. 0-3, default is 2.
|
||||||
# 0.0.0.0 => allow rpc from any host: we gate it via firewall and auth requirement
|
# 10.0.1.6 => allow rpc only from the root servo ns. it'll tunnel things to the net, if need be.
|
||||||
rpc-bind-address = "0.0.0.0";
|
rpc-bind-address = "10.0.1.6";
|
||||||
#rpc-host-whitelist = "bt.uninsane.org";
|
#rpc-host-whitelist = "bt.uninsane.org";
|
||||||
#rpc-whitelist = "*.*.*.*";
|
#rpc-whitelist = "*.*.*.*";
|
||||||
rpc-authentication-required = true;
|
rpc-authentication-required = true;
|
||||||
|
@ -92,6 +117,10 @@ in
|
||||||
rpc-password = "{503fc8928344f495efb8e1f955111ca5c862ce0656SzQnQ5";
|
rpc-password = "{503fc8928344f495efb8e1f955111ca5c862ce0656SzQnQ5";
|
||||||
rpc-whitelist-enabled = false;
|
rpc-whitelist-enabled = false;
|
||||||
|
|
||||||
|
# force behind ovpns in case the NetworkNamespace fails somehow
|
||||||
|
bind-address-ipv4 = "185.157.162.178";
|
||||||
|
port-forwarding-enabled = false;
|
||||||
|
|
||||||
# hopefully, make the downloads world-readable
|
# hopefully, make the downloads world-readable
|
||||||
# umask = 0; #< default is 2: i.e. deny writes from world
|
# umask = 0; #< default is 2: i.e. deny writes from world
|
||||||
|
|
||||||
|
@ -131,6 +160,8 @@ in
|
||||||
systemd.services.transmission.serviceConfig = {
|
systemd.services.transmission.serviceConfig = {
|
||||||
# run this behind the OVPN static VPN
|
# run this behind the OVPN static VPN
|
||||||
NetworkNamespacePath = "/run/netns/ovpns";
|
NetworkNamespacePath = "/run/netns/ovpns";
|
||||||
|
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect 185.157.162.178" ]; # abort if public IP is not as expected
|
||||||
|
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = "30s";
|
RestartSec = "30s";
|
||||||
BindPaths = [ "/var/media" ]; #< so it can move completed torrents into the media library
|
BindPaths = [ "/var/media" ]; #< so it can move completed torrents into the media library
|
||||||
|
|
|
@ -2,19 +2,11 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
|
dyn-dns = config.sane.services.dyn-dns;
|
||||||
nativeAddrs = lib.mapAttrs (_name: builtins.head) config.sane.dns.zones."uninsane.org".inet.A;
|
nativeAddrs = lib.mapAttrs (_name: builtins.head) config.sane.dns.zones."uninsane.org".inet.A;
|
||||||
bindOvpn = "10.0.1.5";
|
bindOvpn = "10.0.1.5";
|
||||||
in lib.mkMerge [
|
in
|
||||||
{
|
{
|
||||||
services.trust-dns.enable = true;
|
|
||||||
|
|
||||||
# don't bind to IPv6 until i explicitly test that stack
|
|
||||||
services.trust-dns.settings.listen_addrs_ipv6 = [];
|
|
||||||
services.trust-dns.quiet = true;
|
|
||||||
# FIXME(2023/11/26): services.trust-dns.debug doesn't log requests: use RUST_LOG=debug env for that.
|
|
||||||
# - see: <https://github.com/hickory-dns/hickory-dns/issues/2082>
|
|
||||||
# services.trust-dns.debug = true;
|
|
||||||
|
|
||||||
sane.ports.ports."53" = {
|
sane.ports.ports."53" = {
|
||||||
protocol = [ "udp" "tcp" ];
|
protocol = [ "udp" "tcp" ];
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
|
@ -66,23 +58,6 @@ in lib.mkMerge [
|
||||||
|
|
||||||
services.trust-dns.settings.zones = [ "uninsane.org" ];
|
services.trust-dns.settings.zones = [ "uninsane.org" ];
|
||||||
|
|
||||||
# TODO: can i transform this into some sort of service group?
|
|
||||||
# have `systemctl restart trust-dns.service` restart all the individual services?
|
|
||||||
systemd.services.trust-dns.serviceConfig = {
|
|
||||||
DynamicUser = lib.mkForce false;
|
|
||||||
User = "trust-dns";
|
|
||||||
Group = "trust-dns";
|
|
||||||
wantedBy = lib.mkForce [];
|
|
||||||
};
|
|
||||||
systemd.services.trust-dns.enable = false;
|
|
||||||
|
|
||||||
users.groups.trust-dns = {};
|
|
||||||
users.users.trust-dns = {
|
|
||||||
group = "trust-dns";
|
|
||||||
isSystemUser = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# sane.services.dyn-dns.restartOnChange = [ "trust-dns.service" ];
|
|
||||||
|
|
||||||
networking.nat.enable = true;
|
networking.nat.enable = true;
|
||||||
networking.nat.extraCommands = ''
|
networking.nat.extraCommands = ''
|
||||||
|
@ -107,98 +82,73 @@ in lib.mkMerge [
|
||||||
visibleTo.lan = true;
|
visibleTo.lan = true;
|
||||||
description = "colin-redirected-dns-for-lan-namespace";
|
description = "colin-redirected-dns-for-lan-namespace";
|
||||||
};
|
};
|
||||||
}
|
|
||||||
{
|
|
||||||
systemd.services =
|
|
||||||
let
|
|
||||||
sed = "${pkgs.gnused}/bin/sed";
|
|
||||||
stateDir = "/var/lib/trust-dns";
|
|
||||||
zoneTemplate = pkgs.writeText "uninsane.org.zone.in" config.sane.dns.zones."uninsane.org".rendered;
|
|
||||||
|
|
||||||
zoneDirFor = flavor: "${stateDir}/${flavor}";
|
|
||||||
zoneFor = flavor: "${zoneDirFor flavor}/uninsane.org.zone";
|
|
||||||
mkTrustDnsService = opts: flavor: let
|
|
||||||
flags = let baseCfg = config.services.trust-dns; in
|
|
||||||
(lib.optional baseCfg.debug "--debug") ++ (lib.optional baseCfg.quiet "--quiet");
|
|
||||||
flagsStr = builtins.concatStringsSep " " flags;
|
|
||||||
|
|
||||||
anative = nativeAddrs."servo.${flavor}";
|
sane.services.trust-dns.enable = true;
|
||||||
|
sane.services.trust-dns.instances = let
|
||||||
toml = pkgs.formats.toml { };
|
mkSubstitutions = flavor: {
|
||||||
configTemplate = opts.config or (toml.generate "trust-dns-${flavor}.toml" (
|
"%AWAN%" = "$(cat '${dyn-dns.ipPath}')";
|
||||||
(
|
"%CNAMENATIVE%" = "servo.${flavor}";
|
||||||
lib.filterAttrsRecursive (_: v: v != null) config.services.trust-dns.settings
|
"%ANATIVE%" = nativeAddrs."servo.${flavor}";
|
||||||
) // {
|
"%AOVPNS%" = "185.157.162.178";
|
||||||
listen_addrs_ipv4 = opts.listen or [ anative ];
|
|
||||||
}
|
|
||||||
));
|
|
||||||
configFile = "${stateDir}/${flavor}-config.toml";
|
|
||||||
|
|
||||||
port = opts.port or 53;
|
|
||||||
in {
|
|
||||||
description = "trust-dns Domain Name Server (serving ${flavor})";
|
|
||||||
unitConfig.Documentation = "https://trust-dns.org/";
|
|
||||||
|
|
||||||
preStart = ''
|
|
||||||
wan=$(cat '${config.sane.services.dyn-dns.ipPath}')
|
|
||||||
${sed} s/%AWAN%/$wan/ ${configTemplate} > ${configFile}
|
|
||||||
'' + lib.optionalString (!opts ? config) ''
|
|
||||||
mkdir -p ${zoneDirFor flavor}
|
|
||||||
${sed} \
|
|
||||||
-e s/%CNAMENATIVE%/servo.${flavor}/ \
|
|
||||||
-e s/%ANATIVE%/${anative}/ \
|
|
||||||
-e s/%AWAN%/$wan/ \
|
|
||||||
-e s/%AOVPNS%/185.157.162.178/ \
|
|
||||||
${zoneTemplate} > ${zoneFor flavor}
|
|
||||||
'';
|
|
||||||
serviceConfig = config.systemd.services.trust-dns.serviceConfig // {
|
|
||||||
ExecStart = ''
|
|
||||||
${pkgs.trust-dns}/bin/${pkgs.trust-dns.meta.mainProgram} \
|
|
||||||
--port ${builtins.toString port} \
|
|
||||||
--zonedir ${zoneDirFor flavor}/ \
|
|
||||||
--config ${configFile} ${flagsStr}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
after = [ "network.target" ];
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
trust-dns-wan = mkTrustDnsService { listen = [ nativeAddrs."servo.lan" bindOvpn ]; } "wan";
|
|
||||||
trust-dns-lan = mkTrustDnsService { port = 1053; } "lan";
|
|
||||||
trust-dns-hn = mkTrustDnsService { port = 1053; } "hn";
|
|
||||||
trust-dns-hn-resolver = mkTrustDnsService {
|
|
||||||
config = pkgs.writeText "hn-resolver-config.toml" ''
|
|
||||||
# i host a resolver in the wireguard VPN so that clients can resolve DNS through the VPN.
|
|
||||||
# (that's what this file achieves).
|
|
||||||
#
|
|
||||||
# one would expect this resolver could host the authoritative zone for `uninsane.org`, and then forward everything else to the system resolver...
|
|
||||||
# and while that works for `dig`, it breaks for `nslookup` (and so `ssh`, etc).
|
|
||||||
#
|
|
||||||
# DNS responses include a flag for if the responding server is the authority of the zone queried.
|
|
||||||
# it seems that default Linux stub resolvers either:
|
|
||||||
# - expect DNSSEC when the response includes that bit, or
|
|
||||||
# - expect A records to be in the `answer` section instead of `additional` section.
|
|
||||||
# or perhaps something more nuanced. but for `nslookup` to be reliable, it has to talk to an
|
|
||||||
# instance of trust-dns which is strictly a resolver, with no authority.
|
|
||||||
# hence, this config: a resolver which forwards to the actual authority.
|
|
||||||
|
|
||||||
listen_addrs_ipv4 = ["${nativeAddrs."servo.hn"}"]
|
|
||||||
listen_addrs_ipv6 = []
|
|
||||||
|
|
||||||
[[zones]]
|
|
||||||
zone = "uninsane.org"
|
|
||||||
zone_type = "Forward"
|
|
||||||
stores = { type = "forward", name_servers = [{ socket_addr = "${nativeAddrs."servo.hn"}:1053", protocol = "udp", trust_nx_responses = true }] }
|
|
||||||
|
|
||||||
[[zones]]
|
|
||||||
# forward the root zone to the local DNS resolver
|
|
||||||
zone = "."
|
|
||||||
zone_type = "Forward"
|
|
||||||
stores = { type = "forward", name_servers = [{ socket_addr = "127.0.0.53:53", protocol = "udp", trust_nx_responses = true }] }
|
|
||||||
'';
|
|
||||||
} "hn-resolver";
|
|
||||||
};
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
wan = {
|
||||||
|
substitutions = mkSubstitutions "wan";
|
||||||
|
listenAddrsIpv4 = [
|
||||||
|
nativeAddrs."servo.lan"
|
||||||
|
bindOvpn
|
||||||
|
];
|
||||||
|
};
|
||||||
|
lan = {
|
||||||
|
substitutions = mkSubstitutions "lan";
|
||||||
|
listenAddrsIpv4 = [ nativeAddrs."servo.lan" ];
|
||||||
|
port = 1053;
|
||||||
|
};
|
||||||
|
hn = {
|
||||||
|
substitutions = mkSubstitutions "hn";
|
||||||
|
listenAddrsIpv4 = [ nativeAddrs."servo.hn" ];
|
||||||
|
port = 1053;
|
||||||
|
};
|
||||||
|
# hn-resolver = {
|
||||||
|
# # don't need %AWAN% here because we forward to the hn instance.
|
||||||
|
# listenAddrsIpv4 = [ nativeAddrs."servo.hn" ];
|
||||||
|
# extraConfig = {
|
||||||
|
# zones = [
|
||||||
|
# {
|
||||||
|
# zone = "uninsane.org";
|
||||||
|
# zone_type = "Forward";
|
||||||
|
# stores = {
|
||||||
|
# type = "forward";
|
||||||
|
# name_servers = [
|
||||||
|
# {
|
||||||
|
# socket_addr = "${nativeAddrs."servo.hn"}:1053";
|
||||||
|
# protocol = "udp";
|
||||||
|
# trust_nx_responses = true;
|
||||||
|
# }
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
|
# }
|
||||||
|
# {
|
||||||
|
# # forward the root zone to the local DNS resolver
|
||||||
|
# zone = ".";
|
||||||
|
# zone_type = "Forward";
|
||||||
|
# stores = {
|
||||||
|
# type = "forward";
|
||||||
|
# name_servers = [
|
||||||
|
# {
|
||||||
|
# socket_addr = "127.0.0.53:53";
|
||||||
|
# protocol = "udp";
|
||||||
|
# trust_nx_responses = true;
|
||||||
|
# }
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
|
# }
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
};
|
||||||
|
|
||||||
sane.services.dyn-dns.restartOnChange = [
|
sane.services.dyn-dns.restartOnChange = [
|
||||||
"trust-dns-wan.service"
|
"trust-dns-wan.service"
|
||||||
|
@ -207,4 +157,3 @@ in lib.mkMerge [
|
||||||
# "trust-dns-hn-resolver.service" # doesn't need restart because it doesn't know about WAN IP
|
# "trust-dns-hn-resolver.service" # doesn't need restart because it doesn't know about WAN IP
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
]
|
|
||||||
|
|
|
@ -81,11 +81,15 @@ let
|
||||||
(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 "fulltimenix.com" // tech)
|
(fromDb "fulltimenix.com" // 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 "mapspodcast.libsyn.com" // uncat) # Multidisciplinary Association for Psychedelic Studies
|
(fromDb "mapspodcast.libsyn.com" // uncat) # Multidisciplinary Association for Psychedelic Studies
|
||||||
|
(fromDb "microarch.club" // tech)
|
||||||
|
(fromDb "mintcast.org" // tech)
|
||||||
(fromDb "omegataupodcast.net" // tech) # 3/4 German; 1/4 eps are English
|
(fromDb "omegataupodcast.net" // tech) # 3/4 German; 1/4 eps are English
|
||||||
(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/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 "originstories.libsyn.com" // uncat)
|
(fromDb "originstories.libsyn.com" // uncat)
|
||||||
(fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
|
(fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
|
||||||
|
@ -101,6 +105,8 @@ let
|
||||||
(fromDb "sharkbytes.transistor.fm" // tech) # Wireshark Podcast o_0
|
(fromDb "sharkbytes.transistor.fm" // tech) # Wireshark Podcast o_0
|
||||||
(fromDb "sscpodcast.libsyn.com" // rat) # Astral Codex Ten
|
(fromDb "sscpodcast.libsyn.com" // rat) # Astral Codex Ten
|
||||||
(fromDb "talesfromthebridge.buzzsprout.com" // tech) # Sci-Fi? has Peter Watts; author of No Moods, Ads or Cutesy Fucking Icons (rifters.com)
|
(fromDb "talesfromthebridge.buzzsprout.com" // tech) # Sci-Fi? has Peter Watts; author of No Moods, Ads or Cutesy Fucking Icons (rifters.com)
|
||||||
|
(fromDb "theamphour.com" // tech)
|
||||||
|
(fromDb "techtalesshow.com" // tech) # Corbin Davenport
|
||||||
(fromDb "techwontsave.us" // pol) # rec by Cory Doctorow
|
(fromDb "techwontsave.us" // pol) # rec by Cory Doctorow
|
||||||
(fromDb "wakingup.libsyn.com" // pol) # Sam Harris
|
(fromDb "wakingup.libsyn.com" // pol) # Sam Harris
|
||||||
(fromDb "werenotwrong.fireside.fm" // pol)
|
(fromDb "werenotwrong.fireside.fm" // pol)
|
||||||
|
@ -124,11 +130,11 @@ let
|
||||||
(fromDb "acoup.blog/feed") # history, states. author: <https://historians.social/@bretdevereaux/following>
|
(fromDb "acoup.blog/feed") # history, states. author: <https://historians.social/@bretdevereaux/following>
|
||||||
(fromDb "amosbbatto.wordpress.com" // tech)
|
(fromDb "amosbbatto.wordpress.com" // tech)
|
||||||
(fromDb "anish.lakhwara.com" // tech)
|
(fromDb "anish.lakhwara.com" // tech)
|
||||||
|
(fromDb "apenwarr.ca/log/rss.php" // tech) # CEO of tailscale
|
||||||
(fromDb "applieddivinitystudies.com" // rat)
|
(fromDb "applieddivinitystudies.com" // rat)
|
||||||
(fromDb "artemis.sh" // tech)
|
(fromDb "artemis.sh" // tech)
|
||||||
(fromDb "ascii.textfiles.com" // tech) # Jason Scott
|
(fromDb "ascii.textfiles.com" // tech) # Jason Scott
|
||||||
(fromDb "austinvernon.site" // tech)
|
(fromDb "austinvernon.site" // tech)
|
||||||
# (fromDb "balajis.com" // pol) # Balaji
|
|
||||||
(fromDb "ben-evans.com/benedictevans" // pol)
|
(fromDb "ben-evans.com/benedictevans" // pol)
|
||||||
(fromDb "bitbashing.io" // tech)
|
(fromDb "bitbashing.io" // tech)
|
||||||
(fromDb "bitsaboutmoney.com" // uncat)
|
(fromDb "bitsaboutmoney.com" // uncat)
|
||||||
|
@ -139,8 +145,6 @@ let
|
||||||
(fromDb "blog.thalheim.io" // tech) # Mic92
|
(fromDb "blog.thalheim.io" // tech) # Mic92
|
||||||
(fromDb "bunniestudios.com" // tech) # Bunnie Juang
|
(fromDb "bunniestudios.com" // tech) # Bunnie Juang
|
||||||
(fromDb "capitolhillseattle.com" // pol)
|
(fromDb "capitolhillseattle.com" // pol)
|
||||||
# (fromDb "drewdevault.com" // tech)
|
|
||||||
# (fromDb "econlib.org" // pol)
|
|
||||||
(fromDb "edwardsnowden.substack.com" // pol // text)
|
(fromDb "edwardsnowden.substack.com" // pol // text)
|
||||||
(fromDb "fasterthanli.me" // tech)
|
(fromDb "fasterthanli.me" // tech)
|
||||||
(fromDb "gwern.net" // rat)
|
(fromDb "gwern.net" // rat)
|
||||||
|
@ -151,9 +155,9 @@ let
|
||||||
(fromDb "interconnected.org/home/feed" // rat) # Matt Webb -- engineering-ish, but dreamy
|
(fromDb "interconnected.org/home/feed" // rat) # Matt Webb -- engineering-ish, but dreamy
|
||||||
(fromDb "jeffgeerling.com" // tech)
|
(fromDb "jeffgeerling.com" // tech)
|
||||||
(fromDb "jefftk.com" // tech)
|
(fromDb "jefftk.com" // tech)
|
||||||
|
(fromDb "jwz.org/blog" // tech // pol) # DNA lounge guy, loooong-time blogger
|
||||||
(fromDb "kill-the-newsletter.com/feeds/joh91bv7am2pnznv.xml" // pol) # Matt Levine - Money Stuff
|
(fromDb "kill-the-newsletter.com/feeds/joh91bv7am2pnznv.xml" // pol) # Matt Levine - Money Stuff
|
||||||
(fromDb "kosmosghost.github.io/index.xml" // tech)
|
(fromDb "kosmosghost.github.io/index.xml" // tech)
|
||||||
# (fromDb "lesswrong.com" // rat)
|
|
||||||
(fromDb "linmob.net" // tech)
|
(fromDb "linmob.net" // tech)
|
||||||
(fromDb "lwn.net" // tech)
|
(fromDb "lwn.net" // tech)
|
||||||
(fromDb "lynalden.com" // pol)
|
(fromDb "lynalden.com" // pol)
|
||||||
|
@ -168,13 +172,13 @@ let
|
||||||
(fromDb "pomeroyb.com" // tech)
|
(fromDb "pomeroyb.com" // tech)
|
||||||
(fromDb "postmarketos.org/blog" // tech)
|
(fromDb "postmarketos.org/blog" // tech)
|
||||||
(fromDb "preposterousuniverse.com" // rat) # Sean Carroll
|
(fromDb "preposterousuniverse.com" // rat) # Sean Carroll
|
||||||
(fromDb "profectusmag.com" // uncat)
|
|
||||||
(fromDb "project-insanity.org" // tech) # shared blog by a few NixOS devs, notably onny
|
(fromDb "project-insanity.org" // tech) # shared blog by a few NixOS devs, notably onny
|
||||||
(fromDb "putanumonit.com" // rat) # mostly dating topics. not advice, or humor, but looking through a social lens
|
(fromDb "putanumonit.com" // rat) # mostly dating topics. not advice, or humor, but looking through a social lens
|
||||||
(fromDb "richardcarrier.info" // rat)
|
(fromDb "richardcarrier.info" // rat)
|
||||||
(fromDb "rifters.com/crawl" // uncat) # No Moods, Ads or Cutesy Fucking Icons
|
(fromDb "rifters.com/crawl" // uncat) # No Moods, Ads or Cutesy Fucking Icons
|
||||||
(fromDb "righto.com" // tech) # Ken Shirriff
|
(fromDb "righto.com" // tech) # Ken Shirriff
|
||||||
(fromDb "rootsofprogress.org" // rat) # Jason Crawford
|
(fromDb "rootsofprogress.org" // rat) # Jason Crawford
|
||||||
|
(fromDb "samuel.dionne-riel.com" // tech) # SamuelDR
|
||||||
(fromDb "sagacioussuricata.com" // tech) # ian (Sanctuary)
|
(fromDb "sagacioussuricata.com" // tech) # ian (Sanctuary)
|
||||||
(fromDb "semiaccurate.com" // tech)
|
(fromDb "semiaccurate.com" // tech)
|
||||||
(fromDb "sideways-view.com" // rat) # Paul Christiano
|
(fromDb "sideways-view.com" // rat) # Paul Christiano
|
||||||
|
@ -183,33 +187,41 @@ let
|
||||||
(fromDb "spectrum.ieee.org" // tech)
|
(fromDb "spectrum.ieee.org" // tech)
|
||||||
(fromDb "stpeter.im/atom.xml" // pol)
|
(fromDb "stpeter.im/atom.xml" // pol)
|
||||||
(fromDb "thediff.co" // pol) # Byrne Hobart
|
(fromDb "thediff.co" // pol) # Byrne Hobart
|
||||||
# (fromDb "theregister.com" // tech)
|
|
||||||
(fromDb "thisweek.gnome.org" // tech)
|
(fromDb "thisweek.gnome.org" // tech)
|
||||||
(fromDb "tuxphones.com" // tech)
|
(fromDb "tuxphones.com" // tech)
|
||||||
(fromDb "uninsane.org" // tech)
|
(fromDb "uninsane.org" // tech)
|
||||||
(fromDb "unintendedconsequenc.es" // rat)
|
(fromDb "unintendedconsequenc.es" // rat)
|
||||||
# (fromDb "vitalik.ca" // tech) # moved to vitalik.eth.limo
|
|
||||||
(fromDb "vitalik.eth.limo" // tech) # Vitalik Buterin
|
(fromDb "vitalik.eth.limo" // tech) # Vitalik Buterin
|
||||||
# (fromDb "webcurious.co.uk" // uncat) # link aggregator; defunct?
|
(fromDb "weekinethereumnews.com" // tech)
|
||||||
(fromDb "willow.phantoma.online") # wizard@xyzzy.link
|
(fromDb "willow.phantoma.online") # wizard@xyzzy.link
|
||||||
(fromDb "xn--gckvb8fzb.com" // tech)
|
(fromDb "xn--gckvb8fzb.com" // tech)
|
||||||
(mkSubstack "astralcodexten" // rat // daily) # Scott Alexander
|
(mkSubstack "astralcodexten" // rat // daily) # Scott Alexander
|
||||||
# (mkSubstack "doomberg" // tech // weekly) # articles are all pay-walled
|
|
||||||
(mkSubstack "eliqian" // rat // weekly)
|
(mkSubstack "eliqian" // rat // weekly)
|
||||||
(mkSubstack "oversharing" // pol // daily)
|
(mkSubstack "oversharing" // pol // daily)
|
||||||
(mkSubstack "samkriss" // humor // infrequent)
|
(mkSubstack "samkriss" // humor // infrequent)
|
||||||
(mkText "http://benjaminrosshoffman.com/feed" // pol // weekly)
|
(mkText "http://benjaminrosshoffman.com/feed" // pol // weekly)
|
||||||
(mkText "http://boginjr.com/feed" // tech // infrequent)
|
(mkText "http://boginjr.com/feed" // tech // infrequent)
|
||||||
(mkText "https://forum.merveilles.town/rss.xml" // pol // infrequent) #quality RSS list here: <https://forum.merveilles.town/thread/57/share-your-rss-feeds%21-6/>
|
(mkText "https://forum.merveilles.town/rss.xml" // pol // infrequent) #quality RSS list here: <https://forum.merveilles.town/thread/57/share-your-rss-feeds%21-6/>
|
||||||
# (mkText "https://github.com/Kaiteki-Fedi/Kaiteki/commits/master.atom" // tech // infrequent)
|
|
||||||
(mkText "https://jvns.ca/atom.xml" // tech // weekly) # Julia Evans
|
(mkText "https://jvns.ca/atom.xml" // tech // weekly) # Julia Evans
|
||||||
(mkText "https://linuxphoneapps.org/blog/atom.xml" // tech // infrequent)
|
(mkText "https://linuxphoneapps.org/blog/atom.xml" // tech // infrequent)
|
||||||
(mkText "https://nixos.org/blog/announcements-rss.xml" // tech // infrequent) # more nixos stuff here, but unclear how to subscribe: <https://nixos.org/blog/categories.html>
|
(mkText "https://nixos.org/blog/announcements-rss.xml" // tech // infrequent) # more nixos stuff here, but unclear how to subscribe: <https://nixos.org/blog/categories.html>
|
||||||
(mkText "https://nixos.org/blog/stories-rss.xml" // tech // weekly)
|
(mkText "https://nixos.org/blog/stories-rss.xml" // tech // weekly)
|
||||||
(mkText "https://solar.lowtechmagazine.com/posts/index.xml" // tech // weekly)
|
(mkText "https://solar.lowtechmagazine.com/posts/index.xml" // tech // weekly)
|
||||||
|
(mkText "https://www.stratechery.com/rss" // pol // weekly) # Ben Thompson
|
||||||
|
|
||||||
|
# (fromDb "balajis.com" // pol) # Balaji
|
||||||
|
# (fromDb "drewdevault.com" // tech)
|
||||||
|
# (fromDb "econlib.org" // pol)
|
||||||
|
# (fromDb "lesswrong.com" // rat)
|
||||||
|
# (fromDb "profectusmag.com" // pol) # some conservative/libertarian think tank
|
||||||
|
# (fromDb "thesideview.co" // uncat) # spiritual journal; RSS items are stubs
|
||||||
|
# (fromDb "theregister.com" // tech)
|
||||||
|
# (fromDb "vitalik.ca" // tech) # moved to vitalik.eth.limo
|
||||||
|
# (fromDb "webcurious.co.uk" // uncat) # link aggregator; defunct?
|
||||||
|
# (mkSubstack "doomberg" // tech // weekly) # articles are all pay-walled
|
||||||
|
# (mkText "https://github.com/Kaiteki-Fedi/Kaiteki/commits/master.atom" // tech // infrequent)
|
||||||
# (mkText "https://til.simonwillison.net/tils/feed.atom" // tech // weekly)
|
# (mkText "https://til.simonwillison.net/tils/feed.atom" // tech // weekly)
|
||||||
# (mkText "https://www.bloomberg.com/opinion/authors/ARbTQlRLRjE/matthew-s-levine.rss" // pol // weekly) # Matt Levine (preview/paywalled)
|
# (mkText "https://www.bloomberg.com/opinion/authors/ARbTQlRLRjE/matthew-s-levine.rss" // pol // weekly) # Matt Levine (preview/paywalled)
|
||||||
(mkText "https://www.stratechery.com/rss" // pol // weekly) # Ben Thompson
|
|
||||||
];
|
];
|
||||||
|
|
||||||
videos = [
|
videos = [
|
||||||
|
@ -221,18 +233,20 @@ let
|
||||||
(fromDb "youtube.com/@JackStauber")
|
(fromDb "youtube.com/@JackStauber")
|
||||||
(fromDb "youtube.com/@NativLang")
|
(fromDb "youtube.com/@NativLang")
|
||||||
(fromDb "youtube.com/@PolyMatter")
|
(fromDb "youtube.com/@PolyMatter")
|
||||||
# (fromDb "youtube.com/@rossmanngroup" // pol // tech) # Louis Rossmann
|
|
||||||
(fromDb "youtube.com/@TechnologyConnections" // tech)
|
(fromDb "youtube.com/@TechnologyConnections" // tech)
|
||||||
(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/@Vox")
|
||||||
(fromDb "youtube.com/@Vsauce")
|
(fromDb "youtube.com/@Vsauce")
|
||||||
|
|
||||||
|
# (fromDb "youtube.com/@rossmanngroup" // pol // tech) # Louis Rossmann
|
||||||
];
|
];
|
||||||
|
|
||||||
images = [
|
images = [
|
||||||
(fromDb "catandgirl.com" // img // humor)
|
(fromDb "catandgirl.com" // img // humor)
|
||||||
(fromDb "davidrevoy.com" // img // art)
|
(fromDb "davidrevoy.com" // img // art)
|
||||||
|
(fromDb "grumpy.website" // img // humor)
|
||||||
(fromDb "miniature-calendar.com" // img // art // daily)
|
(fromDb "miniature-calendar.com" // img // art // daily)
|
||||||
(fromDb "pbfcomics.com" // img // humor)
|
(fromDb "pbfcomics.com" // img // humor)
|
||||||
(fromDb "poorlydrawnlines.com/feed" // img // humor)
|
(fromDb "poorlydrawnlines.com/feed" // img // humor)
|
||||||
|
|
|
@ -107,7 +107,8 @@ let
|
||||||
ftp = common ++ fuseColin ++ [
|
ftp = common ++ fuseColin ++ [
|
||||||
# "ftpfs_debug=2"
|
# "ftpfs_debug=2"
|
||||||
"user=colin:ipauth"
|
"user=colin:ipauth"
|
||||||
"connect_timeout=10"
|
# connect_timeout=10: casting shows to T.V. fails partway through about half the time
|
||||||
|
"connect_timeout=20"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
remoteHome = host: {
|
remoteHome = host: {
|
||||||
|
@ -225,10 +226,10 @@ lib.mkMerge [
|
||||||
(remoteServo "media/Books")
|
(remoteServo "media/Books")
|
||||||
(remoteServo "media/collections")
|
(remoteServo "media/collections")
|
||||||
# (remoteServo "media/datasets")
|
# (remoteServo "media/datasets")
|
||||||
(remoteServo "media/freeleech")
|
|
||||||
(remoteServo "media/games")
|
(remoteServo "media/games")
|
||||||
(remoteServo "media/Music")
|
(remoteServo "media/Music")
|
||||||
(remoteServo "media/Pictures/macros")
|
(remoteServo "media/Pictures/macros")
|
||||||
|
(remoteServo "media/torrents")
|
||||||
(remoteServo "media/Videos")
|
(remoteServo "media/Videos")
|
||||||
(remoteServo "playground")
|
(remoteServo "playground")
|
||||||
]
|
]
|
||||||
|
|
|
@ -80,14 +80,12 @@
|
||||||
# - query details with `sudo cpupower frequency-info`
|
# - query details with `sudo cpupower frequency-info`
|
||||||
powerManagement.cpuFreqGovernor = "ondemand";
|
powerManagement.cpuFreqGovernor = "ondemand";
|
||||||
|
|
||||||
services.logind.extraConfig = ''
|
# see: `man logind.conf`
|
||||||
# see: `man logind.conf`
|
# don’t shutdown when power button is short-pressed (commonly done an accident, or by cats).
|
||||||
# don’t shutdown when power button is short-pressed (commonly done an accident, or by cats).
|
# but do on long-press: useful to gracefully power-off server.
|
||||||
# but do on long-press: useful to gracefully power-off server.
|
services.logind.powerKey = "lock";
|
||||||
HandlePowerKey=lock
|
services.logind.powerKeyLongPress = "poweroff";
|
||||||
HandlePowerKeyLongPress=poweroff
|
services.logind.lidSwitch = "lock";
|
||||||
HandleLidSwitch=lock
|
|
||||||
'';
|
|
||||||
|
|
||||||
# services.snapper.configs = {
|
# services.snapper.configs = {
|
||||||
# root = {
|
# root = {
|
||||||
|
|
|
@ -7,6 +7,17 @@
|
||||||
"usb_storage" # rpi needed this to boot from usb storage, i think.
|
"usb_storage" # rpi needed this to boot from usb storage, i think.
|
||||||
"nvme" # to boot from nvme devices
|
"nvme" # to boot from nvme devices
|
||||||
# efi_pstore evivars
|
# efi_pstore evivars
|
||||||
|
|
||||||
|
# added (speculatively) 2024/05/21; these were implicitly being added by nixos/modules/system/boot/kernel.nix
|
||||||
|
# i've copied not all of them, but most
|
||||||
|
"mmc_block"
|
||||||
|
"dm_mod"
|
||||||
|
# USB keyboards
|
||||||
|
"uhci_hcd" "ehci_hcd" "ehci_pci" "ohci_hcd" "ohci_pci" "xhci_hcd" "xhci_pci" "usbhid" "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" "hid_logitech_hidpp" "hid_logitech_dj" "hid_microsoft" "hid_cherry" "hid_corsair"
|
||||||
|
# x86 keyboard stuff
|
||||||
|
"pcips2" "atkbd" "i8042"
|
||||||
|
# stage-2 init needs rtc?
|
||||||
|
"rtc_cmos"
|
||||||
];
|
];
|
||||||
|
|
||||||
hardware.cpu.amd.updateMicrocode = true; # desktop
|
hardware.cpu.amd.updateMicrocode = true; # desktop
|
||||||
|
|
|
@ -50,7 +50,7 @@ let
|
||||||
localShareApplicationsPkg = (pkgs.symlinkJoin {
|
localShareApplicationsPkg = (pkgs.symlinkJoin {
|
||||||
name = "user-local-share-applications";
|
name = "user-local-share-applications";
|
||||||
paths = builtins.map
|
paths = builtins.map
|
||||||
(p: "${p.package}")
|
(p: builtins.toString p.package)
|
||||||
(enabledProgramsWithPackage ++ [ { package=mimeappsListPkg; } ]);
|
(enabledProgramsWithPackage ++ [ { package=mimeappsListPkg; } ]);
|
||||||
}).overrideAttrs (orig: {
|
}).overrideAttrs (orig: {
|
||||||
# like normal symlinkJoin, but don't error if the path doesn't exist
|
# like normal symlinkJoin, but don't error if the path doesn't exist
|
||||||
|
|
|
@ -3,11 +3,15 @@
|
||||||
{
|
{
|
||||||
# XDG defines things like ~/Desktop, ~/Downloads, etc.
|
# XDG defines things like ~/Desktop, ~/Downloads, etc.
|
||||||
# these clutter the home, so i mostly don't use them.
|
# these clutter the home, so i mostly don't use them.
|
||||||
|
# note that several of these are not actually standardized anywhere.
|
||||||
|
# some are even non-conventional, like:
|
||||||
|
# - XDG_PHOTOS_DIR: only works because i patch e.g. megapixels
|
||||||
sane.user.fs.".config/user-dirs.dirs".symlink.text = ''
|
sane.user.fs.".config/user-dirs.dirs".symlink.text = ''
|
||||||
XDG_DESKTOP_DIR="$HOME/.xdg/Desktop"
|
XDG_DESKTOP_DIR="$HOME/.xdg/Desktop"
|
||||||
XDG_DOCUMENTS_DIR="$HOME/dev"
|
XDG_DOCUMENTS_DIR="$HOME/dev"
|
||||||
XDG_DOWNLOAD_DIR="$HOME/tmp"
|
XDG_DOWNLOAD_DIR="$HOME/tmp"
|
||||||
XDG_MUSIC_DIR="$HOME/Music"
|
XDG_MUSIC_DIR="$HOME/Music"
|
||||||
|
XDG_PHOTOS_DIR="$HOME/Pictures/Photos"
|
||||||
XDG_PICTURES_DIR="$HOME/Pictures"
|
XDG_PICTURES_DIR="$HOME/Pictures"
|
||||||
XDG_PUBLICSHARE_DIR="$HOME/.xdg/Public"
|
XDG_PUBLICSHARE_DIR="$HOME/.xdg/Public"
|
||||||
XDG_SCREENSHOTS_DIR="$HOME/Pictures/Screenshots"
|
XDG_SCREENSHOTS_DIR="$HOME/Pictures/Screenshots"
|
||||||
|
@ -19,11 +23,5 @@
|
||||||
# see <https://manpages.ubuntu.com/manpages/bionic/man5/user-dirs.conf.5.html>
|
# see <https://manpages.ubuntu.com/manpages/bionic/man5/user-dirs.conf.5.html>
|
||||||
sane.user.fs.".config/user-dirs.conf".symlink.text = "enabled=False";
|
sane.user.fs.".config/user-dirs.conf".symlink.text = "enabled=False";
|
||||||
|
|
||||||
sane.user.fs.".profile".symlink.text = ''
|
sane.user.fs.".config/environment.d/30-user-dirs.conf".symlink.target = "../user-dirs.dirs";
|
||||||
# configure XDG_<type>_DIR preferences (e.g. for downloads, screenshots, etc)
|
|
||||||
# surround with `set -o allexport` since user-dirs.dirs doesn't `export` its vars
|
|
||||||
set -a
|
|
||||||
source $HOME/.config/user-dirs.dirs
|
|
||||||
set +a
|
|
||||||
'';
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
{ ... }:
|
{ ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
|
# partially supported in nixpkgs <repo:nixos/nixpkgs:nixos/modules/misc/ids.nix>
|
||||||
|
sane.ids.networkmanager.uid = 57; #< nixpkgs unofficially reserves this, to match networkmanager's gid
|
||||||
|
|
||||||
# legacy servo users, some are inconvenient to migrate
|
# legacy servo users, some are inconvenient to migrate
|
||||||
sane.ids.dhcpcd.gid = 991;
|
sane.ids.dhcpcd.gid = 991;
|
||||||
sane.ids.dhcpcd.uid = 992;
|
sane.ids.dhcpcd.uid = 992;
|
||||||
|
@ -18,7 +21,7 @@
|
||||||
sane.ids.matrix-appservice-irc.uid = 993;
|
sane.ids.matrix-appservice-irc.uid = 993;
|
||||||
sane.ids.matrix-appservice-irc.gid = 992;
|
sane.ids.matrix-appservice-irc.gid = 992;
|
||||||
|
|
||||||
# greetd (used by sway)
|
# greetd (legacy)
|
||||||
sane.ids.greeter.uid = 999;
|
sane.ids.greeter.uid = 999;
|
||||||
sane.ids.greeter.gid = 999;
|
sane.ids.greeter.gid = 999;
|
||||||
|
|
||||||
|
@ -78,6 +81,7 @@
|
||||||
|
|
||||||
# found on graphical hosts
|
# found on graphical hosts
|
||||||
sane.ids.nm-iodine.uid = 2101; # desko/moby/lappy
|
sane.ids.nm-iodine.uid = 2101; # desko/moby/lappy
|
||||||
|
sane.ids.seat.gid = 2102;
|
||||||
|
|
||||||
# found on desko host
|
# found on desko host
|
||||||
# from services.usbmuxd
|
# from services.usbmuxd
|
||||||
|
|
|
@ -60,8 +60,5 @@
|
||||||
networking.networkmanager.plugins = lib.mkForce [];
|
networking.networkmanager.plugins = lib.mkForce [];
|
||||||
|
|
||||||
# keyfile.path = where networkmanager should look for connection credentials
|
# keyfile.path = where networkmanager should look for connection credentials
|
||||||
networking.networkmanager.extraConfig = ''
|
networking.networkmanager.settings.keyfile.path = "/var/lib/NetworkManager/system-connections";
|
||||||
[keyfile]
|
|
||||||
path=/var/lib/NetworkManager/system-connections
|
|
||||||
'';
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
# things to consider when changing these parameters:
|
# things to consider when changing these parameters:
|
||||||
# - temporary VPN access (`sane-vpn up ...`)
|
# - temporary VPN access (`sane-vpn up ...`)
|
||||||
# - servo `ovpns` namespace (it *relies* on /etc/resolv.conf mentioning 127.0.0.53)
|
# - servo `ovpns` namespace (it *relies* on /etc/resolv.conf mentioning 127.0.0.53)
|
||||||
# - jails: `firejail --net=br-ovpnd-us --noprofile --dns=46.227.67.134 ping 1.1.1.1`
|
|
||||||
#
|
#
|
||||||
# components:
|
# components:
|
||||||
# - /etc/nsswitch.conf:
|
# - /etc/nsswitch.conf:
|
||||||
|
@ -18,17 +17,22 @@
|
||||||
# - modern implementations hardcodes `127.0.0.53` and then systemd-resolved proxies everything (and caches).
|
# - modern implementations hardcodes `127.0.0.53` and then systemd-resolved proxies everything (and caches).
|
||||||
#
|
#
|
||||||
# namespacing:
|
# namespacing:
|
||||||
# - each namespace can use a different /etc/resolv.conf to specify different DNS servers (see `firejail --dns=...`)
|
# - each namespace may use a different /etc/resolv.conf to specify different DNS servers
|
||||||
# - nscd breaks namespacing: the host nscd is unaware of the guest's /etc/resolv.conf, and so direct's the guest's DNS requests to the host's servers.
|
# - nscd breaks namespacing: the host nscd is unaware of the guest's /etc/resolv.conf, and so directs the guest's DNS requests to the host's servers.
|
||||||
# - this is fixed by either `firejail --blacklist=/var/run/nscd/socket`, or disabling nscd altogether.
|
# - this is fixed by either removing `/var/run/nscd/socket` from the namespace, or disabling nscd altogether.
|
||||||
{ lib, ... }:
|
{ config, lib, ... }:
|
||||||
|
lib.mkMerge [
|
||||||
{
|
{
|
||||||
|
sane.services.trust-dns.enable = lib.mkDefault config.sane.services.trust-dns.asSystemResolver;
|
||||||
|
sane.services.trust-dns.asSystemResolver = lib.mkDefault true;
|
||||||
|
}
|
||||||
|
(lib.mkIf (!config.sane.services.trust-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: rework servo's netns to use `firejail`, which is capable of spoofing /etc/resolv.conf.
|
# TODO: improve trust-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
|
||||||
|
@ -44,7 +48,8 @@
|
||||||
# stub resolver (just forwards upstream) lives on 127.0.0.54
|
# stub resolver (just forwards upstream) lives on 127.0.0.54
|
||||||
"127.0.0.53"
|
"127.0.0.53"
|
||||||
];
|
];
|
||||||
|
})
|
||||||
|
{
|
||||||
# nscd -- the Name Service Caching Daemon -- caches DNS query responses
|
# nscd -- the Name Service Caching Daemon -- caches DNS query responses
|
||||||
# in a way that's unaware of my VPN routing, so routes are frequently poor against
|
# in a way that's unaware of my VPN routing, so routes are frequently poor against
|
||||||
# services which advertise different IPs based on geolocation.
|
# services which advertise different IPs based on geolocation.
|
||||||
|
@ -65,3 +70,4 @@
|
||||||
services.nscd.enable = false;
|
services.nscd.enable = false;
|
||||||
system.nssModules = lib.mkForce [];
|
system.nssModules = lib.mkForce [];
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
|
|
@ -7,50 +7,62 @@
|
||||||
|
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
let
|
let
|
||||||
def-ovpn = name: { endpoint, publicKey, addrV4, id }: {
|
# N.B.: OVPN issues each key (i.e. device) a different IP (addrV4), and requires you use it.
|
||||||
sane.vpn."ovpnd-${name}" = {
|
# the IP it issues can be used to connect to any of their VPNs.
|
||||||
inherit endpoint publicKey addrV4 id;
|
# effectively the IP and key map 1-to-1.
|
||||||
privateKeyFile = config.sops.secrets."wg/ovpnd_${name}_privkey".path;
|
# it seems to still be possible to keep two active tunnels on one device, using the same key/IP address, though.
|
||||||
|
def-ovpn = name: { endpoint, publicKey, id }: let
|
||||||
|
inherit (config.sane.ovpn) addrV4;
|
||||||
|
in {
|
||||||
|
sane.vpn."ovpnd-${name}" = lib.mkIf (addrV4 != null) {
|
||||||
|
inherit addrV4 endpoint publicKey id;
|
||||||
|
privateKeyFile = config.sops.secrets."ovpn_privkey".path;
|
||||||
dns = [
|
dns = [
|
||||||
"46.227.67.134"
|
"46.227.67.134"
|
||||||
"192.165.9.158"
|
"192.165.9.158"
|
||||||
|
# "2a07:a880:4601:10f0:cd45::1"
|
||||||
|
# "2001:67c:750:1:cafe:cd45::1"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets."wg/ovpnd_${name}_privkey" = {
|
sops.secrets."ovpn_privkey" = lib.mkIf (addrV4 != null) {
|
||||||
# needs to be readable by systemd-network or else it says "Ignoring network device" and doesn't expose it to networkctl.
|
# needs to be readable by systemd-network or else it says "Ignoring network device" and doesn't expose it to networkctl.
|
||||||
owner = "systemd-network";
|
owner = "systemd-network";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in lib.mkMerge [
|
in {
|
||||||
(def-ovpn "us" {
|
options = with lib; {
|
||||||
endpoint = "vpn31.prd.losangeles.ovpn.com:9929";
|
sane.ovpn.addrV4 = mkOption {
|
||||||
publicKey = "VW6bEWMOlOneta1bf6YFE25N/oMGh1E1UFBCfyggd0k=";
|
type = types.nullOr types.str;
|
||||||
id = 1;
|
default = null;
|
||||||
addrV4 = "172.27.237.218";
|
description = ''
|
||||||
# addrV6 = "fd00:0000:1337:cafe:1111:1111:ab00:4c8f";
|
ovpn issues one IP address per device.
|
||||||
})
|
set `null` to disable OVPN for this host.
|
||||||
# TODO: us-atl disabled until i can give it a different link-local address and wireguard key than us-mi
|
'';
|
||||||
# (def-ovpn "us-atl" {
|
};
|
||||||
# endpoint = "vpn18.prd.atlanta.ovpn.com:9929";
|
};
|
||||||
# publicKey = "Dpg/4v5s9u0YbrXukfrMpkA+XQqKIFpf8ZFgyw0IkE0=";
|
|
||||||
# address = [
|
config = lib.mkMerge [
|
||||||
# "172.21.182.178/32"
|
(def-ovpn "us" {
|
||||||
# "fd00:0000:1337:cafe:1111:1111:cfcb:27e3/128"
|
endpoint = "vpn31.prd.losangeles.ovpn.com:9929";
|
||||||
# ];
|
publicKey = "VW6bEWMOlOneta1bf6YFE25N/oMGh1E1UFBCfyggd0k=";
|
||||||
# })
|
id = 1;
|
||||||
(def-ovpn "us-mi" {
|
})
|
||||||
endpoint = "vpn34.prd.miami.ovpn.com:9929";
|
(def-ovpn "us-mi" {
|
||||||
publicKey = "VtJz2irbu8mdkIQvzlsYhU+k9d55or9mx4A2a14t0V0=";
|
endpoint = "vpn34.prd.miami.ovpn.com:9929";
|
||||||
id = 2;
|
publicKey = "VtJz2irbu8mdkIQvzlsYhU+k9d55or9mx4A2a14t0V0=";
|
||||||
addrV4 = "172.21.182.178";
|
id = 2;
|
||||||
# addrV6 = "fd00:0000:1337:cafe:1111:1111:cfcb:27e3";
|
})
|
||||||
})
|
(def-ovpn "ukr" {
|
||||||
(def-ovpn "ukr" {
|
endpoint = "vpn96.prd.kyiv.ovpn.com:9929";
|
||||||
endpoint = "vpn96.prd.kyiv.ovpn.com:9929";
|
publicKey = "CjZcXDxaaKpW8b5As1EcNbI6+42A6BjWahwXDCwfVFg=";
|
||||||
publicKey = "CjZcXDxaaKpW8b5As1EcNbI6+42A6BjWahwXDCwfVFg=";
|
id = 3;
|
||||||
id = 3;
|
})
|
||||||
addrV4 = "172.18.180.159";
|
# TODO: us-atl disabled until i need it again, i guess.
|
||||||
# addrV6 = "fd00:0000:1337:cafe:1111:1111:ec5c:add3";
|
# (def-ovpn "us-atl" {
|
||||||
})
|
# endpoint = "vpn18.prd.atlanta.ovpn.com:9929";
|
||||||
]
|
# publicKey = "Dpg/4v5s9u0YbrXukfrMpkA+XQqKIFpf8ZFgyw0IkE0=";
|
||||||
|
# id = 4;
|
||||||
|
# })
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
|
|
||||||
# allow `nix-shell` (and probably nix-index?) to locate our patched and custom packages.
|
# allow `nix-shell` (and probably nix-index?) to locate our patched and custom packages.
|
||||||
# this is actually a no-op, and the real action happens in assigning `nix.settings.nix-path`.
|
# this is actually a no-op, and the real action happens in assigning `nix.settings.nix-path`.
|
||||||
nix.nixPath = (lib.optionals config.sane.enableSlowPrograms [
|
nix.nixPath = (lib.optionals (config.sane.maxBuildCost >= 2) [
|
||||||
"nixpkgs=${pkgs.path}"
|
"nixpkgs=${pkgs.path}"
|
||||||
]) ++ [
|
]) ++ [
|
||||||
# note the import starts at repo root: this allows `./overlay/default.nix` to access the stuff at the root
|
# note the import starts at repo root: this allows `./overlay/default.nix` to access the stuff at the root
|
||||||
|
@ -65,10 +65,10 @@
|
||||||
|
|
||||||
# ensure new deployments have a source of this repo with which they can bootstrap.
|
# ensure new deployments have a source of this repo with which they can bootstrap.
|
||||||
# this however changes on every commit and can be slow to copy for e.g. `moby`.
|
# this however changes on every commit and can be slow to copy for e.g. `moby`.
|
||||||
environment.etc."nixos" = lib.mkIf config.sane.enableSlowPrograms {
|
environment.etc."nixos" = lib.mkIf (config.sane.maxBuildCost >= 3) {
|
||||||
source = ../../..;
|
source = ../../..;
|
||||||
};
|
};
|
||||||
environment.etc."nix/registry.json" = lib.mkIf (!config.sane.enableSlowPrograms) {
|
environment.etc."nix/registry.json" = lib.mkIf (config.sane.maxBuildCost < 3) {
|
||||||
enable = false;
|
enable = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,72 +1,216 @@
|
||||||
# strictly *decrease* the scope of the default nixos installation/config
|
# strictly *decrease* the scope of the default nixos installation/config
|
||||||
|
|
||||||
{ lib, ... }:
|
{ lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
suidlessPam = pkgs.pam.overrideAttrs (upstream: {
|
||||||
|
# nixpkgs' pam hardcodes unix_chkpwd path to the /run/wrappers one,
|
||||||
|
# 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.
|
||||||
|
# TODO: add a `package` option to the nixos' pam module and substitute it that way.
|
||||||
|
postPatch = (if upstream.postPatch != null then upstream.postPatch else "") + ''
|
||||||
|
substituteInPlace modules/pam_unix/Makefile.am --replace-fail \
|
||||||
|
"/run/wrappers/bin/unix_chkpwd" "$out/bin/unix_chkpwd"
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
in
|
||||||
{
|
{
|
||||||
# disable non-required packages like nano, perl, rsync, strace
|
# remove a few items from /run/wrappers we don't need.
|
||||||
environment.defaultPackages = [];
|
options.security.wrappers = lib.mkOption {
|
||||||
|
apply = lib.filterAttrs (name: _: !(builtins.elem name [
|
||||||
|
# from <repo:nixos/nixpkgs:nixos/modules/security/polkit.nix>
|
||||||
|
"pkexec"
|
||||||
|
"polkit-agent-helper-1" #< used by systemd; without this you'll have to `sudo systemctl daemon-reload` instead of unauth'd `systemctl daemon-reload`
|
||||||
|
# from <repo:nixos/nixpkgs:nixos/modules/services/system/dbus.nix>
|
||||||
|
"dbus-daemon-launch-helper"
|
||||||
|
# from <repo:nixos/nixpkgs:nixos/modules/security/wrappers/default.nix>
|
||||||
|
"fusermount" #< only needed if you want to mount entries declared in /etc/fstab or mtab as unprivileged user
|
||||||
|
"fusermount3"
|
||||||
|
"mount" #< only needed if you want to mount entries declared in /etc/fstab or mtab as unprivileged user
|
||||||
|
"umount"
|
||||||
|
# from <repo:nixos/nixpkgs:nixos/modules/programs/shadow.nix>
|
||||||
|
"newgidmap"
|
||||||
|
"newgrp"
|
||||||
|
"newuidmap"
|
||||||
|
"sg"
|
||||||
|
"su"
|
||||||
|
# from: <repo:nixos/nixpkgs:nixos/modules/security/pam.nix>
|
||||||
|
# requires associated `pam` patch to not hardcode unix_chkpwd path
|
||||||
|
"unix_chkpwd"
|
||||||
|
]));
|
||||||
|
};
|
||||||
|
options.security.pam.services = lib.mkOption {
|
||||||
|
apply = services: let
|
||||||
|
filtered = lib.filterAttrs (name: _: !(builtins.elem name [
|
||||||
|
# from <repo:nixos/nixpkgs:nixos/modules/security/pam.nix>
|
||||||
|
"i3lock"
|
||||||
|
"i3lock-color"
|
||||||
|
"vlock"
|
||||||
|
"xlock"
|
||||||
|
"xscreensaver"
|
||||||
|
"runuser"
|
||||||
|
"runuser-l"
|
||||||
|
# from ??
|
||||||
|
"chfn"
|
||||||
|
"chpasswd"
|
||||||
|
"chsh"
|
||||||
|
"groupadd"
|
||||||
|
"groupdel"
|
||||||
|
"groupmems"
|
||||||
|
"groupmod"
|
||||||
|
"useradd"
|
||||||
|
"userdel"
|
||||||
|
"usermod"
|
||||||
|
# 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!
|
||||||
|
])) 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;
|
||||||
|
};
|
||||||
|
|
||||||
# remove all the non-existent default directories from XDG_DATA_DIRS, XDG_CONFIG_DIRS to simplify debugging.
|
options.environment.systemPackages = lib.mkOption {
|
||||||
# this is defaulted in <repo:nixos/nixpkgs:nixos/modules/programs/environment.nix>,
|
# see: <repo:nixos/nixpkgs:nixos/modules/config/system-path.nix>
|
||||||
# without being gated by any higher config.
|
# it's 31 "requiredPackages", with no explanation of why they're "required"...
|
||||||
environment.profiles = lib.mkForce [
|
# most of these can be safely removed without breaking the *boot*,
|
||||||
"/etc/profiles/per-user/$USER"
|
# but some core system services DO implicitly depend on them.
|
||||||
"/run/current-system/sw"
|
# TODO: see which more of these i can remove (or shadow/sandbox)
|
||||||
];
|
apply = let
|
||||||
|
requiredPackages = builtins.map (pkg: lib.setPrio ((pkg.meta.priority or 5) + 3) pkg) [
|
||||||
|
# pkgs.acl
|
||||||
|
# pkgs.attr
|
||||||
|
# pkgs.bashInteractive
|
||||||
|
# pkgs.bzip2
|
||||||
|
# pkgs.coreutils-full
|
||||||
|
# pkgs.cpio
|
||||||
|
# pkgs.curl
|
||||||
|
# pkgs.diffutils
|
||||||
|
# pkgs.findutils
|
||||||
|
# pkgs.gawk
|
||||||
|
# pkgs.stdenv.cc.libc
|
||||||
|
# pkgs.getent
|
||||||
|
# pkgs.getconf
|
||||||
|
# pkgs.gnugrep
|
||||||
|
# pkgs.gnupatch
|
||||||
|
# pkgs.gnused
|
||||||
|
# pkgs.gnutar
|
||||||
|
# pkgs.gzip
|
||||||
|
# pkgs.xz
|
||||||
|
pkgs.less
|
||||||
|
# pkgs.libcap #< implicitly required by NetworkManager/wpa_supplicant!
|
||||||
|
# pkgs.ncurses
|
||||||
|
pkgs.netcat
|
||||||
|
# config.programs.ssh.package
|
||||||
|
# pkgs.mkpasswd
|
||||||
|
pkgs.procps
|
||||||
|
# pkgs.su
|
||||||
|
# pkgs.time
|
||||||
|
# pkgs.util-linux
|
||||||
|
# pkgs.which
|
||||||
|
# pkgs.zstd
|
||||||
|
];
|
||||||
|
in lib.filter (p: ! builtins.elem p requiredPackages);
|
||||||
|
};
|
||||||
|
|
||||||
# NIXPKGS_CONFIG defaults to "/etc/nix/nixpkgs-config.nix" in <nixos/modules/programs/environment.nix>.
|
options.system.fsPackages = lib.mkOption {
|
||||||
# that's never existed on my system and everything does fine without it set empty (no nixpkgs API to forcibly *unset* it).
|
# <repo:nixos/nixpkgs:nixos/modules/tasks/filesystems/vfat.nix> adds `mtools` and `dosfstools`
|
||||||
environment.variables.NIXPKGS_CONFIG = lib.mkForce "";
|
# dosfstools actually makes its way into the initrd (`fsck.vfat`).
|
||||||
# XDG_CONFIG_DIRS defaults to "/etc/xdg", which doesn't exist.
|
# mtools is like "MS-DOS for Linux", ancient functionality i'll never use.
|
||||||
# in practice, pam appends the values i want to XDG_CONFIG_DIRS, though this approach causes an extra leading `:`
|
apply = lib.filter (p: p != pkgs.mtools);
|
||||||
environment.sessionVariables.XDG_CONFIG_DIRS = lib.mkForce [];
|
};
|
||||||
# XCURSOR_PATH: defaults to `[ "$HOME/.icons" "$HOME/.local/share/icons" ]`, neither of which i use, just adding noise.
|
|
||||||
# see: <repo:nixos/nixpkgs:nixos/modules/config/xdg/icons.nix>
|
|
||||||
environment.sessionVariables.XCURSOR_PATH = lib.mkForce [];
|
|
||||||
|
|
||||||
# disable nixos' portal module, otherwise /share/applications gets linked into the system and complicates things (sandboxing).
|
config = {
|
||||||
# instead, i manage portals myself via the sane.programs API (e.g. sane.programs.xdg-desktop-portal).
|
# disable non-required packages like nano, perl, rsync, strace
|
||||||
xdg.portal.enable = false;
|
environment.defaultPackages = [];
|
||||||
xdg.menus.enable = false; #< links /share/applications, and a bunch of other empty (i.e. unused) dirs
|
|
||||||
|
|
||||||
# xdg.autostart.enable defaults to true, and links /etc/xdg/autostart into the environment, populated with .desktop files.
|
# remove all the non-existent default directories from XDG_DATA_DIRS, XDG_CONFIG_DIRS to simplify debugging.
|
||||||
# see: <repo:nixos/nixpkgs:nixos/modules/config/xdg/autostart.nix>
|
# this is defaulted in <repo:nixos/nixpkgs:nixos/modules/programs/environment.nix>,
|
||||||
# .desktop files are a questionable way to autostart things: i generally prefer a service manager for that.
|
# without being gated by any higher config.
|
||||||
xdg.autostart.enable = false;
|
environment.profiles = lib.mkForce [
|
||||||
|
"/etc/profiles/per-user/$USER"
|
||||||
|
"/run/current-system/sw"
|
||||||
|
];
|
||||||
|
|
||||||
# nix.channel.enable: populates `/nix/var/nix/profiles/per-user/root/channels`, `/root/.nix-channels`, `$HOME/.nix-defexpr/channels`
|
# NIXPKGS_CONFIG defaults to "/etc/nix/nixpkgs-config.nix" in <nixos/modules/programs/environment.nix>.
|
||||||
# <repo:nixos/nixpkgs:nixos/modules/config/nix-channel.nix>
|
# that's never existed on my system and everything does fine without it set empty (no nixpkgs API to forcibly *unset* it).
|
||||||
# TODO: may want to recreate NIX_PATH, nix.settings.nix-path
|
environment.variables.NIXPKGS_CONFIG = lib.mkForce "";
|
||||||
nix.channel.enable = false;
|
# XDG_CONFIG_DIRS defaults to "/etc/xdg", which doesn't exist.
|
||||||
|
# in practice, pam appends the values i want to XDG_CONFIG_DIRS, though this approach causes an extra leading `:`
|
||||||
|
environment.sessionVariables.XDG_CONFIG_DIRS = lib.mkForce [];
|
||||||
|
# XCURSOR_PATH: defaults to `[ "$HOME/.icons" "$HOME/.local/share/icons" ]`, neither of which i use, just adding noise.
|
||||||
|
# see: <repo:nixos/nixpkgs:nixos/modules/config/xdg/icons.nix>
|
||||||
|
environment.sessionVariables.XCURSOR_PATH = lib.mkForce [];
|
||||||
|
|
||||||
# environment.stub-ld: populate /lib/ld-linux.so with an object that unconditionally errors on launch,
|
# disable nixos' portal module, otherwise /share/applications gets linked into the system and complicates things (sandboxing).
|
||||||
# so as to inform when trying to run a non-nixos binary?
|
# instead, i manage portals myself via the sane.programs API (e.g. sane.programs.xdg-desktop-portal).
|
||||||
# IMO that's confusing: i thought /lib/ld-linux.so was some file actually required by nix.
|
xdg.portal.enable = false;
|
||||||
environment.stub-ld.enable = false;
|
xdg.menus.enable = false; #< links /share/applications, and a bunch of other empty (i.e. unused) dirs
|
||||||
|
|
||||||
# `less.enable` sets LESSKEYIN_SYSTEM, LESSOPEN, LESSCLOSE env vars, which does confusing "lesspipe" things, so disable that.
|
# xdg.autostart.enable defaults to true, and links /etc/xdg/autostart into the environment, populated with .desktop files.
|
||||||
# it's enabled by default from `<nixos/modules/programs/environment.nix>`, who also sets `PAGER="less"` and `EDITOR="nano"` (keep).
|
# see: <repo:nixos/nixpkgs:nixos/modules/config/xdg/autostart.nix>
|
||||||
programs.less.enable = lib.mkForce false;
|
# .desktop files are a questionable way to autostart things: i generally prefer a service manager for that.
|
||||||
environment.variables.PAGER = lib.mkOverride 900 ""; # mkDefault sets 1000. non-override is 100. 900 will beat the nixpkgs `mkDefault` but not anyone else.
|
xdg.autostart.enable = false;
|
||||||
environment.variables.EDITOR = lib.mkOverride 900 "";
|
|
||||||
|
|
||||||
# several packages (dconf, modemmanager, networkmanager, gvfs, polkit, udisks, bluez/blueman, feedbackd, etc)
|
# nix.channel.enable: populates `/nix/var/nix/profiles/per-user/root/channels`, `/root/.nix-channels`, `$HOME/.nix-defexpr/channels`
|
||||||
# will add themselves to the dbus search path.
|
# <repo:nixos/nixpkgs:nixos/modules/config/nix-channel.nix>
|
||||||
# i prefer dbus to only search XDG paths (/share/dbus-1) for service files, as that's more introspectable.
|
# TODO: may want to recreate NIX_PATH, nix.settings.nix-path
|
||||||
# see: <repo:nixos/nixpkgs:nixos/modules/services/system/dbus.nix>
|
nix.channel.enable = false;
|
||||||
# TODO: sandbox dbus? i pretty explicitly don't want to use it as a launcher.
|
|
||||||
services.dbus.packages = lib.mkForce [
|
|
||||||
"/run/current-system/sw"
|
|
||||||
# config.system.path
|
|
||||||
# pkgs.dbus
|
|
||||||
# pkgs.polkit.out
|
|
||||||
# pkgs.modemmanager
|
|
||||||
# pkgs.networkmanager
|
|
||||||
# pkgs.udisks
|
|
||||||
# pkgs.wpa_supplicant
|
|
||||||
];
|
|
||||||
|
|
||||||
# systemd by default forces shitty defaults for e.g. /tmp/.X11-unix.
|
# environment.stub-ld: populate /lib/ld-linux.so with an object that unconditionally errors on launch,
|
||||||
# nixos propagates those in: <nixos/modules/system/boot/systemd/tmpfiles.nix>
|
# so as to inform when trying to run a non-nixos binary?
|
||||||
# by overwriting this with an empty file, we can effectively remove it.
|
# IMO that's confusing: i thought /lib/ld-linux.so was some file actually required by nix.
|
||||||
environment.etc."tmpfiles.d/x11.conf".text = "# (removed by Colin)";
|
environment.stub-ld.enable = false;
|
||||||
|
|
||||||
|
# `less.enable` sets LESSKEYIN_SYSTEM, LESSOPEN, LESSCLOSE env vars, which does confusing "lesspipe" things, so disable that.
|
||||||
|
# it's enabled by default from `<nixos/modules/programs/environment.nix>`, who also sets `PAGER="less"` and `EDITOR="nano"` (keep).
|
||||||
|
programs.less.enable = lib.mkForce false;
|
||||||
|
environment.variables.PAGER = lib.mkOverride 900 ""; # mkDefault sets 1000. non-override is 100. 900 will beat the nixpkgs `mkDefault` but not anyone else.
|
||||||
|
environment.variables.EDITOR = lib.mkOverride 900 "";
|
||||||
|
|
||||||
|
# several packages (dconf, modemmanager, networkmanager, gvfs, polkit, udisks, bluez/blueman, feedbackd, etc)
|
||||||
|
# will add themselves to the dbus search path.
|
||||||
|
# i prefer dbus to only search XDG paths (/share/dbus-1) for service files, as that's more introspectable.
|
||||||
|
# see: <repo:nixos/nixpkgs:nixos/modules/services/system/dbus.nix>
|
||||||
|
# TODO: sandbox dbus? i pretty explicitly don't want to use it as a launcher.
|
||||||
|
services.dbus.packages = lib.mkForce [
|
||||||
|
"/run/current-system/sw"
|
||||||
|
# config.system.path
|
||||||
|
# pkgs.dbus
|
||||||
|
# pkgs.polkit.out
|
||||||
|
# pkgs.modemmanager
|
||||||
|
# pkgs.networkmanager
|
||||||
|
# pkgs.udisks
|
||||||
|
# pkgs.wpa_supplicant
|
||||||
|
];
|
||||||
|
|
||||||
|
# systemd by default forces shitty defaults for e.g. /tmp/.X11-unix.
|
||||||
|
# nixos propagates those in: <nixos/modules/system/boot/systemd/tmpfiles.nix>
|
||||||
|
# by overwriting this with an empty file, we can effectively remove it.
|
||||||
|
environment.etc."tmpfiles.d/x11.conf".text = "# (removed by Colin)";
|
||||||
|
|
||||||
|
# see: <nixos/modules/tasks/swraid.nix>
|
||||||
|
# it was enabled by default before 23.11
|
||||||
|
boot.swraid.enable = lib.mkDefault false;
|
||||||
|
|
||||||
|
# see: <nixos/modules/tasks/bcache.nix>
|
||||||
|
# these allow you to use the Linux block cache (cool! doesn't need to be a default though)
|
||||||
|
boot.bcache.enable = lib.mkDefault false;
|
||||||
|
|
||||||
|
# see: <nixos/modules/system/boot/kernel.nix>
|
||||||
|
# by default, it adds to boot.initrd.availableKernelModules:
|
||||||
|
# - SATA: "ahci" "sata_nv" "sata_via" "sata_sis" "sata_uli" "ata_piix" "pata_marvell"
|
||||||
|
# - "nvme"
|
||||||
|
# - scsi: "sd_mod" "sr_mod"
|
||||||
|
# - SD/eMMC: "mmc_block"
|
||||||
|
# - USB keyboards: "uhci_hcd" "ehci_hcd" "ehci_pci" "ohci_hcd" "ohci_pci" "xhci_hcd" "xhci_pci" "usbhid" "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" "hid_logitech_hidpp" "hid_logitech_dj" "hid_microsoft" "hid_cherry" "hid_corsair"
|
||||||
|
# - LVM: "dm_mod"
|
||||||
|
# - on x86 only: more keyboard stuff: "pcips2" "atkbd" "i8042"
|
||||||
|
|
||||||
|
boot.initrd.includeDefaultModules = lib.mkDefault false;
|
||||||
|
|
||||||
|
# see: <repo:nixos/nixpkgs:nixos/modules/virtualisation/nixos-containers.nix>
|
||||||
|
boot.enableContainers = lib.mkDefault false;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,39 +15,33 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
# upstream alsa ships with PinePhone audio configs, but they don't actually produce sound.
|
# upstream alsa ships with PinePhone audio configs, but they don't actually produce sound.
|
||||||
# see: <https://github.com/alsa-project/alsa-ucm-conf/pull/134>
|
# - still true as of 2024-05-26
|
||||||
# these audio files come from some revision of:
|
# - see: <https://github.com/alsa-project/alsa-ucm-conf/pull/134>
|
||||||
# - <https://gitlab.manjaro.org/manjaro-arm/packages/community/phosh/alsa-ucm-pinephone>
|
|
||||||
#
|
#
|
||||||
# alternative to patching is to plumb `ALSA_CONFIG_UCM2 = "${./ucm2}"` environment variable into the relevant places
|
# we can substitute working UCM conf in two ways:
|
||||||
# e.g. `systemd.services.pulseaudio.environment`.
|
# 1. nixpkgs' override for the `alsa-ucm-conf` package
|
||||||
# that leaves more opportunity for gaps (i.e. missing a service),
|
# - that forces a rebuild of ~500 packages (including webkitgtk).
|
||||||
# on the other hand this method causes about 500 packages to be rebuilt (including qt5 and webkitgtk).
|
# 2. set ALSA_CONFIG_UCM2 = /path/to/ucm2 in the relevant places
|
||||||
|
# - e.g. pulsewire service.
|
||||||
|
# - easy to miss places, though.
|
||||||
#
|
#
|
||||||
# note that with these files, the following audio device support:
|
# alsa-ucm-pinephone-manjaro (2024-05-26):
|
||||||
# - headphones work.
|
# - headphones work
|
||||||
# - "internal earpiece" works.
|
# - "internal earpiece" works
|
||||||
# - "internal speaker" doesn't work (but that's probably because i broke the ribbon cable)
|
# - "internal speaker" is silent (maybe hardware issue)
|
||||||
# - "analog output" doesn't work.
|
# - 3.5mm connection is flapping when playing to my car, which eventually breaks audio and requires restarting wireplumber
|
||||||
packageUnwrapped = pkgs.alsa-ucm-conf.overrideAttrs (upstream: {
|
# packageUnwrapped = pkgs.alsa-ucm-pinephone-manjaro.override {
|
||||||
postPatch = (upstream.postPatch or "") + ''
|
# inherit (cfg.config) preferEarpiece;
|
||||||
cp ${./ucm2/PinePhone}/* ucm2/Allwinner/A64/PinePhone/
|
# };
|
||||||
|
# alsa-ucm-pinephone-pmos (2024-05-26):
|
||||||
|
# - headphones work
|
||||||
|
# - "internal earpiece" works
|
||||||
|
# - "internal speaker" is silent (maybe hardware issue)
|
||||||
|
packageUnwrapped = pkgs.alsa-ucm-pinephone-pmos.override {
|
||||||
|
inherit (cfg.config) preferEarpiece;
|
||||||
|
};
|
||||||
|
|
||||||
# fix the self-contained ucm files i source from to have correct path within the alsa-ucm-conf source tree
|
sandbox.enable = false; #< only provides $out/share/alsa
|
||||||
substituteInPlace ucm2/Allwinner/A64/PinePhone/PinePhone.conf \
|
|
||||||
--replace-fail 'HiFi.conf' '/Allwinner/A64/PinePhone/HiFi.conf'
|
|
||||||
substituteInPlace ucm2/Allwinner/A64/PinePhone/PinePhone.conf \
|
|
||||||
--replace-fail 'VoiceCall.conf' '/Allwinner/A64/PinePhone/VoiceCall.conf'
|
|
||||||
'' + lib.optionalString cfg.config.preferEarpiece ''
|
|
||||||
# decrease the priority of the internal speaker so that sounds are routed
|
|
||||||
# to the earpiece by default.
|
|
||||||
# this is just personal preference.
|
|
||||||
substituteInPlace ucm2/Allwinner/A64/PinePhone/{HiFi.conf,VoiceCall.conf} \
|
|
||||||
--replace-fail 'PlaybackPriority 300' 'PlaybackPriority 100'
|
|
||||||
'';
|
|
||||||
});
|
|
||||||
|
|
||||||
sandbox.enable = false; #< only provides #out/share/alsa
|
|
||||||
|
|
||||||
# alsa-lib package only looks in its $out/share/alsa to find runtime config data, by default.
|
# alsa-lib package only looks in its $out/share/alsa to find runtime config data, by default.
|
||||||
# but ALSA_CONFIG_UCM2 is an env var that can override that.
|
# but ALSA_CONFIG_UCM2 is an env var that can override that.
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
buildCost = 1;
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ in
|
||||||
];
|
];
|
||||||
|
|
||||||
sysadminUtils = declPackageSet [
|
sysadminUtils = declPackageSet [
|
||||||
|
"ausyscall"
|
||||||
"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
|
||||||
|
@ -43,6 +44,7 @@ in
|
||||||
"dtc" # device tree [de]compiler
|
"dtc" # device tree [de]compiler
|
||||||
"e2fsprogs" # resize2fs
|
"e2fsprogs" # resize2fs
|
||||||
"efibootmgr"
|
"efibootmgr"
|
||||||
|
"errno"
|
||||||
"ethtool"
|
"ethtool"
|
||||||
"fatresize"
|
"fatresize"
|
||||||
"fd"
|
"fd"
|
||||||
|
@ -63,8 +65,11 @@ in
|
||||||
"jq"
|
"jq"
|
||||||
"killall"
|
"killall"
|
||||||
"less"
|
"less"
|
||||||
|
"lftp"
|
||||||
# "libcap_ng" # for `netcap`
|
# "libcap_ng" # for `netcap`
|
||||||
"lsof"
|
"lsof"
|
||||||
|
"man-pages"
|
||||||
|
"man-pages-posix"
|
||||||
# "miniupnpc"
|
# "miniupnpc"
|
||||||
"nano"
|
"nano"
|
||||||
# "ncdu" # ncurses disk usage. doesn't cross compile (zig)
|
# "ncdu" # ncurses disk usage. doesn't cross compile (zig)
|
||||||
|
@ -89,6 +94,7 @@ in
|
||||||
"tree"
|
"tree"
|
||||||
"usbutils" # lsusb
|
"usbutils" # lsusb
|
||||||
"util-linux" # lsblk, lscpu, etc
|
"util-linux" # lsblk, lscpu, etc
|
||||||
|
"valgrind"
|
||||||
"wget"
|
"wget"
|
||||||
"wirelesstools" # iwlist
|
"wirelesstools" # iwlist
|
||||||
# "xq" # jq for XML
|
# "xq" # jq for XML
|
||||||
|
@ -108,7 +114,6 @@ in
|
||||||
# - debugging?
|
# - debugging?
|
||||||
consoleUtils = declPackageSet [
|
consoleUtils = declPackageSet [
|
||||||
"alsaUtils" # for aplay, speaker-test
|
"alsaUtils" # for aplay, speaker-test
|
||||||
"strings"
|
|
||||||
# "cdrtools"
|
# "cdrtools"
|
||||||
# "clinfo"
|
# "clinfo"
|
||||||
# "dmidecode"
|
# "dmidecode"
|
||||||
|
@ -137,6 +142,7 @@ in
|
||||||
"nmon"
|
"nmon"
|
||||||
# "node2nix"
|
# "node2nix"
|
||||||
# "oathToolkit" # for oathtool
|
# "oathToolkit" # for oathtool
|
||||||
|
"objdump"
|
||||||
# "ponymix"
|
# "ponymix"
|
||||||
"pulsemixer"
|
"pulsemixer"
|
||||||
"python3-repl"
|
"python3-repl"
|
||||||
|
@ -149,6 +155,7 @@ in
|
||||||
"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"
|
||||||
# "ssh-to-age"
|
# "ssh-to-age"
|
||||||
|
"strings"
|
||||||
"sudo"
|
"sudo"
|
||||||
# "tageditor" # music tagging
|
# "tageditor" # music tagging
|
||||||
# "unar"
|
# "unar"
|
||||||
|
@ -173,6 +180,7 @@ in
|
||||||
"ffmpeg"
|
"ffmpeg"
|
||||||
"go2tv" # cast videos to UPNP/DLNA device (i.e. tv).
|
"go2tv" # cast videos to UPNP/DLNA device (i.e. tv).
|
||||||
"imagemagick"
|
"imagemagick"
|
||||||
|
"sane-cast" # cast videos to UPNP/DLNA, with compatibility
|
||||||
"sox"
|
"sox"
|
||||||
"yt-dlp"
|
"yt-dlp"
|
||||||
];
|
];
|
||||||
|
@ -203,6 +211,175 @@ in
|
||||||
# "tree-sitter"
|
# "tree-sitter"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
gameApps = declPackageSet [
|
||||||
|
"animatch"
|
||||||
|
"gnome-2048"
|
||||||
|
"gnome.hitori" # like sudoku
|
||||||
|
];
|
||||||
|
|
||||||
|
pcGameApps = declPackageSet [
|
||||||
|
# "andyetitmoves" # TODO: fix build!
|
||||||
|
# "armagetronad" # tron/lightcycles; WAN and LAN multiplayer
|
||||||
|
"celeste64"
|
||||||
|
# "cutemaze" # meh: trivial maze game; qt6 and keyboard-only
|
||||||
|
# "cuyo" # trivial puyo-puyo clone
|
||||||
|
"endless-sky" # space merchantilism/exploration
|
||||||
|
# "factorio"
|
||||||
|
"frozen-bubble" # WAN + LAN + 1P/2P bubble bobble
|
||||||
|
"hase" # WAN worms game
|
||||||
|
# "hedgewars" # WAN + LAN worms game (5~10 people online at any moment; <https://hedgewars.org>)
|
||||||
|
# "libremines" # meh: trivial minesweeper; qt6
|
||||||
|
# "mario0" # SMB + portal
|
||||||
|
# "mindustry"
|
||||||
|
# "minesweep-rs" # CLI minesweeper
|
||||||
|
# "nethack"
|
||||||
|
# "osu-lazer"
|
||||||
|
# "pinball" # 3d pinball; kb/mouse. old sourceforge project
|
||||||
|
# "powermanga" # STYLISH space invaders derivative (keyboard-only)
|
||||||
|
"shattered-pixel-dungeon" # doesn't cross compile
|
||||||
|
"space-cadet-pinball" # LMB/RMB controls (bindable though. volume buttons?)
|
||||||
|
"superTux" # keyboard-only controls
|
||||||
|
"superTuxKart" # poor FPS on pinephone
|
||||||
|
"tumiki-fighters" # keyboard-only
|
||||||
|
"vvvvvv" # keyboard-only controls
|
||||||
|
# "wine"
|
||||||
|
];
|
||||||
|
|
||||||
|
guiApps = declPackageSet [
|
||||||
|
# package sets
|
||||||
|
"gameApps"
|
||||||
|
"guiBaseApps"
|
||||||
|
];
|
||||||
|
|
||||||
|
guiBaseApps = declPackageSet [
|
||||||
|
# "abaddon" # discord client
|
||||||
|
"alacritty" # terminal emulator
|
||||||
|
"calls" # gnome calls (dialer/handler)
|
||||||
|
"dbus"
|
||||||
|
"dconf" # required by many packages, but not well-documented :(
|
||||||
|
# "delfin" # Jellyfin client
|
||||||
|
"dialect" # language translation
|
||||||
|
"dino" # XMPP client
|
||||||
|
"dissent" # Discord client (formerly known as: gtkcord4)
|
||||||
|
# "emote"
|
||||||
|
# "evince" # PDF viewer
|
||||||
|
# "flare-signal" # gtk4 signal client
|
||||||
|
# "foliate" # e-book reader
|
||||||
|
"fractal" # matrix client
|
||||||
|
"g4music" # local music player
|
||||||
|
# "gnome.cheese"
|
||||||
|
# "gnome-feeds" # RSS reader (with claimed mobile support)
|
||||||
|
# "gnome.file-roller"
|
||||||
|
"gnome.geary" # adaptive e-mail client; uses webkitgtk 4.1
|
||||||
|
"gnome.gnome-calculator"
|
||||||
|
"gnome.gnome-calendar"
|
||||||
|
"gnome.gnome-clocks"
|
||||||
|
"gnome.gnome-maps"
|
||||||
|
# "gnome-podcasts"
|
||||||
|
# "gnome.gnome-system-monitor"
|
||||||
|
# "gnome.gnome-terminal" # works on phosh
|
||||||
|
"gnome.gnome-weather"
|
||||||
|
# "gnome.seahorse" # keyring/secret manager
|
||||||
|
"gnome-frog" # OCR/QR decoder
|
||||||
|
"gpodder"
|
||||||
|
"gst-device-monitor" # for debugging audio/video
|
||||||
|
# "gthumb"
|
||||||
|
# "lemoa" # lemmy app
|
||||||
|
"libcamera" # for `cam` binary (useful for debugging cameras)
|
||||||
|
"libnotify" # for notify-send; debugging
|
||||||
|
# "lollypop"
|
||||||
|
"loupe" # image viewer
|
||||||
|
"mate.engrampa" # archive manager
|
||||||
|
"mepo" # maps viewer
|
||||||
|
"mpv"
|
||||||
|
"networkmanagerapplet" # for nm-connection-editor: it's better than not having any gui!
|
||||||
|
"ntfy-sh" # notification service
|
||||||
|
# "newsflash" # RSS viewer
|
||||||
|
"pavucontrol"
|
||||||
|
"pwvucontrol" # pipewire version of pavu
|
||||||
|
# "picard" # music tagging
|
||||||
|
# "libsForQt5.plasmatube" # Youtube player
|
||||||
|
"signal-desktop"
|
||||||
|
"snapshot" # camera app
|
||||||
|
"spot" # Gnome Spotify client
|
||||||
|
# "sublime-music"
|
||||||
|
# "tdesktop" # broken on phosh
|
||||||
|
# "tokodon"
|
||||||
|
"tuba" # mastodon/pleroma client (stores pw in keyring)
|
||||||
|
"vulkan-tools" # vulkaninfo
|
||||||
|
# "whalebird" # pleroma client (Electron). input is broken on phosh.
|
||||||
|
"xdg-terminal-exec"
|
||||||
|
"zathura" # PDF/CBZ/ePUB viewer
|
||||||
|
];
|
||||||
|
|
||||||
|
handheldGuiApps = declPackageSet [
|
||||||
|
# "celluloid" # mpv frontend
|
||||||
|
# "chatty" # matrix/xmpp/irc client (2023/12/29: disabled because broken cross build)
|
||||||
|
"cozy" # audiobook player
|
||||||
|
"epiphany" # gnome's web browser
|
||||||
|
# "iotas" # note taking app
|
||||||
|
"komikku"
|
||||||
|
"koreader"
|
||||||
|
"megapixels" # camera app
|
||||||
|
"notejot" # note taking, e.g. shopping list
|
||||||
|
"planify" # todo-tracker/planner
|
||||||
|
"portfolio-filemanager"
|
||||||
|
"tangram" # web browser
|
||||||
|
"wike" # Wikipedia Reader
|
||||||
|
"xarchiver" # archiver, backup option for when engrampa UI overflows screen and is unusale (xarchiver UI fails in different ways)
|
||||||
|
];
|
||||||
|
|
||||||
|
pcGuiApps = declPackageSet [
|
||||||
|
# package sets
|
||||||
|
"pcGameApps"
|
||||||
|
"pcTuiApps"
|
||||||
|
####
|
||||||
|
"audacity"
|
||||||
|
# "blanket" # ambient noise generator
|
||||||
|
"brave" # for the integrated wallet -- as a backup
|
||||||
|
# "cantata" # music player (mpd frontend)
|
||||||
|
# "chromium" # chromium takes hours to build. brave is chromium-based, distributed in binary form, so prefer it.
|
||||||
|
# "cups"
|
||||||
|
"discord" # x86-only
|
||||||
|
"electrum"
|
||||||
|
"element-desktop"
|
||||||
|
"firefox"
|
||||||
|
"font-manager"
|
||||||
|
# "gajim" # XMPP client. cross build tries to import host gobject-introspection types (2023/09/01)
|
||||||
|
"gimp" # broken on phosh
|
||||||
|
# "gnome.dconf-editor"
|
||||||
|
# "gnome.file-roller"
|
||||||
|
"gnome.gnome-disk-utility"
|
||||||
|
"gnome.nautilus" # file browser
|
||||||
|
# "gnome.totem" # video player, supposedly supports UPnP
|
||||||
|
"handbrake"
|
||||||
|
"inkscape"
|
||||||
|
# "jellyfin-media-player"
|
||||||
|
"kdenlive"
|
||||||
|
# "kid3" # audio tagging
|
||||||
|
"krita"
|
||||||
|
"libreoffice" # TODO: replace with an office suite that uses saner packaging?
|
||||||
|
"losslesscut-bin" # x86-only
|
||||||
|
# "makemkv" # x86-only
|
||||||
|
# "monero-gui" # x86-only
|
||||||
|
# "mumble"
|
||||||
|
# "nheko" # Matrix chat client
|
||||||
|
# "nicotine-plus" # soulseek client. before re-enabling this make sure it's properly sandboxed!
|
||||||
|
# "obsidian"
|
||||||
|
# "openscad" # 3d modeling
|
||||||
|
# "rhythmbox" # local music player
|
||||||
|
# "slic3r"
|
||||||
|
"soundconverter"
|
||||||
|
"spotify" # x86-only
|
||||||
|
"steam"
|
||||||
|
"tor-browser" # x86-only
|
||||||
|
# "vlc"
|
||||||
|
"wireshark" # could maybe ship the cli as sysadmin pkg
|
||||||
|
# "xterm" # requires Xwayland
|
||||||
|
# "zecwallet-lite" # x86-only
|
||||||
|
# "zulip"
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
# INDIVIDUAL PACKAGE DEFINITIONS
|
# INDIVIDUAL PACKAGE DEFINITIONS
|
||||||
|
|
||||||
|
@ -211,6 +388,7 @@ in
|
||||||
|
|
||||||
backblaze-b2 = {};
|
backblaze-b2 = {};
|
||||||
|
|
||||||
|
blanket.buildCost = 1;
|
||||||
blanket.sandbox.method = "bwrap";
|
blanket.sandbox.method = "bwrap";
|
||||||
blanket.sandbox.whitelistAudio = true;
|
blanket.sandbox.whitelistAudio = true;
|
||||||
# blanket.sandbox.whitelistDbus = [ "user" ]; # TODO: untested
|
# blanket.sandbox.whitelistDbus = [ "user" ]; # TODO: untested
|
||||||
|
@ -229,14 +407,6 @@ in
|
||||||
bridge-utils.sandbox.method = "bwrap"; #< bwrap, landlock: both work
|
bridge-utils.sandbox.method = "bwrap"; #< bwrap, landlock: both work
|
||||||
bridge-utils.sandbox.net = "all";
|
bridge-utils.sandbox.net = "all";
|
||||||
|
|
||||||
brightnessctl.sandbox.method = "landlock"; # also bwrap, but landlock is more responsive
|
|
||||||
brightnessctl.sandbox.extraPaths = [
|
|
||||||
"/sys/class/backlight"
|
|
||||||
"/sys/class/leds"
|
|
||||||
"/sys/devices"
|
|
||||||
];
|
|
||||||
brightnessctl.sandbox.whitelistDbus = [ "system" ];
|
|
||||||
|
|
||||||
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`
|
||||||
|
|
||||||
|
@ -263,13 +433,14 @@ in
|
||||||
ddrescue.sandbox.method = "landlock"; # TODO:sandbox: untested
|
ddrescue.sandbox.method = "landlock"; # TODO:sandbox: untested
|
||||||
ddrescue.sandbox.autodetectCliPaths = "existingOrParent";
|
ddrescue.sandbox.autodetectCliPaths = "existingOrParent";
|
||||||
|
|
||||||
# auth token, preferences
|
delfin.buildCost = 1;
|
||||||
delfin.sandbox.method = "bwrap";
|
delfin.sandbox.method = "bwrap";
|
||||||
delfin.sandbox.whitelistAudio = true;
|
delfin.sandbox.whitelistAudio = true;
|
||||||
delfin.sandbox.whitelistDbus = [ "user" ]; # else `mpris` plugin crashes the player
|
delfin.sandbox.whitelistDbus = [ "user" ]; # else `mpris` plugin crashes the player
|
||||||
delfin.sandbox.whitelistDri = true;
|
delfin.sandbox.whitelistDri = true;
|
||||||
delfin.sandbox.whitelistWayland = true;
|
delfin.sandbox.whitelistWayland = true;
|
||||||
delfin.sandbox.net = "clearnet";
|
delfin.sandbox.net = "clearnet";
|
||||||
|
# auth token, preferences
|
||||||
delfin.persist.byStore.private = [ ".config/delfin" ];
|
delfin.persist.byStore.private = [ ".config/delfin" ];
|
||||||
|
|
||||||
dig.sandbox.method = "bwrap";
|
dig.sandbox.method = "bwrap";
|
||||||
|
@ -296,11 +467,7 @@ in
|
||||||
];
|
];
|
||||||
|
|
||||||
dtc.sandbox.method = "bwrap";
|
dtc.sandbox.method = "bwrap";
|
||||||
dtc.sandbox.autodetectCliPaths = true; # TODO:sandbox: untested
|
dtc.sandbox.autodetectCliPaths = "existingFile"; # TODO:sandbox: untested
|
||||||
|
|
||||||
dtrx.sandbox.method = "bwrap";
|
|
||||||
dtrx.sandbox.whitelistPwd = true;
|
|
||||||
dtrx.sandbox.autodetectCliPaths = "existing"; #< for the archive
|
|
||||||
|
|
||||||
duplicity = {};
|
duplicity = {};
|
||||||
|
|
||||||
|
@ -314,11 +481,13 @@ in
|
||||||
|
|
||||||
eg25-control = {};
|
eg25-control = {};
|
||||||
|
|
||||||
|
electrum.buildCost = 1;
|
||||||
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.cryptClearOnBoot = [ ".electrum" ]; #< TODO: use XDG dirs!
|
||||||
|
|
||||||
|
endless-sky.buildCost = 1;
|
||||||
endless-sky.persist.byStore.plaintext = [ ".local/share/endless-sky" ];
|
endless-sky.persist.byStore.plaintext = [ ".local/share/endless-sky" ];
|
||||||
endless-sky.sandbox.method = "bwrap";
|
endless-sky.sandbox.method = "bwrap";
|
||||||
endless-sky.sandbox.whitelistAudio = true;
|
endless-sky.sandbox.whitelistAudio = true;
|
||||||
|
@ -334,10 +503,9 @@ in
|
||||||
ethtool.sandbox.capabilities = [ "net_admin" ];
|
ethtool.sandbox.capabilities = [ "net_admin" ];
|
||||||
|
|
||||||
# eza `ls` replacement
|
# eza `ls` replacement
|
||||||
# landlock is OK, only `whitelistPwd` doesn't make the intermediate symlinks traversable, so it breaks on e.g. ~/Videos/servo/Shows/foo
|
|
||||||
# eza.sandbox.method = "landlock";
|
# eza.sandbox.method = "landlock";
|
||||||
eza.sandbox.method = "bwrap";
|
eza.sandbox.method = "bwrap"; #< note that bwrap causes `/proc` files to be listed differently (e.g. `eza /proc/sys/net/ipv6/conf/`)
|
||||||
eza.sandbox.autodetectCliPaths = true;
|
eza.sandbox.autodetectCliPaths = "existing";
|
||||||
eza.sandbox.whitelistPwd = true;
|
eza.sandbox.whitelistPwd = true;
|
||||||
eza.sandbox.extraHomePaths = [
|
eza.sandbox.extraHomePaths = [
|
||||||
# so that e.g. `eza -l ~` can show which symlink exist
|
# so that e.g. `eza -l ~` can show which symlink exist
|
||||||
|
@ -349,7 +517,7 @@ in
|
||||||
fatresize.sandbox.autodetectCliPaths = "parent"; # /dev/sda1 -> needs /dev/sda
|
fatresize.sandbox.autodetectCliPaths = "parent"; # /dev/sda1 -> needs /dev/sda
|
||||||
|
|
||||||
fd.sandbox.method = "landlock";
|
fd.sandbox.method = "landlock";
|
||||||
fd.sandbox.autodetectCliPaths = true;
|
fd.sandbox.autodetectCliPaths = "existing";
|
||||||
fd.sandbox.whitelistPwd = true;
|
fd.sandbox.whitelistPwd = true;
|
||||||
fd.sandbox.extraHomePaths = [
|
fd.sandbox.extraHomePaths = [
|
||||||
# let it follow symlinks to non-sensitive data
|
# let it follow symlinks to non-sensitive data
|
||||||
|
@ -357,14 +525,15 @@ in
|
||||||
".persist/plaintext"
|
".persist/plaintext"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
ffmpeg.buildCost = 1;
|
||||||
ffmpeg.sandbox.method = "bwrap";
|
ffmpeg.sandbox.method = "bwrap";
|
||||||
ffmpeg.sandbox.autodetectCliPaths = "existingFileOrParent"; # it outputs uncreated files -> parent dir needs mounting
|
ffmpeg.sandbox.autodetectCliPaths = "existingFileOrParent"; # it outputs uncreated files -> parent dir needs mounting
|
||||||
|
|
||||||
file.sandbox.method = "bwrap";
|
file.sandbox.method = "bwrap";
|
||||||
file.sandbox.autodetectCliPaths = true;
|
file.sandbox.autodetectCliPaths = "existing"; #< file OR directory, yes
|
||||||
|
|
||||||
findutils.sandbox.method = "bwrap";
|
findutils.sandbox.method = "bwrap";
|
||||||
findutils.sandbox.autodetectCliPaths = true;
|
findutils.sandbox.autodetectCliPaths = "existing";
|
||||||
findutils.sandbox.whitelistPwd = true;
|
findutils.sandbox.whitelistPwd = true;
|
||||||
findutils.sandbox.extraHomePaths = [
|
findutils.sandbox.extraHomePaths = [
|
||||||
# let it follow symlinks to non-sensitive data
|
# let it follow symlinks to non-sensitive data
|
||||||
|
@ -374,16 +543,16 @@ in
|
||||||
|
|
||||||
fluffychat-moby.persist.byStore.plaintext = [ ".local/share/chat.fluffy.fluffychat" ];
|
fluffychat-moby.persist.byStore.plaintext = [ ".local/share/chat.fluffy.fluffychat" ];
|
||||||
|
|
||||||
|
font-manager.buildCost = 1;
|
||||||
font-manager.sandbox.method = "bwrap";
|
font-manager.sandbox.method = "bwrap";
|
||||||
|
font-manager.sandbox.whitelistWayland = true;
|
||||||
font-manager.packageUnwrapped = pkgs.rmDbusServicesInPlace (pkgs.font-manager.override {
|
font-manager.packageUnwrapped = pkgs.rmDbusServicesInPlace (pkgs.font-manager.override {
|
||||||
# build without the "Google Fonts" integration feature, to save closure / avoid webkitgtk_4_0
|
# build without the "Google Fonts" integration feature, to save closure / avoid webkitgtk_4_0
|
||||||
withWebkit = false;
|
withWebkit = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
forkstat.sandbox.method = "landlock"; #< doesn't seem to support bwrap
|
forkstat.sandbox.method = "landlock"; #< doesn't seem to support bwrap
|
||||||
forkstat.sandbox.extraConfig = [
|
forkstat.sandbox.isolatePids = false;
|
||||||
"--sane-sandbox-keep-namespace" "pid"
|
|
||||||
];
|
|
||||||
forkstat.sandbox.extraPaths = [
|
forkstat.sandbox.extraPaths = [
|
||||||
"/proc"
|
"/proc"
|
||||||
];
|
];
|
||||||
|
@ -397,7 +566,7 @@ in
|
||||||
|
|
||||||
gawk.sandbox.method = "bwrap"; # TODO:sandbox: untested
|
gawk.sandbox.method = "bwrap"; # TODO:sandbox: untested
|
||||||
gawk.sandbox.wrapperType = "inplace"; # /share/gawk libraries refer to /libexec
|
gawk.sandbox.wrapperType = "inplace"; # /share/gawk libraries refer to /libexec
|
||||||
gawk.sandbox.autodetectCliPaths = true;
|
gawk.sandbox.autodetectCliPaths = "existingFile";
|
||||||
|
|
||||||
gdb.sandbox.enable = false; # gdb doesn't sandbox well. i don't know how you could.
|
gdb.sandbox.enable = false; # gdb doesn't sandbox well. i don't know how you could.
|
||||||
# gdb.sandbox.method = "landlock"; # permission denied when trying to attach, even as root
|
# gdb.sandbox.method = "landlock"; # permission denied when trying to attach, even as root
|
||||||
|
@ -409,6 +578,7 @@ in
|
||||||
# TODO: we can populate gh's stuff statically; it even lets us use the same oauth across machines
|
# TODO: we can populate gh's stuff statically; it even lets us use the same oauth across machines
|
||||||
gh.persist.byStore.private = [ ".config/gh" ];
|
gh.persist.byStore.private = [ ".config/gh" ];
|
||||||
|
|
||||||
|
gimp.buildCost = 1;
|
||||||
gimp.sandbox.method = "bwrap";
|
gimp.sandbox.method = "bwrap";
|
||||||
gimp.sandbox.whitelistX = true;
|
gimp.sandbox.whitelistX = true;
|
||||||
gimp.sandbox.whitelistWayland = true;
|
gimp.sandbox.whitelistWayland = true;
|
||||||
|
@ -428,32 +598,39 @@ in
|
||||||
"/tmp" # "Cannot open display:" if it can't mount /tmp 👀
|
"/tmp" # "Cannot open display:" if it can't mount /tmp 👀
|
||||||
];
|
];
|
||||||
|
|
||||||
|
"gnome.gnome-calculator".buildCost = 1;
|
||||||
"gnome.gnome-calculator".sandbox.method = "bwrap";
|
"gnome.gnome-calculator".sandbox.method = "bwrap";
|
||||||
"gnome.gnome-calculator".sandbox.whitelistWayland = true;
|
"gnome.gnome-calculator".sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
|
"gnome.gnome-calendar".buildCost = 1;
|
||||||
# gnome-calendar surely has data to persist, but i use it strictly to do date math, not track events.
|
# gnome-calendar surely has data to persist, but i use it strictly to do date math, not track events.
|
||||||
"gnome.gnome-calendar".sandbox.method = "bwrap";
|
"gnome.gnome-calendar".sandbox.method = "bwrap";
|
||||||
"gnome.gnome-calendar".sandbox.whitelistWayland = true;
|
"gnome.gnome-calendar".sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
"gnome.gnome-clocks".sandbox.method = "bwrap";
|
|
||||||
"gnome.gnome-clocks".sandbox.whitelistWayland = true;
|
|
||||||
"gnome.gnome-clocks".suggestedPrograms = [ "dconf" ];
|
|
||||||
|
|
||||||
# gnome-disks
|
# gnome-disks
|
||||||
|
"gnome.gnome-disk-utility".buildCost = 1;
|
||||||
"gnome.gnome-disk-utility".sandbox.method = "bwrap";
|
"gnome.gnome-disk-utility".sandbox.method = "bwrap";
|
||||||
"gnome.gnome-disk-utility".sandbox.whitelistDbus = [ "system" ];
|
"gnome.gnome-disk-utility".sandbox.whitelistDbus = [ "system" ];
|
||||||
"gnome.gnome-disk-utility".sandbox.whitelistWayland = true;
|
"gnome.gnome-disk-utility".sandbox.whitelistWayland = true;
|
||||||
|
"gnome.gnome-disk-utility".sandbox.extraHomePaths = [
|
||||||
|
"tmp"
|
||||||
|
"use/iso"
|
||||||
|
# TODO: probably need /dev and such
|
||||||
|
];
|
||||||
|
|
||||||
# seahorse: dump gnome-keyring secrets.
|
# seahorse: dump gnome-keyring secrets.
|
||||||
|
"gnome.seahorse".buildCost = 1;
|
||||||
# N.B.: it can also manage ~/.ssh keys, but i explicitly don't add those to the sandbox for now.
|
# N.B.: it can also manage ~/.ssh keys, but i explicitly don't add those to the sandbox for now.
|
||||||
"gnome.seahorse".sandbox.method = "bwrap";
|
"gnome.seahorse".sandbox.method = "bwrap";
|
||||||
"gnome.seahorse".sandbox.whitelistDbus = [ "user" ];
|
"gnome.seahorse".sandbox.whitelistDbus = [ "user" ];
|
||||||
"gnome.seahorse".sandbox.whitelistWayland = true;
|
"gnome.seahorse".sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
|
gnome-2048.buildCost = 1;
|
||||||
gnome-2048.sandbox.method = "bwrap";
|
gnome-2048.sandbox.method = "bwrap";
|
||||||
gnome-2048.sandbox.whitelistWayland = true;
|
gnome-2048.sandbox.whitelistWayland = true;
|
||||||
gnome-2048.persist.byStore.plaintext = [ ".local/share/gnome-2048/scores" ];
|
gnome-2048.persist.byStore.plaintext = [ ".local/share/gnome-2048/scores" ];
|
||||||
|
|
||||||
|
gnome-frog.buildCost = 1;
|
||||||
gnome-frog.sandbox.method = "bwrap";
|
gnome-frog.sandbox.method = "bwrap";
|
||||||
gnome-frog.sandbox.whitelistWayland = true;
|
gnome-frog.sandbox.whitelistWayland = true;
|
||||||
gnome-frog.sandbox.whitelistDbus = [ "user" ];
|
gnome-frog.sandbox.whitelistDbus = [ "user" ];
|
||||||
|
@ -480,11 +657,12 @@ in
|
||||||
# 1. no number may appear unshaded more than once in the same row/column
|
# 1. no number may appear unshaded more than once in the same row/column
|
||||||
# 2. no two shaded tiles can be direct N/S/E/W neighbors
|
# 2. no two shaded tiles can be direct N/S/E/W neighbors
|
||||||
# - win once (1) and (2) are satisfied
|
# - win once (1) and (2) are satisfied
|
||||||
|
"gnome.hitori".buildCost = 1;
|
||||||
"gnome.hitori".sandbox.method = "bwrap";
|
"gnome.hitori".sandbox.method = "bwrap";
|
||||||
"gnome.hitori".sandbox.whitelistWayland = true;
|
"gnome.hitori".sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
gnugrep.sandbox.method = "bwrap";
|
gnugrep.sandbox.method = "bwrap";
|
||||||
gnugrep.sandbox.autodetectCliPaths = true;
|
gnugrep.sandbox.autodetectCliPaths = "existing";
|
||||||
gnugrep.sandbox.whitelistPwd = true;
|
gnugrep.sandbox.whitelistPwd = true;
|
||||||
gnugrep.sandbox.extraHomePaths = [
|
gnugrep.sandbox.extraHomePaths = [
|
||||||
# let it follow symlinks to non-sensitive data
|
# let it follow symlinks to non-sensitive data
|
||||||
|
@ -492,7 +670,6 @@ in
|
||||||
".persist/plaintext"
|
".persist/plaintext"
|
||||||
];
|
];
|
||||||
|
|
||||||
# sed: there is an edgecase of `--file=<foo>`, wherein `foo` won't be whitelisted.
|
|
||||||
gnused.sandbox.method = "bwrap";
|
gnused.sandbox.method = "bwrap";
|
||||||
gnused.sandbox.autodetectCliPaths = "existingFile";
|
gnused.sandbox.autodetectCliPaths = "existingFile";
|
||||||
gnused.sandbox.whitelistPwd = true; #< `-i` flag creates a temporary file in pwd (?) and then moves it.
|
gnused.sandbox.whitelistPwd = true; #< `-i` flag creates a temporary file in pwd (?) and then moves it.
|
||||||
|
@ -509,6 +686,7 @@ in
|
||||||
grim.sandbox.autodetectCliPaths = "existingOrParent";
|
grim.sandbox.autodetectCliPaths = "existingOrParent";
|
||||||
grim.sandbox.whitelistWayland = true;
|
grim.sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
|
hase.buildCost = 1;
|
||||||
hase.sandbox.method = "bwrap";
|
hase.sandbox.method = "bwrap";
|
||||||
hase.sandbox.net = "clearnet";
|
hase.sandbox.net = "clearnet";
|
||||||
hase.sandbox.whitelistAudio = true;
|
hase.sandbox.whitelistAudio = true;
|
||||||
|
@ -517,7 +695,7 @@ in
|
||||||
|
|
||||||
# hdparm: has to be run as sudo. e.g. `sudo hdparm -i /dev/sda`
|
# hdparm: has to be run as sudo. e.g. `sudo hdparm -i /dev/sda`
|
||||||
hdparm.sandbox.method = "bwrap";
|
hdparm.sandbox.method = "bwrap";
|
||||||
hdparm.sandbox.autodetectCliPaths = true;
|
hdparm.sandbox.autodetectCliPaths = "existingFile";
|
||||||
|
|
||||||
host.sandbox.method = "landlock";
|
host.sandbox.method = "landlock";
|
||||||
host.sandbox.net = "all"; #< technically, only needs to contact localhost's DNS server
|
host.sandbox.net = "all"; #< technically, only needs to contact localhost's DNS server
|
||||||
|
@ -529,6 +707,7 @@ in
|
||||||
# N.B.: inetutils' `ping` is shadowed by iputils' ping (by nixos, intentionally).
|
# N.B.: inetutils' `ping` is shadowed by iputils' ping (by nixos, intentionally).
|
||||||
inetutils.sandbox.method = "landlock"; # want to keep the same netns, at least.
|
inetutils.sandbox.method = "landlock"; # want to keep the same netns, at least.
|
||||||
|
|
||||||
|
inkscape.buildCost = 1;
|
||||||
inkscape.sandbox.method = "bwrap";
|
inkscape.sandbox.method = "bwrap";
|
||||||
inkscape.sandbox.whitelistWayland = true;
|
inkscape.sandbox.whitelistWayland = true;
|
||||||
inkscape.sandbox.extraHomePaths = [
|
inkscape.sandbox.extraHomePaths = [
|
||||||
|
@ -550,14 +729,17 @@ in
|
||||||
];
|
];
|
||||||
iotop.sandbox.capabilities = [ "net_admin" ];
|
iotop.sandbox.capabilities = [ "net_admin" ];
|
||||||
|
|
||||||
# provides `ip`, `routel`, others
|
# provides `ip`, `routel`, `bridge`, others.
|
||||||
iproute2.sandbox.method = "landlock";
|
# landlock works fine for most of these, but `ip netns exec` wants to attach to an existing namespace
|
||||||
iproute2.sandbox.net = "all";
|
# and that means we can't use ANY sandboxer for it.
|
||||||
iproute2.sandbox.capabilities = [ "net_admin" ];
|
iproute2.sandbox.enable = false;
|
||||||
iproute2.sandbox.extraPaths = [
|
# iproute2.sandbox.net = "all";
|
||||||
"/run/netns" # for `ip netns ...` to work
|
# iproute2.sandbox.capabilities = [ "net_admin" ];
|
||||||
"/var/run/netns"
|
# iproute2.sandbox.extraPaths = [
|
||||||
];
|
# "/run/netns" # for `ip netns ...` to work, but maybe not needed anymore?
|
||||||
|
# "/sys/class/net" # for `ip netns ...` to work
|
||||||
|
# "/var/run/netns"
|
||||||
|
# ];
|
||||||
|
|
||||||
iptables.sandbox.method = "landlock";
|
iptables.sandbox.method = "landlock";
|
||||||
iptables.sandbox.net = "all";
|
iptables.sandbox.net = "all";
|
||||||
|
@ -580,6 +762,7 @@ in
|
||||||
"/proc"
|
"/proc"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
krita.buildCost = 1;
|
||||||
krita.sandbox.method = "bwrap";
|
krita.sandbox.method = "bwrap";
|
||||||
krita.sandbox.whitelistWayland = true;
|
krita.sandbox.whitelistWayland = true;
|
||||||
krita.sandbox.autodetectCliPaths = "existing";
|
krita.sandbox.autodetectCliPaths = "existing";
|
||||||
|
@ -595,11 +778,15 @@ in
|
||||||
"tmp"
|
"tmp"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
libcamera = {};
|
||||||
|
|
||||||
|
libcap.sandbox.enable = false; #< for `capsh`, which i use as a sandboxer
|
||||||
libcap_ng.sandbox.enable = false; # there's something about /proc/$pid/fd which breaks `readlink`/stat with every sandbox technique (except capsh-only)
|
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
|
||||||
|
|
||||||
|
losslesscut-bin.buildCost = 1;
|
||||||
losslesscut-bin.sandbox.method = "bwrap";
|
losslesscut-bin.sandbox.method = "bwrap";
|
||||||
losslesscut-bin.sandbox.extraHomePaths = [
|
losslesscut-bin.sandbox.extraHomePaths = [
|
||||||
"Music"
|
"Music"
|
||||||
|
@ -615,14 +802,19 @@ in
|
||||||
losslesscut-bin.sandbox.whitelistX = true;
|
losslesscut-bin.sandbox.whitelistX = true;
|
||||||
|
|
||||||
lsof.sandbox.method = "capshonly"; # lsof doesn't sandbox under bwrap or even landlock w/ full access to /
|
lsof.sandbox.method = "capshonly"; # lsof doesn't sandbox under bwrap or even landlock w/ full access to /
|
||||||
|
lsof.sandbox.capabilities = [ "dac_override" "sys_ptrace" ];
|
||||||
|
|
||||||
lua = {};
|
lua = {};
|
||||||
|
|
||||||
|
man-pages.sandbox.enable = false;
|
||||||
|
man-pages-posix.sandbox.enable = false;
|
||||||
|
|
||||||
mercurial.sandbox.method = "bwrap"; # TODO:sandbox: untested
|
mercurial.sandbox.method = "bwrap"; # TODO:sandbox: untested
|
||||||
mercurial.sandbox.net = "clearnet";
|
mercurial.sandbox.net = "clearnet";
|
||||||
mercurial.sandbox.whitelistPwd = true;
|
mercurial.sandbox.whitelistPwd = true;
|
||||||
|
|
||||||
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
|
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
|
||||||
|
monero-gui.buildCost = 1;
|
||||||
# XXX: is it really safe to persist this? it doesn't have info that could de-anonymize if captured?
|
# XXX: is it really safe to persist this? it doesn't have info that could de-anonymize if captured?
|
||||||
monero-gui.persist.byStore.plaintext = [ ".bitmonero" ];
|
monero-gui.persist.byStore.plaintext = [ ".bitmonero" ];
|
||||||
monero-gui.sandbox.method = "bwrap";
|
monero-gui.sandbox.method = "bwrap";
|
||||||
|
@ -631,6 +823,7 @@ in
|
||||||
"records/finance/cryptocurrencies/monero"
|
"records/finance/cryptocurrencies/monero"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
mumble.buildCost = 1;
|
||||||
mumble.persist.byStore.private = [ ".local/share/Mumble" ];
|
mumble.persist.byStore.private = [ ".local/share/Mumble" ];
|
||||||
|
|
||||||
nano.sandbox.method = "bwrap";
|
nano.sandbox.method = "bwrap";
|
||||||
|
@ -658,9 +851,15 @@ in
|
||||||
nixpkgs-review.sandbox.wrapperType = "inplace"; #< shell completions use full paths
|
nixpkgs-review.sandbox.wrapperType = "inplace"; #< shell completions use full paths
|
||||||
nixpkgs-review.sandbox.net = "clearnet";
|
nixpkgs-review.sandbox.net = "clearnet";
|
||||||
nixpkgs-review.sandbox.whitelistPwd = true;
|
nixpkgs-review.sandbox.whitelistPwd = true;
|
||||||
|
nixpkgs-review.sandbox.extraHomePaths = [
|
||||||
|
".config/git" #< it needs to know commiter name/email, even if not posting
|
||||||
|
];
|
||||||
nixpkgs-review.sandbox.extraPaths = [
|
nixpkgs-review.sandbox.extraPaths = [
|
||||||
"/nix"
|
"/nix"
|
||||||
];
|
];
|
||||||
|
nixpkgs-review.persist.byStore.cryptClearOnBoot = [
|
||||||
|
".cache/nixpkgs-review" #< help it not exhaust / tmpfs
|
||||||
|
];
|
||||||
|
|
||||||
nmap.sandbox.method = "bwrap";
|
nmap.sandbox.method = "bwrap";
|
||||||
nmap.sandbox.net = "all"; # clearnet and lan
|
nmap.sandbox.net = "all"; # clearnet and lan
|
||||||
|
@ -689,6 +888,8 @@ in
|
||||||
# settings (electron app)
|
# settings (electron app)
|
||||||
obsidian.persist.byStore.plaintext = [ ".config/obsidian" ];
|
obsidian.persist.byStore.plaintext = [ ".config/obsidian" ];
|
||||||
|
|
||||||
|
passt.sandbox.enable = false; #< sandbox helper (netns specifically)
|
||||||
|
|
||||||
parted.sandbox.method = "landlock";
|
parted.sandbox.method = "landlock";
|
||||||
parted.sandbox.extraPaths = [
|
parted.sandbox.extraPaths = [
|
||||||
"/dev"
|
"/dev"
|
||||||
|
@ -720,9 +921,7 @@ in
|
||||||
|
|
||||||
# procps: free, pgrep, pidof, pkill, ps, pwait, top, uptime, couple others
|
# procps: free, pgrep, pidof, pkill, ps, pwait, top, uptime, couple others
|
||||||
procps.sandbox.method = "bwrap";
|
procps.sandbox.method = "bwrap";
|
||||||
procps.sandbox.extraConfig = [
|
procps.sandbox.isolatePids = false;
|
||||||
"--sane-sandbox-keep-namespace" "pid"
|
|
||||||
];
|
|
||||||
|
|
||||||
pstree.sandbox.method = "landlock";
|
pstree.sandbox.method = "landlock";
|
||||||
pstree.sandbox.extraPaths = [
|
pstree.sandbox.extraPaths = [
|
||||||
|
@ -734,11 +933,14 @@ in
|
||||||
pulsemixer.sandbox.method = "landlock";
|
pulsemixer.sandbox.method = "landlock";
|
||||||
pulsemixer.sandbox.whitelistAudio = true;
|
pulsemixer.sandbox.whitelistAudio = true;
|
||||||
|
|
||||||
|
pwvucontrol.buildCost = 1;
|
||||||
pwvucontrol.sandbox.method = "bwrap";
|
pwvucontrol.sandbox.method = "bwrap";
|
||||||
pwvucontrol.sandbox.whitelistAudio = true;
|
pwvucontrol.sandbox.whitelistAudio = true;
|
||||||
|
pwvucontrol.sandbox.whitelistDri = true; # else perf on moby is unusable
|
||||||
pwvucontrol.sandbox.whitelistWayland = true;
|
pwvucontrol.sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
python3-repl.packageUnwrapped = pkgs.python3.withPackages (ps: with ps; [
|
python3-repl.packageUnwrapped = pkgs.python3.withPackages (ps: with ps; [
|
||||||
|
psutil
|
||||||
requests
|
requests
|
||||||
]);
|
]);
|
||||||
python3-repl.sandbox.method = "bwrap";
|
python3-repl.sandbox.method = "bwrap";
|
||||||
|
@ -749,7 +951,7 @@ in
|
||||||
];
|
];
|
||||||
|
|
||||||
qemu.sandbox.enable = false; #< it's a launcher
|
qemu.sandbox.enable = false; #< it's a launcher
|
||||||
qemu.slowToBuild = true;
|
qemu.buildCost = 2;
|
||||||
|
|
||||||
rsync.sandbox.method = "bwrap";
|
rsync.sandbox.method = "bwrap";
|
||||||
rsync.sandbox.net = "clearnet";
|
rsync.sandbox.net = "clearnet";
|
||||||
|
@ -757,17 +959,23 @@ in
|
||||||
|
|
||||||
rustc = {};
|
rustc = {};
|
||||||
|
|
||||||
sane-open-desktop.sandbox.enable = false; #< trivial script, and all our deps are sandboxed
|
sane-cast.sandbox.method = "bwrap";
|
||||||
sane-open-desktop.suggestedPrograms = [
|
sane-cast.sandbox.net = "clearnet";
|
||||||
"gdbus"
|
sane-cast.sandbox.autodetectCliPaths = "existingFile";
|
||||||
];
|
sane-cast.suggestedPrograms = [ "go2tv" ];
|
||||||
|
|
||||||
|
sane-die-with-parent.sandbox.enable = false; #< it's a launcher; can't sandbox
|
||||||
|
|
||||||
|
sane-weather.sandbox.method = "bwrap";
|
||||||
|
sane-weather.sandbox.net = "clearnet";
|
||||||
|
|
||||||
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.sandbox.method = "bwrap"; # TODO:sandbox: untested
|
||||||
sequoia.sandbox.whitelistPwd = true;
|
sequoia.sandbox.whitelistPwd = true;
|
||||||
sequoia.sandbox.autodetectCliPaths = true;
|
sequoia.sandbox.autodetectCliPaths = "existingFileOrParent"; # supports `-o <file-to-create>`
|
||||||
|
|
||||||
|
shattered-pixel-dungeon.buildCost = 1;
|
||||||
shattered-pixel-dungeon.persist.byStore.plaintext = [ ".local/share/.shatteredpixel/shattered-pixel-dungeon" ];
|
shattered-pixel-dungeon.persist.byStore.plaintext = [ ".local/share/.shatteredpixel/shattered-pixel-dungeon" ];
|
||||||
shattered-pixel-dungeon.sandbox.method = "bwrap";
|
shattered-pixel-dungeon.sandbox.method = "bwrap";
|
||||||
shattered-pixel-dungeon.sandbox.whitelistAudio = true;
|
shattered-pixel-dungeon.sandbox.whitelistAudio = true;
|
||||||
|
@ -775,6 +983,7 @@ in
|
||||||
shattered-pixel-dungeon.sandbox.whitelistWayland = true;
|
shattered-pixel-dungeon.sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
# printer/filament settings
|
# printer/filament settings
|
||||||
|
slic3r.buildCost = 1;
|
||||||
slic3r.persist.byStore.plaintext = [ ".Slic3r" ];
|
slic3r.persist.byStore.plaintext = [ ".Slic3r" ];
|
||||||
|
|
||||||
slurp.sandbox.method = "bwrap";
|
slurp.sandbox.method = "bwrap";
|
||||||
|
@ -786,15 +995,20 @@ in
|
||||||
smartmontools.sandbox.autodetectCliPaths = "existing";
|
smartmontools.sandbox.autodetectCliPaths = "existing";
|
||||||
smartmontools.sandbox.capabilities = [ "sys_rawio" ];
|
smartmontools.sandbox.capabilities = [ "sys_rawio" ];
|
||||||
|
|
||||||
|
# snapshot camera, based on libcamera
|
||||||
|
# TODO: enable dma heaps for more efficient buffer sharing: <https://gitlab.com/postmarketOS/pmaports/-/issues/2789>
|
||||||
|
snapshot = {};
|
||||||
|
|
||||||
sops.sandbox.method = "bwrap"; # TODO:sandbox: untested
|
sops.sandbox.method = "bwrap"; # TODO:sandbox: untested
|
||||||
sops.sandbox.extraHomePaths = [
|
sops.sandbox.extraHomePaths = [
|
||||||
".config/sops"
|
".config/sops"
|
||||||
"dev/nixos"
|
"nixos"
|
||||||
# TODO: sops should only need access to knowledge/secrets,
|
# TODO: sops should only need access to knowledge/secrets,
|
||||||
# except that i currently put its .sops.yaml config in the root of ~/knowledge
|
# except that i currently put its .sops.yaml config in the root of ~/knowledge
|
||||||
"knowledge"
|
"knowledge"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
soundconverter.buildCost = 1;
|
||||||
soundconverter.sandbox.method = "bwrap";
|
soundconverter.sandbox.method = "bwrap";
|
||||||
soundconverter.sandbox.whitelistWayland = true;
|
soundconverter.sandbox.whitelistWayland = true;
|
||||||
soundconverter.sandbox.extraHomePaths = [
|
soundconverter.sandbox.extraHomePaths = [
|
||||||
|
@ -812,6 +1026,7 @@ in
|
||||||
sox.sandbox.autodetectCliPaths = "existingFileOrParent";
|
sox.sandbox.autodetectCliPaths = "existingFileOrParent";
|
||||||
sox.sandbox.whitelistAudio = true;
|
sox.sandbox.whitelistAudio = true;
|
||||||
|
|
||||||
|
space-cadet-pinball.buildCost = 1;
|
||||||
space-cadet-pinball.persist.byStore.plaintext = [ ".local/share/SpaceCadetPinball" ];
|
space-cadet-pinball.persist.byStore.plaintext = [ ".local/share/SpaceCadetPinball" ];
|
||||||
space-cadet-pinball.sandbox.method = "bwrap";
|
space-cadet-pinball.sandbox.method = "bwrap";
|
||||||
space-cadet-pinball.sandbox.whitelistAudio = true;
|
space-cadet-pinball.sandbox.whitelistAudio = true;
|
||||||
|
@ -832,6 +1047,7 @@ in
|
||||||
subversion.sandbox.whitelistPwd = true;
|
subversion.sandbox.whitelistPwd = true;
|
||||||
sudo.sandbox.enable = false;
|
sudo.sandbox.enable = false;
|
||||||
|
|
||||||
|
superTux.buildCost = 1;
|
||||||
superTux.sandbox.method = "bwrap";
|
superTux.sandbox.method = "bwrap";
|
||||||
superTux.sandbox.wrapperType = "inplace"; # package Makefile incorrectly installs to $out/games/superTux instead of $out/share/games
|
superTux.sandbox.wrapperType = "inplace"; # package Makefile incorrectly installs to $out/games/superTux instead of $out/share/games
|
||||||
superTux.sandbox.whitelistAudio = true;
|
superTux.sandbox.whitelistAudio = true;
|
||||||
|
@ -850,12 +1066,14 @@ in
|
||||||
|
|
||||||
tdesktop.persist.byStore.private = [ ".local/share/TelegramDesktop" ];
|
tdesktop.persist.byStore.private = [ ".local/share/TelegramDesktop" ];
|
||||||
|
|
||||||
|
tokodon.buildCost = 1;
|
||||||
tokodon.persist.byStore.private = [ ".cache/KDE/tokodon" ];
|
tokodon.persist.byStore.private = [ ".cache/KDE/tokodon" ];
|
||||||
|
|
||||||
tree.sandbox.method = "landlock";
|
tree.sandbox.method = "landlock";
|
||||||
tree.sandbox.autodetectCliPaths = true;
|
tree.sandbox.autodetectCliPaths = "existing";
|
||||||
tree.sandbox.whitelistPwd = true;
|
tree.sandbox.whitelistPwd = true;
|
||||||
|
|
||||||
|
tumiki-fighters.buildCost = 1;
|
||||||
tumiki-fighters.sandbox.method = "bwrap";
|
tumiki-fighters.sandbox.method = "bwrap";
|
||||||
tumiki-fighters.sandbox.whitelistAudio = true;
|
tumiki-fighters.sandbox.whitelistAudio = true;
|
||||||
tumiki-fighters.sandbox.whitelistDri = true; #< not strictly necessary, but triples CPU perf
|
tumiki-fighters.sandbox.whitelistDri = true; #< not strictly necessary, but triples CPU perf
|
||||||
|
@ -874,12 +1092,16 @@ in
|
||||||
"/sys/bus/usb"
|
"/sys/bus/usb"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
valgrind.buildCost = 1;
|
||||||
|
valgrind.sandbox.enable = false; #< it's a launcher: can't sandbox
|
||||||
|
|
||||||
visidata.sandbox.method = "bwrap"; # TODO:sandbox: untested
|
visidata.sandbox.method = "bwrap"; # TODO:sandbox: untested
|
||||||
visidata.sandbox.autodetectCliPaths = true;
|
visidata.sandbox.autodetectCliPaths = true;
|
||||||
|
|
||||||
# `vulkaninfo`, `vkcube`
|
# `vulkaninfo`, `vkcube`
|
||||||
vulkan-tools.sandbox.method = "landlock";
|
vulkan-tools.sandbox.method = "landlock";
|
||||||
|
|
||||||
|
vvvvvv.buildCost = 1;
|
||||||
vvvvvv.sandbox.method = "bwrap";
|
vvvvvv.sandbox.method = "bwrap";
|
||||||
vvvvvv.sandbox.whitelistAudio = true;
|
vvvvvv.sandbox.whitelistAudio = true;
|
||||||
vvvvvv.sandbox.whitelistDri = true; #< playable without, but burns noticably more CPU
|
vvvvvv.sandbox.whitelistDri = true; #< playable without, but burns noticably more CPU
|
||||||
|
@ -900,6 +1122,7 @@ in
|
||||||
wget.sandbox.net = "all";
|
wget.sandbox.net = "all";
|
||||||
wget.sandbox.whitelistPwd = true; # saves to pwd by default
|
wget.sandbox.whitelistPwd = true; # saves to pwd by default
|
||||||
|
|
||||||
|
whalebird.buildCost = 1;
|
||||||
whalebird.persist.byStore.private = [ ".config/Whalebird" ];
|
whalebird.persist.byStore.private = [ ".config/Whalebird" ];
|
||||||
|
|
||||||
# `wg`, `wg-quick`
|
# `wg`, `wg-quick`
|
||||||
|
@ -914,6 +1137,8 @@ in
|
||||||
wl-clipboard.sandbox.whitelistWayland = true;
|
wl-clipboard.sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
wtype = {};
|
wtype = {};
|
||||||
|
wtype.sandbox.method = "bwrap";
|
||||||
|
wtype.sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
xwayland.sandbox.method = "bwrap";
|
xwayland.sandbox.method = "bwrap";
|
||||||
xwayland.sandbox.wrapperType = "inplace"; #< consumers use it as a library (e.g. wlroots)
|
xwayland.sandbox.wrapperType = "inplace"; #< consumers use it as a library (e.g. wlroots)
|
||||||
|
@ -932,7 +1157,44 @@ in
|
||||||
zfs = {};
|
zfs = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
programs.feedbackd = lib.mkIf config.sane.programs.feedbackd.enabled {
|
sane.persist.sys.byStore.plaintext = lib.mkIf config.sane.programs.guiApps.enabled [
|
||||||
|
# "/var/lib/alsa" # preserve output levels, default devices
|
||||||
|
{ path = "/var/lib/systemd/backlight"; method = "bind"; } # backlight brightness; bind because systemd T_T
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd.services."systemd-backlight@" = lib.mkIf config.sane.programs.guiApps.enabled {
|
||||||
|
after = [
|
||||||
|
"ensure-var-lib-systemd-backlight.service"
|
||||||
|
];
|
||||||
|
wants = [
|
||||||
|
"ensure-var-lib-systemd-backlight.service"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
hardware.opengl = lib.mkIf config.sane.programs.guiApps.enabled ({
|
||||||
enable = true;
|
enable = true;
|
||||||
|
driSupport = lib.mkDefault true;
|
||||||
|
} // (lib.optionalAttrs pkgs.stdenv.isx86_64 {
|
||||||
|
# for 32 bit applications
|
||||||
|
# upstream nixpkgs forbids setting driSupport32Bit unless specifically x86_64 (so aarch64 isn't allowed)
|
||||||
|
driSupport32Bit = lib.mkDefault true;
|
||||||
|
}));
|
||||||
|
|
||||||
|
system.activationScripts.notifyActive = lib.mkIf config.sane.programs.guiApps.enabled {
|
||||||
|
text = lib.concatStringsSep "\n" ([
|
||||||
|
''
|
||||||
|
tryNotifyUser() {
|
||||||
|
local user="$1"
|
||||||
|
local new_path="$PATH:${pkgs.sudo}/bin:${pkgs.libnotify}/bin"
|
||||||
|
local version="$(cat $systemConfig/nixos-version)"
|
||||||
|
PATH="$new_path" sudo -u "$user" \
|
||||||
|
env PATH="$new_path" NIXOS_VERSION="$version" /bin/sh -c \
|
||||||
|
'. $HOME/.profile; dbus_file="$XDG_RUNTIME_DIR/bus"; if [ -z "$DBUS_SESSION_BUS_ADDRESS" ] && [ -e "$dbus_file" ]; then export DBUS_SESSION_BUS_ADDRESS="unix:path=$dbus_file"; fi ; if [ -n "$DBUS_SESSION_BUS_ADDRESS" ]; then notify-send "nixos activated" "version: $NIXOS_VERSION" ; fi'
|
||||||
|
}
|
||||||
|
''
|
||||||
|
] ++ lib.mapAttrsToList
|
||||||
|
(user: en: lib.optionalString en "tryNotifyUser ${user}")
|
||||||
|
config.sane.programs.guiApps.enableFor.user
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,12 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
buildCost = 1;
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.whitelistAudio = true;
|
sandbox.whitelistAudio = true;
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
sandbox.autodetectCliPaths = true;
|
sandbox.autodetectCliPaths = "existingFile";
|
||||||
sandbox.extraHomePaths = [
|
sandbox.extraHomePaths = [
|
||||||
# support media imports via file->open dir to some common media directories
|
# support media imports via file->open dir to some common media directories
|
||||||
"tmp"
|
"tmp"
|
||||||
|
|
10
hosts/common/programs/ausyscall.nix
Normal file
10
hosts/common/programs/ausyscall.nix
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# `ausyscall --dump`: lists all syscalls by number and name
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.programs.ausyscall = {
|
||||||
|
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.audit "bin/ausyscall";
|
||||||
|
|
||||||
|
sandbox.method = "landlock";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ let
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
sane.programs.bemenu = {
|
sane.programs.bemenu = {
|
||||||
sandbox.method = "bwrap"; # landlock works, but requires *all* of /run/user/$ID to be granted.
|
sandbox.method = "bwrap"; # landlock works, but requires *all* of $XDG_RUNTIME_DIR to be granted.
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
sandbox.extraHomePaths = [
|
sandbox.extraHomePaths = [
|
||||||
".cache/fontconfig" #< else it complains, and is *way* slower
|
".cache/fontconfig" #< else it complains, and is *way* slower
|
||||||
|
|
|
@ -2,10 +2,7 @@
|
||||||
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])" -p blast-ugjka
|
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])" -p blast-ugjka
|
||||||
# vim: set filetype=python :
|
# vim: set filetype=python :
|
||||||
|
|
||||||
import ctypes
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import signal
|
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
@ -16,53 +13,9 @@ logger = logging.getLogger(__name__)
|
||||||
# map from known devices -> required flags
|
# map from known devices -> required flags
|
||||||
DEVICE_MAP = {
|
DEVICE_MAP = {
|
||||||
"Theater TV": [],
|
"Theater TV": [],
|
||||||
"[LG] webOS TV OLED55C9PUA": [ "-usewav" ],
|
"Cuddlevision": [ "-usewav" ],
|
||||||
}
|
}
|
||||||
|
|
||||||
def set_pdeathsig(sig=signal.SIGTERM):
|
|
||||||
"""
|
|
||||||
helper function to ensure once parent process exits, its children processes will automatically die.
|
|
||||||
see: <https://stackoverflow.com/a/43152455>
|
|
||||||
see: <https://www.man7.org/linux/man-pages/man2/prctl.2.html>
|
|
||||||
"""
|
|
||||||
libc = ctypes.CDLL("libc.so.6")
|
|
||||||
return libc.prctl(1, sig)
|
|
||||||
|
|
||||||
MY_PID = None
|
|
||||||
|
|
||||||
def reap_children(sig=None, frame=None):
|
|
||||||
global MY_PID
|
|
||||||
# reset SIGTERM handler to avoid recursing
|
|
||||||
signal.signal(signal.SIGTERM, signal.Handlers.SIG_DFL)
|
|
||||||
logger.info("killing all children (of pid %d)", MY_PID)
|
|
||||||
os.killpg(MY_PID, signal.SIGTERM)
|
|
||||||
|
|
||||||
def reap_on_exit():
|
|
||||||
"""
|
|
||||||
catch when the parent exits, and map that to SIGTERM for this process.
|
|
||||||
when this process receives SIGTERM, also terminate all descendent processes.
|
|
||||||
|
|
||||||
this is done because:
|
|
||||||
1. mpv invokes this, but (potentially) via the sandbox wrapper.
|
|
||||||
2. when mpv exits, it `SIGKILL`s that sandbox wrapper.
|
|
||||||
3. bwrap does not pass SIGKILL or SIGTERM to its child.
|
|
||||||
4. hence, we neither receive that signal NOR can we pass it on simply by killing our immediate children
|
|
||||||
(since any bwrap'd children wouldn't pass that signal on...)
|
|
||||||
really, the proper fix would be on mpv's side:
|
|
||||||
- mpv should create a new process group when it launches a command, and kill that process group on exit.
|
|
||||||
or fix this in the sandbox wrapper:
|
|
||||||
- why *doesn't* bwrap forward the signals?
|
|
||||||
- there's --die-with-parent, but i can't apply that *system wide* and expect reasonably behavior
|
|
||||||
<https://github.com/containers/bubblewrap/issues/529>
|
|
||||||
"""
|
|
||||||
global MY_PID
|
|
||||||
MY_PID = os.getpid()
|
|
||||||
# create a new process group, pgid = gid
|
|
||||||
os.setpgid(MY_PID, MY_PID)
|
|
||||||
|
|
||||||
set_pdeathsig(signal.SIGTERM)
|
|
||||||
signal.signal(signal.SIGTERM, reap_children)
|
|
||||||
|
|
||||||
def get_ranked_ip_addrs():
|
def get_ranked_ip_addrs():
|
||||||
"""
|
"""
|
||||||
return the IP addresses most likely to be LAN addresses
|
return the IP addresses most likely to be LAN addresses
|
||||||
|
@ -96,8 +49,6 @@ class BlastDriver:
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
# this pdeathsig isn't necessary; seems it might result in leaked pulse outputs
|
|
||||||
# preexec_fn=set_pdeathsig
|
|
||||||
)
|
)
|
||||||
self.blast_flags = list(blast_flags)
|
self.blast_flags = list(blast_flags)
|
||||||
self.receiver_names = []
|
self.receiver_names = []
|
||||||
|
@ -202,15 +153,11 @@ def main():
|
||||||
logging.basicConfig()
|
logging.basicConfig()
|
||||||
logging.getLogger().setLevel(logging.DEBUG)
|
logging.getLogger().setLevel(logging.DEBUG)
|
||||||
|
|
||||||
reap_on_exit()
|
|
||||||
|
|
||||||
blast = try_blast()
|
blast = try_blast()
|
||||||
|
|
||||||
if blast is not None:
|
if blast is not None:
|
||||||
logger.info("waiting until blast exits")
|
logger.info("waiting until blast exits")
|
||||||
blast.blast.wait()
|
blast.blast.wait()
|
||||||
|
|
||||||
reap_children()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -39,12 +39,10 @@ in
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.whitelistAudio = true;
|
sandbox.whitelistAudio = true;
|
||||||
sandbox.net = "clearnet";
|
sandbox.net = "clearnet";
|
||||||
sandbox.extraConfig = [
|
#v else it fails to reap its children (or, maybe, it fails to hook its parent's death signal?)
|
||||||
# else it fails to reap its children (or, maybe, it fails to hook its parent's death signal?)
|
#v might be possible to remove this, but kinda hard to see a clean way.
|
||||||
# might be possible to remove this, but kinda hard to see a clean way.
|
sandbox.isolatePids = false;
|
||||||
"--sane-sandbox-keep-namespace" "pid"
|
suggestedPrograms = [ "blast-ugjka" "sane-die-with-parent" ];
|
||||||
];
|
|
||||||
suggestedPrograms = [ "blast-ugjka" ];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = lib.mkIf cfg.enabled [ 9000 ];
|
networking.firewall.allowedTCPPorts = lib.mkIf cfg.enabled [ 9000 ];
|
||||||
|
|
|
@ -99,28 +99,41 @@ in
|
||||||
type = types.listOf transitionType;
|
type = types.listOf transitionType;
|
||||||
default = [];
|
default = [];
|
||||||
};
|
};
|
||||||
configFile = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
default = pkgs.writeText "bonsai_tree.json" (builtins.toJSON cfg.config.transitions);
|
|
||||||
description = ''
|
|
||||||
configuration file to pass to bonsai.
|
|
||||||
usually auto-generated from the sibling options; exposed mainly for debugging or convenience.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
packageUnwrapped = pkgs.bonsai.overrideAttrs (upstream: {
|
||||||
|
# patch to place the socket in a subdirectory where it can be sandboxed
|
||||||
|
postPatch = (upstream.postPatch or "") + ''
|
||||||
|
substituteInPlace cmd/{bonsaictl,bonsaid}/main.ha \
|
||||||
|
--replace-fail 'path::set(&buf, statedir, "bonsai")' 'path::set(&buf, statedir, "bonsai/bonsai")'
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.".config/bonsai/bonsai_tree.json".symlink.text = builtins.toJSON cfg.config.transitions;
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.extraRuntimePaths = [
|
sandbox.extraRuntimePaths = [
|
||||||
"/" #< just needs "bonsai", but needs to create it first...
|
"bonsai"
|
||||||
];
|
];
|
||||||
|
|
||||||
services.bonsaid = {
|
services.bonsaid = {
|
||||||
description = "bonsai: programmable input dispatcher";
|
description = "bonsai: programmable input dispatcher";
|
||||||
|
dependencyOf = [ "sway" ]; # to ensure `$XDG_RUNTIME_DIR/bonsai` exists before sway binds it
|
||||||
partOf = [ "graphical-session" ];
|
partOf = [ "graphical-session" ];
|
||||||
command = "bonsaid -t ${cfg.config.configFile}";
|
# nice -n -11 chosen arbitrarily. i hope this will allow for faster response to inputs, but without audio underruns (pipewire is -21, dino -15-ish)
|
||||||
cleanupCommand = "rm -f $XDG_RUNTIME_DIR/bonsai";
|
command = pkgs.writeShellScript "bonsai-start" ''
|
||||||
|
# TODO: don't create the sway directory here!
|
||||||
|
# i do it for now because sway and bonsai call into eachother; circular dependency:
|
||||||
|
# - sway -> bonsai -> sane-input-handler -> swaymsg
|
||||||
|
mkdir -p $XDG_RUNTIME_DIR/{bonsai,sway}
|
||||||
|
exec nice -n -11 bonsaid -t $HOME/.config/bonsai/bonsai_tree.json
|
||||||
|
'';
|
||||||
|
cleanupCommand = "rm -f $XDG_RUNTIME_DIR/bonsai/bonsai";
|
||||||
|
readiness.waitExists = [
|
||||||
|
"$XDG_RUNTIME_DIR/bonsai/bonsai"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
"dev" # for developing anything web-related
|
"dev" # for developing anything web-related
|
||||||
"tmp"
|
"tmp"
|
||||||
];
|
];
|
||||||
|
sandbox.extraPaths = [
|
||||||
|
"/tmp" # needed particularly if run from `sane-vpn do`
|
||||||
|
];
|
||||||
sandbox.whitelistAudio = true;
|
sandbox.whitelistAudio = true;
|
||||||
sandbox.whitelistDri = true;
|
sandbox.whitelistDri = true;
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
|
|
23
hosts/common/programs/brightnessctl.nix
Normal file
23
hosts/common/programs/brightnessctl.nix
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs.brightnessctl;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.brightnessctl = {
|
||||||
|
sandbox.method = "landlock"; # also bwrap, but landlock is more responsive
|
||||||
|
sandbox.extraPaths = [
|
||||||
|
"/sys/class/backlight"
|
||||||
|
"/sys/class/leds"
|
||||||
|
"/sys/devices"
|
||||||
|
];
|
||||||
|
# sandbox.whitelistDbus = [ "system" ]; #< only necessary if not granting udev perms
|
||||||
|
};
|
||||||
|
|
||||||
|
services.udev.extraRules = let
|
||||||
|
chmod = "${pkgs.coreutils}/bin/chmod";
|
||||||
|
chown = "${pkgs.coreutils}/bin/chown";
|
||||||
|
in lib.mkIf cfg.enabled ''
|
||||||
|
# make backlight controllable by members of `video`
|
||||||
|
SUBSYSTEM=="backlight", RUN+="${chown} :video $sys$devpath/brightness", RUN+="${chmod} g+w $sys$devpath/brightness"
|
||||||
|
'';
|
||||||
|
}
|
26
hosts/common/programs/callaudiod.nix
Normal file
26
hosts/common/programs/callaudiod.nix
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# https://gitlab.com/mobian1/callaudiod
|
||||||
|
# device support:
|
||||||
|
# - moby:
|
||||||
|
# - mic muting works fine
|
||||||
|
# - speaker seems to have zero volume (maybe it's my alsa profiles?)
|
||||||
|
# - shows some failures when only the modem is online (no wifi)
|
||||||
|
# - gnome-calls doesn't even create an output audio stream, for example; and the other end of the call can't hear any mic.
|
||||||
|
# - desko: unsupported. no mic muting, etc.
|
||||||
|
# - "Card 'alsa_card.pci-0000_0b_00.1' lacks speaker and/or earpiece port, skipping"
|
||||||
|
# - "callaudiod-pulse-CRITICAL **: 07:45:48.092: No suitable card found, stopping here..."
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.programs.callaudiod = {
|
||||||
|
packageUnwrapped = pkgs.rmDbusServices pkgs.callaudiod;
|
||||||
|
|
||||||
|
# probably more needed once i enable proper sandboxing, but for now this ensures the service isn't started too early!
|
||||||
|
sandbox.whitelistAudio = true;
|
||||||
|
sandbox.whitelistDbus = [ "user" ];
|
||||||
|
|
||||||
|
services.callaudiod = {
|
||||||
|
description = "callaudiod: dbus service to switch audio profiles and mute microphone";
|
||||||
|
partOf = [ "default" ];
|
||||||
|
command = "callaudiod";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,20 +1,14 @@
|
||||||
# GNOME calls
|
# GNOME calls
|
||||||
# - <https://gitlab.gnome.org/GNOME/calls>
|
# - <https://gitlab.gnome.org/GNOME/calls>
|
||||||
# - both a dialer and a call handler.
|
# - both a dialer and a call handler.
|
||||||
# - uses callaudiod dbus package.
|
# - uses callaudiod dbus service.
|
||||||
#
|
#
|
||||||
# initial JMP.chat configuration:
|
# initial JMP.chat configuration:
|
||||||
# - message @cheogram.com "reset sip account" (this is not destructive, despite the name)
|
# - message @cheogram.com "reset sip account" (this is not destructive, despite the name)
|
||||||
# - 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 requires more chatting with the help bot
|
# - now gnome-calls can do outbound calls. inbound calls can be routed by messaging the bot: "configure calls"
|
||||||
#
|
{ config, lib, pkgs, ... }:
|
||||||
# my setup here is still very WIP.
|
|
||||||
# open questions:
|
|
||||||
# - can i receive calls even with GUI closed?
|
|
||||||
# - e.g. activated by callaudiod?
|
|
||||||
# - looks like `gnome-calls --daemon` does that?
|
|
||||||
{ config, lib, ... }:
|
|
||||||
let
|
let
|
||||||
cfg = config.sane.programs.calls;
|
cfg = config.sane.programs.calls;
|
||||||
in
|
in
|
||||||
|
@ -25,31 +19,52 @@ in
|
||||||
type = types.submodule {
|
type = types.submodule {
|
||||||
options.autostart = mkOption {
|
options.autostart = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
packageUnwrapped = pkgs.calls.overrideAttrs (upstream: {
|
||||||
|
patches = (upstream.patches or []) ++ [
|
||||||
|
(pkgs.fetchpatch {
|
||||||
|
# usability improvement... if the UI is visible, then i can receive calls. otherwise, i can't!
|
||||||
|
url = "https://git.uninsane.org/colin/gnome-calls/commit/a19166d85927e59662fae189a780eed18bf876ce.patch";
|
||||||
|
name = "exit on close (i.e. never daemonize)";
|
||||||
|
hash = "sha256-NoVQV2TlkCcsBt0uwSyK82hBKySUW4pADrJVfLFvWgU=";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
sandbox.method = "bwrap";
|
||||||
|
sandbox.net = "clearnet";
|
||||||
|
sandbox.whitelistAudio = true;
|
||||||
|
sandbox.whitelistDbus = [ "user" ]; # necessary for secrets, at the minimum
|
||||||
|
sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
persist.byStore.private = [
|
persist.byStore.private = [
|
||||||
# ".cache/folks" # contact avatars?
|
# ".cache/folks" # contact avatars?
|
||||||
# ".config/calls"
|
# ".config/calls"
|
||||||
".local/share/calls" # call "records"
|
".local/share/calls" # call "records"
|
||||||
# .local/share/folks # contacts?
|
# .local/share/folks # contacts?
|
||||||
];
|
];
|
||||||
|
# this is only the username/endpoint: the actual password appears to be stored in gnome-keyring
|
||||||
secrets.".config/calls/sip-account.cfg" = ../../../secrets/common/gnome_calls_sip-account.cfg.bin;
|
secrets.".config/calls/sip-account.cfg" = ../../../secrets/common/gnome_calls_sip-account.cfg.bin;
|
||||||
suggestedPrograms = [
|
suggestedPrograms = [
|
||||||
|
"callaudiod" # runtime dependency (optional, but probably needed for mic muting?)
|
||||||
"feedbackd" # needs `phone-incoming-call`, in particular
|
"feedbackd" # needs `phone-incoming-call`, in particular
|
||||||
|
"gnome-keyring" # to remember the password
|
||||||
];
|
];
|
||||||
|
|
||||||
services.gnome-calls = {
|
services.gnome-calls = {
|
||||||
# TODO: prevent gnome-calls from daemonizing when started manually
|
|
||||||
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" ];
|
||||||
# add --verbose for more debugging
|
# add --verbose for more debugging
|
||||||
command = "env G_MESSAGES_DEBUG=all gnome-calls --daemon";
|
# add --daemon to avoid showing UI on launch.
|
||||||
|
# note that no matter the flags, it returns to being a daemon whenever the UI is manually closed,
|
||||||
|
# revealed when launched.
|
||||||
|
# default latency is 10ms, which is too low and i get underruns on moby.
|
||||||
|
# 50ms is copied from dino, not at all tuned.
|
||||||
|
command = "env G_MESSAGES_DEBUG=all PULSE_LATENCY_MSEC=50 gnome-calls";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
programs.calls = lib.mkIf cfg.enabled {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
sane.programs.celeste64 = {
|
sane.programs.celeste64 = {
|
||||||
|
buildCost = 1;
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.whitelistAudio = true;
|
sandbox.whitelistAudio = true;
|
||||||
sandbox.whitelistDri = true;
|
sandbox.whitelistDri = true;
|
||||||
|
|
|
@ -1,7 +1,18 @@
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
|
sane.programs.sane-battery-estimate = {
|
||||||
|
packageUnwrapped = pkgs.static-nix-shell.mkBash {
|
||||||
|
pname = "sane-battery-estimate";
|
||||||
|
srcRoot = ./.;
|
||||||
|
};
|
||||||
|
sandbox.method = "bwrap";
|
||||||
|
sandbox.extraPaths = [
|
||||||
|
"/sys/class/power_supply"
|
||||||
|
"/sys/devices"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
sane.programs.conky = {
|
sane.programs.conky = {
|
||||||
# TODO: non-sandboxed `conky` still ships via `sxmo-utils`, but unused
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.net = "clearnet"; #< for the scripts it calls (weather)
|
sandbox.net = "clearnet"; #< for the scripts it calls (weather)
|
||||||
sandbox.extraPaths = [
|
sandbox.extraPaths = [
|
||||||
|
@ -12,18 +23,16 @@
|
||||||
];
|
];
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
fs.".config/conky/conky.conf".symlink.target =
|
suggestedPrograms = [
|
||||||
let
|
"sane-battery-estimate"
|
||||||
# TODO: make this just another `suggestedPrograms`!
|
"sane-weather"
|
||||||
battery_estimate = pkgs.static-nix-shell.mkBash {
|
];
|
||||||
pname = "battery_estimate";
|
|
||||||
srcRoot = ./.;
|
fs.".config/conky/conky.conf".symlink.target = pkgs.substituteAll {
|
||||||
};
|
src = ./conky.conf;
|
||||||
in pkgs.substituteAll {
|
bat = "sane-battery-estimate";
|
||||||
src = ./conky.conf;
|
weather = "timeout 20 sane-weather";
|
||||||
bat = "${battery_estimate}/bin/battery_estimate";
|
};
|
||||||
weather = "timeout 20 ${pkgs.sane-weather}/bin/sane-weather";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.conky = {
|
services.conky = {
|
||||||
description = "conky dynamic desktop background";
|
description = "conky dynamic desktop background";
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#!/bin/sh
|
|
||||||
#!/usr/bin/env nix-shell
|
#!/usr/bin/env nix-shell
|
||||||
#!nix-shell -i bash
|
#!nix-shell -i bash
|
||||||
|
|
||||||
|
@ -15,7 +14,7 @@ usage() {
|
||||||
echo " --percent-suffix <string>: use the provided string when displaying percents"
|
echo " --percent-suffix <string>: use the provided string when displaying percents"
|
||||||
}
|
}
|
||||||
|
|
||||||
# these icons come from sxmo; they only render in nerdfonts
|
# these icons may only render in nerdfonts
|
||||||
icon_bat_chg=("" "" "" "")
|
icon_bat_chg=("" "" "" "")
|
||||||
icon_bat_dis=("" "" "" "")
|
icon_bat_dis=("" "" "" "")
|
||||||
suffix_icon=" " # thin space
|
suffix_icon=" " # thin space
|
|
@ -13,6 +13,8 @@
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
buildCost = 1;
|
||||||
|
|
||||||
sandbox.method = "bwrap"; # landlock gives: _multiprocessing.SemLock: Permission Denied
|
sandbox.method = "bwrap"; # landlock gives: _multiprocessing.SemLock: Permission Denied
|
||||||
sandbox.whitelistAudio = true;
|
sandbox.whitelistAudio = true;
|
||||||
sandbox.whitelistDbus = [ "user" ]; # mpris
|
sandbox.whitelistDbus = [ "user" ]; # mpris
|
||||||
|
|
34
hosts/common/programs/cups.nix
Normal file
34
hosts/common/programs/cups.nix
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# docs: <https://wiki.nixos.org/wiki/Printing>
|
||||||
|
# to add a printer:
|
||||||
|
# 1. <http://localhost:631/admin/>
|
||||||
|
# 2. click "find new printers" and follow prompts
|
||||||
|
# - prefer to use the "Generic IPP Everywhere Printer" driver
|
||||||
|
# alternatively, add/modify printers by running
|
||||||
|
# - `system-config-printer`
|
||||||
|
{ config, lib, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs.cups;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.cups = {
|
||||||
|
suggestedPrograms = [
|
||||||
|
"system-config-printer"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
sane.programs.system-config-printer = {};
|
||||||
|
|
||||||
|
services.printing = lib.mkIf cfg.enabled {
|
||||||
|
enable = true;
|
||||||
|
startWhenNeeded = false; #< a.k.a. socket activated?
|
||||||
|
# webInterface = false;
|
||||||
|
# logLevel = "debug"; # default: "info"
|
||||||
|
# extraConfig = "<lines ... >";
|
||||||
|
# drivers = [ <cups driver packages...> ]
|
||||||
|
};
|
||||||
|
# services.avahi = lib.mkIf cfg.enabled {
|
||||||
|
# # only needed for wireless printing
|
||||||
|
# enable = true;
|
||||||
|
# nssmdns4 = true;
|
||||||
|
# openFirewall = true;
|
||||||
|
# };
|
||||||
|
}
|
|
@ -21,5 +21,15 @@
|
||||||
ln -s curlftpfs $out/bin/mount.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"
|
||||||
|
# ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
54
hosts/common/programs/dbus.nix
Normal file
54
hosts/common/programs/dbus.nix
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs.dissent;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.dbus = {
|
||||||
|
configOption = with lib; mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.submodule {
|
||||||
|
options.autostart = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
packageUnwrapped = (pkgs.dbus.override {
|
||||||
|
# remove features i don't want. mostly to avoid undesired interactions, but also it reduces the closure by 55 MB :)
|
||||||
|
enableSystemd = false;
|
||||||
|
x11Support = false;
|
||||||
|
}).overrideAttrs (upstream: {
|
||||||
|
postFixup = (upstream.postFixup or "") + ''
|
||||||
|
# the XML docs have a URI field which points to self,
|
||||||
|
# and that breaks the sandbox checker
|
||||||
|
substituteInPlace $out/share/xml/dbus-1/catalog.xml \
|
||||||
|
--replace-fail "$out" "/run/current-system/sw"
|
||||||
|
|
||||||
|
# conf file points to dbus-daemon-launch-helper by absolute path,
|
||||||
|
# which breaks sandboxing. i don't want dbus auto-launching stuff anyway though.
|
||||||
|
substituteInPlace $out/share/dbus-1/system.conf \
|
||||||
|
--replace-fail "$out/libexec/dbus-daemon-launch-helper" "false"
|
||||||
|
'';
|
||||||
|
});
|
||||||
|
|
||||||
|
sandbox.method = "bwrap";
|
||||||
|
sandbox.extraRuntimePaths = [
|
||||||
|
"/" #< it needs to create a file in the root. TODO: move the bus handle into a sandboxable subdirectory
|
||||||
|
];
|
||||||
|
sandbox.isolatePids = false; #< not actually sure *why* this is necessary, but it is
|
||||||
|
|
||||||
|
env.DBUS_SESSION_BUS_ADDRESS = "unix:path=$XDG_RUNTIME_DIR/bus";
|
||||||
|
|
||||||
|
# normally systemd would create a dbus session for us, but if you configure it not to do that
|
||||||
|
# then we can create our own. not sure if there's a dependency ordering issue here: lots
|
||||||
|
# of things depend on dbus but i don't do anything special to guarantee this is initialized
|
||||||
|
# before them.
|
||||||
|
services.dbus = {
|
||||||
|
description = "dbus user session";
|
||||||
|
partOf = lib.mkIf cfg.config.autostart [ "default" ];
|
||||||
|
command = "dbus-daemon --session --nofork --address=$DBUS_SESSION_BUS_ADDRESS";
|
||||||
|
readiness.waitExists = [ "$XDG_RUNTIME_DIR/bus" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -34,7 +34,7 @@ in
|
||||||
|
|
||||||
services.dconf = {
|
services.dconf = {
|
||||||
description = "dconf configuration database/server";
|
description = "dconf configuration database/server";
|
||||||
partOf = [ "graphical-session" ];
|
partOf = [ "default" ];
|
||||||
command = "${lib.getLib cfg.package}/libexec/dconf-service";
|
command = "${lib.getLib cfg.package}/libexec/dconf-service";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,14 @@
|
||||||
./animatch.nix
|
./animatch.nix
|
||||||
./assorted.nix
|
./assorted.nix
|
||||||
./audacity.nix
|
./audacity.nix
|
||||||
|
./ausyscall.nix
|
||||||
./bemenu.nix
|
./bemenu.nix
|
||||||
./blast-ugjka
|
./blast-ugjka
|
||||||
./bonsai.nix
|
./bonsai.nix
|
||||||
./brave.nix
|
./brave.nix
|
||||||
|
./brightnessctl.nix
|
||||||
./bubblewrap.nix
|
./bubblewrap.nix
|
||||||
|
./callaudiod.nix
|
||||||
./calls.nix
|
./calls.nix
|
||||||
./cantata.nix
|
./cantata.nix
|
||||||
./catt.nix
|
./catt.nix
|
||||||
|
@ -21,20 +24,24 @@
|
||||||
./chatty.nix
|
./chatty.nix
|
||||||
./conky
|
./conky
|
||||||
./cozy.nix
|
./cozy.nix
|
||||||
|
./cups.nix
|
||||||
./curlftpfs.nix
|
./curlftpfs.nix
|
||||||
|
./dbus.nix
|
||||||
./dconf.nix
|
./dconf.nix
|
||||||
./deadd-notification-center
|
./deadd-notification-center
|
||||||
./dialect.nix
|
./dialect.nix
|
||||||
./dino.nix
|
./dino.nix
|
||||||
./dissent.nix
|
./dissent.nix
|
||||||
|
./dtrx.nix
|
||||||
|
./eg25-control.nix
|
||||||
./element-desktop.nix
|
./element-desktop.nix
|
||||||
./engrampa.nix
|
./engrampa.nix
|
||||||
./epiphany.nix
|
./epiphany.nix
|
||||||
|
./errno.nix
|
||||||
./evince.nix
|
./evince.nix
|
||||||
./fcitx5.nix
|
./fcitx5.nix
|
||||||
./feedbackd.nix
|
./feedbackd.nix
|
||||||
./firefox.nix
|
./firefox.nix
|
||||||
./firejail.nix
|
|
||||||
./flare-signal.nix
|
./flare-signal.nix
|
||||||
./fontconfig.nix
|
./fontconfig.nix
|
||||||
./fractal.nix
|
./fractal.nix
|
||||||
|
@ -45,6 +52,7 @@
|
||||||
./gdbus.nix
|
./gdbus.nix
|
||||||
./geary.nix
|
./geary.nix
|
||||||
./git.nix
|
./git.nix
|
||||||
|
./gnome-clocks.nix
|
||||||
./gnome-feeds.nix
|
./gnome-feeds.nix
|
||||||
./gnome-keyring
|
./gnome-keyring
|
||||||
./gnome-maps.nix
|
./gnome-maps.nix
|
||||||
|
@ -52,7 +60,9 @@
|
||||||
./go2tv.nix
|
./go2tv.nix
|
||||||
./gpodder.nix
|
./gpodder.nix
|
||||||
./grimshot.nix
|
./grimshot.nix
|
||||||
|
./gst-device-monitor.nix
|
||||||
./gthumb.nix
|
./gthumb.nix
|
||||||
|
./gvfs.nix
|
||||||
./handbrake.nix
|
./handbrake.nix
|
||||||
./helix.nix
|
./helix.nix
|
||||||
./htop
|
./htop
|
||||||
|
@ -62,6 +72,7 @@
|
||||||
./komikku.nix
|
./komikku.nix
|
||||||
./koreader
|
./koreader
|
||||||
./less.nix
|
./less.nix
|
||||||
|
./lftp.nix
|
||||||
./libreoffice.nix
|
./libreoffice.nix
|
||||||
./lemoa.nix
|
./lemoa.nix
|
||||||
./loupe.nix
|
./loupe.nix
|
||||||
|
@ -69,17 +80,22 @@
|
||||||
./megapixels.nix
|
./megapixels.nix
|
||||||
./mepo.nix
|
./mepo.nix
|
||||||
./mimeo
|
./mimeo
|
||||||
|
./mmcli.nix
|
||||||
|
./modemmanager.nix
|
||||||
./mopidy.nix
|
./mopidy.nix
|
||||||
./mpv
|
./mpv
|
||||||
./msmtp.nix
|
./msmtp.nix
|
||||||
./nautilus.nix
|
./nautilus.nix
|
||||||
./neovim.nix
|
./neovim.nix
|
||||||
|
./networkmanager.nix
|
||||||
./newsflash.nix
|
./newsflash.nix
|
||||||
./nheko.nix
|
./nheko.nix
|
||||||
./nicotine-plus.nix
|
./nicotine-plus.nix
|
||||||
./nix-index.nix
|
./nix-index.nix
|
||||||
|
./nmcli.nix
|
||||||
./notejot.nix
|
./notejot.nix
|
||||||
./ntfy-sh.nix
|
./ntfy-sh.nix
|
||||||
|
./objdump.nix
|
||||||
./obsidian.nix
|
./obsidian.nix
|
||||||
./offlineimap.nix
|
./offlineimap.nix
|
||||||
./open-in-mpv.nix
|
./open-in-mpv.nix
|
||||||
|
@ -90,12 +106,18 @@
|
||||||
./rhythmbox.nix
|
./rhythmbox.nix
|
||||||
./ripgrep.nix
|
./ripgrep.nix
|
||||||
./rofi
|
./rofi
|
||||||
|
./rtkit.nix
|
||||||
./s6-rc.nix
|
./s6-rc.nix
|
||||||
./sane-input-handler
|
./sane-input-handler
|
||||||
|
./sane-open.nix
|
||||||
./sane-screenshot.nix
|
./sane-screenshot.nix
|
||||||
./sane-scripts.nix
|
./sane-scripts.nix
|
||||||
|
./sane-theme.nix
|
||||||
|
./sanebox.nix
|
||||||
./schlock.nix
|
./schlock.nix
|
||||||
|
./seatd.nix
|
||||||
./sfeed.nix
|
./sfeed.nix
|
||||||
|
./shadow.nix
|
||||||
./signal-desktop.nix
|
./signal-desktop.nix
|
||||||
./splatmoji.nix
|
./splatmoji.nix
|
||||||
./spot.nix
|
./spot.nix
|
||||||
|
@ -122,6 +144,7 @@
|
||||||
./wine.nix
|
./wine.nix
|
||||||
./wireplumber.nix
|
./wireplumber.nix
|
||||||
./wireshark.nix
|
./wireshark.nix
|
||||||
|
./wpa_supplicant.nix
|
||||||
./wvkbd.nix
|
./wvkbd.nix
|
||||||
./xarchiver.nix
|
./xarchiver.nix
|
||||||
./xdg-desktop-portal.nix
|
./xdg-desktop-portal.nix
|
||||||
|
@ -132,6 +155,7 @@
|
||||||
./zathura.nix
|
./zathura.nix
|
||||||
./zeal.nix
|
./zeal.nix
|
||||||
./zecwallet-lite.nix
|
./zecwallet-lite.nix
|
||||||
|
./zulip.nix
|
||||||
./zsh
|
./zsh
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,6 @@
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
sane.programs.dialect = {
|
sane.programs.dialect = {
|
||||||
sandbox.method = "bwrap";
|
|
||||||
sandbox.wrapperType = "inplace"; # share/search_providers/ calls back into the binary, weird wrap semantics
|
|
||||||
sandbox.whitelistWayland = true;
|
|
||||||
sandbox.net = "clearnet";
|
|
||||||
sandbox.extraHomePaths = [
|
|
||||||
".config/dconf" # won't start without it
|
|
||||||
];
|
|
||||||
suggestedPrograms = [ "dconf" ]; #< to persist settings
|
|
||||||
|
|
||||||
packageUnwrapped = pkgs.dialect.overrideAttrs (upstream: {
|
packageUnwrapped = pkgs.dialect.overrideAttrs (upstream: {
|
||||||
# TODO: send upstream
|
# TODO: send upstream
|
||||||
# TODO: figure out how to get audio working
|
# TODO: figure out how to get audio working
|
||||||
|
@ -18,5 +9,17 @@
|
||||||
pkgs.glib-networking # for TLS
|
pkgs.glib-networking # for TLS
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
suggestedPrograms = [ "dconf" ]; #< to persist settings
|
||||||
|
|
||||||
|
buildCost = 1;
|
||||||
|
|
||||||
|
sandbox.method = "bwrap";
|
||||||
|
sandbox.wrapperType = "inplace"; # share/search_providers/ calls back into the binary, weird wrap semantics
|
||||||
|
sandbox.whitelistWayland = true;
|
||||||
|
sandbox.net = "clearnet";
|
||||||
|
sandbox.extraHomePaths = [
|
||||||
|
".config/dconf" # won't start without it
|
||||||
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,17 +22,17 @@
|
||||||
# - mic is sometimes disabled at call start despite presenting as enabled
|
# - mic is sometimes disabled at call start despite presenting as enabled
|
||||||
# - fix is to toggle it off -> on in the Dino UI
|
# - fix is to toggle it off -> on in the Dino UI
|
||||||
# - default mic gain is WAY TOO MUCH (heavily distorted)
|
# - default mic gain is WAY TOO MUCH (heavily distorted)
|
||||||
# - TODO: dino should have more optimal niceness/priority to ensure it can process its buffers
|
# - on lappy/desktop, right-clicking the mic button allows to toggle audio devices, but impossible to trigger this on moby/touch screen!
|
||||||
# - possibly this is solved by enabling RealtimeKit (rtkit)
|
|
||||||
# - TODO: see if Dino calls work better with `echo full > /sys/kernel/debug/sched/preempt`
|
# - TODO: see if Dino calls work better with `echo full > /sys/kernel/debug/sched/preempt`
|
||||||
#
|
#
|
||||||
# probably fixed:
|
# probably fixed:
|
||||||
# - once per 1-2 minutes dino will temporarily drop mic input:
|
# - once per 1-2 minutes dino will temporarily drop mic input:
|
||||||
# - `rtp-WRNING: plugin.vala:148: Warning in pipeline: Can't record audio fast enough
|
# - `rtp-WARNING: plugin.vala:148: Warning in pipeline: Can't record audio fast enough
|
||||||
# - this was *partially* fixed by bumping the pipewire mic buffer to 2048 samples (from ~512)
|
# - this was *partially* fixed by bumping the pipewire mic buffer to 2048 samples (from ~512)
|
||||||
# - this was further fixed by setting PULSE_LATENCY_MSEC=20.
|
# - this was further fixed by setting PULSE_LATENCY_MSEC=20.
|
||||||
# - possibly Dino should be updated internally: `info.rate / 100` -> `info.rate / 50`.
|
# - possibly Dino should be updated internally: `info.rate / 100` -> `info.rate / 50`.
|
||||||
# - i think that affects the batching for echo cancellation, adaptive gain control, etc.
|
# - i think that affects the batching for echo cancellation, adaptive gain control, etc.
|
||||||
|
# - dino *should* be able to use Pipewire directly for calls instead of going through pulse, but had trouble achieving that in actuality
|
||||||
#
|
#
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
let
|
let
|
||||||
|
@ -50,16 +50,25 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
packageUnwrapped = pkgs.dino.overrideAttrs (upstream: {
|
packageUnwrapped = (pkgs.dino.override {
|
||||||
|
# XXX(2024/04/24): build without echo cancelation (i.e. force WITH_VOICE_PROCESSOR to be undefined).
|
||||||
|
# this means that if the other end of the call is on speaker phone, i'm liable to hear my own voice
|
||||||
|
# leave their speaker, enter their mic, and then return to me.
|
||||||
|
# the benefit is a >50% reduction in CPU use. insignificant on any modern PC; make-or-break on a low-power Pinephone.
|
||||||
|
webrtc-audio-processing = null;
|
||||||
|
}).overrideAttrs (upstream: {
|
||||||
# i'm updating experimentally to see if it improves call performance.
|
# i'm updating experimentally to see if it improves call performance.
|
||||||
# i don't *think* this is actually necessary; i don't notice any difference.
|
# i don't *think* this is actually necessary; i don't notice any difference.
|
||||||
version = "0.4.3-unstable-2024-04-01";
|
version = "0.4.3-unstable-2024-04-28";
|
||||||
src = lib.warnIf (lib.versionOlder "0.4.3" upstream.version) "dino update: safe to remove sane patches" pkgs.fetchFromGitHub {
|
src = lib.warnIf (lib.versionOlder "0.4.3" upstream.version) "dino update: safe to remove sane patches" pkgs.fetchFromGitHub {
|
||||||
owner = "dino";
|
owner = "dino";
|
||||||
repo = "dino";
|
repo = "dino";
|
||||||
rev = "d9fa4daa6a7d16f5f0e2183a77ee2d07849dd9f3";
|
rev = "657502955567dd538e56f300e075c7db52e25d74";
|
||||||
hash = "sha256-vJBIMsMLlK8Aw19fD2aFNtegXkjOqEgb3m1hi3fE5DE=";
|
hash = "sha256-SApJy9FgxxLOB5A/zGtpdFZtSqSiS03vggRrCte1tFE=";
|
||||||
};
|
};
|
||||||
|
# avoid double-application of upstreamed patches
|
||||||
|
# https://github.com/NixOS/nixpkgs/pull/309265
|
||||||
|
patches = [];
|
||||||
checkPhase = ''
|
checkPhase = ''
|
||||||
runHook preCheck
|
runHook preCheck
|
||||||
./xmpp-vala-test
|
./xmpp-vala-test
|
||||||
|
@ -96,17 +105,29 @@ in
|
||||||
# audio buffering; see: <https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/FAQ#pipewire-buffering-explained>
|
# audio buffering; see: <https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/FAQ#pipewire-buffering-explained>
|
||||||
# dino defaults to 10ms mic buffer, which causes underruns, which Dino handles *very* poorly
|
# dino defaults to 10ms mic buffer, which causes underruns, which Dino handles *very* poorly
|
||||||
# as in, the other end of the call will just not receive sound from us for a couple seconds.
|
# as in, the other end of the call will just not receive sound from us for a couple seconds.
|
||||||
# pipewire uses power-of-two buffering for the mic itself. that would put us at 21.33 ms, but this env var supports only whole numbers (21ms ends up not power-of-two).
|
# pipewire uses power-of-two buffering for the mic itself (by default), but this env var supports only whole numbers, which isn't quite reconcilable:
|
||||||
# also, Dino's likely still doing things in 10ms batches internally anyway.
|
# - 1024/48000 = 21.33ms
|
||||||
|
# - 2048/48000 = 42.67ms
|
||||||
|
# - 4096/48000 = 85.33ms
|
||||||
|
# also, Dino's likely still doing things in 10ms batches internally.
|
||||||
|
#
|
||||||
|
# note that this number supposedly is just the buffer size which Dino asks Pulse (pipewire) to share with it.
|
||||||
|
# in theory, it's equivalent to adjusting pipewire's quanta setting, and so isn't additive to the existing pipewire buffers.
|
||||||
|
# (and would also be overriden by pipewire's quanta.min setting).
|
||||||
|
# but in practice, setting this seems to have some more effect beyond just the buffer sizes visible in `pw-top`.
|
||||||
#
|
#
|
||||||
# further: decrease the "niceness" of dino, so that it can take precedence over anything else.
|
# further: decrease the "niceness" of dino, so that it can take precedence over anything else.
|
||||||
# ideally this would target just the audio processing, rather than the whole program.
|
# ideally this would target just the audio processing, rather than the whole program.
|
||||||
# pipewire is the equivalent of `nice -n -21`, so probably don't want to go any more extreme than that.
|
# pipewire is the equivalent of `nice -n -21`, so probably don't want to go any more extreme than that.
|
||||||
# nice -n -15 chosen arbitrarily; not optimized
|
# nice -n -15 chosen arbitrarily; not optimized (and seems to have very little impact in practice anyway).
|
||||||
|
# buffer size:
|
||||||
|
# - 1024 (PULSE_LATENCY_MSEC=20): `pw-top` shows several underruns per second.
|
||||||
|
# - 2048 (PULSE_LATENCY_MSEC=50): `pw-top` shows very few underruns: maybe 1-5 per minute. with voice processor disabled, this works well. with it enabled, i still get gaps in which the mic "disappears".
|
||||||
|
# - 4096 (PULSE_LATENCY_MSEC=100): `pw-top` shows 0 underruns. with voice processor disabled, i seem to be permanently muted. with it enabled, this works well.
|
||||||
#
|
#
|
||||||
# note that debug logging during calls produces so much journal spam that it pegs the CPU and causes dropped audio
|
# note that debug logging during calls produces so much journal spam that it pegs the CPU and causes dropped audio
|
||||||
# env G_MESSAGES_DEBUG = "all";
|
# env G_MESSAGES_DEBUG = "all";
|
||||||
command = "env PULSE_LATENCY_MSEC=20 nice -n -15 dino";
|
command = "env PULSE_LATENCY_MSEC=50 nice -n -15 dino";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
16
hosts/common/programs/dtrx.nix
Normal file
16
hosts/common/programs/dtrx.nix
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.programs.dtrx = {
|
||||||
|
packageUnwrapped = pkgs.dtrx.override {
|
||||||
|
# `binutils` is the nix wrapper, which reads nix-related env vars
|
||||||
|
# before passing on to e.g. `ld`.
|
||||||
|
# dtrx probably only needs `ar` at runtime, not even `ld`.
|
||||||
|
binutils = pkgs.binutils-unwrapped;
|
||||||
|
# build without rpm support, since `rpm` package doesn't cross-compile.
|
||||||
|
rpm = null;
|
||||||
|
};
|
||||||
|
sandbox.method = "bwrap";
|
||||||
|
sandbox.whitelistPwd = true;
|
||||||
|
sandbox.autodetectCliPaths = "existing"; #< for the archive
|
||||||
|
};
|
||||||
|
}
|
58
hosts/common/programs/eg25-control.nix
Normal file
58
hosts/common/programs/eg25-control.nix
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs.eg25-control;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.eg25-control = {
|
||||||
|
suggestedPrograms = [ "modemmanager" ];
|
||||||
|
|
||||||
|
services.eg25-control-powered = {
|
||||||
|
description = "eg25-control-powered: power to the Qualcomm eg25 modem used by PinePhone";
|
||||||
|
startCommand = "eg25-control --power-on --verbose";
|
||||||
|
cleanupCommand = "eg25-control --power-off --verbose";
|
||||||
|
# depends = [ "ModemManager" ]
|
||||||
|
};
|
||||||
|
|
||||||
|
services.eg25-control-gps = {
|
||||||
|
# TODO: separate almanac upload from GPS enablement
|
||||||
|
# - don't want to re-upload the almanac everytime the GPS is toggled
|
||||||
|
# - want to upload almanac even when GPS *isn't* enabled, if we have internet connection.
|
||||||
|
description = "eg25-control-gps: background GPS tracking";
|
||||||
|
startCommand = "eg25-control --enable-gps --dump-debug-info --verbose";
|
||||||
|
cleanupCommand = "eg25-control --disable-gps --dump-debug-info --verbose";
|
||||||
|
depends = [ "eg25-control-powered" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
persist.byStore.plaintext = [ ".cache/eg25-control" ]; #< for cached agps data
|
||||||
|
};
|
||||||
|
|
||||||
|
# TODO: port to s6
|
||||||
|
systemd.services.eg25-control-freshen-agps = lib.mkIf cfg.enabled {
|
||||||
|
description = "keep assisted-GPS data fresh";
|
||||||
|
serviceConfig = {
|
||||||
|
# XXX: this can have a race condition with eg25-control-gps
|
||||||
|
# - eg25-control-gps initiates DL of new/<agps>
|
||||||
|
# - eg25-control-gps tests new/<agps>: it works
|
||||||
|
# - eg25-control-freshen-agps initiates DL of new/<agps>
|
||||||
|
# - eg25-control-gps: moves new/<agps> into cache/
|
||||||
|
# - but it moved the result (possibly incomplete) of eg25-control-freshen-agps, incorrectly
|
||||||
|
# in practice, i don't expect much issue from this.
|
||||||
|
ExecStart = "${cfg.package}/bin/eg25-control --ensure-agps-cache --verbose";
|
||||||
|
Restart = "no";
|
||||||
|
|
||||||
|
User = "colin";
|
||||||
|
};
|
||||||
|
startAt = "hourly"; # this is a bit more than necessary, but idk systemd calendar syntax
|
||||||
|
after = [ "network-online.target" "nss-lookup.target" ];
|
||||||
|
requires = [ "network-online.target" ];
|
||||||
|
# wantedBy = [ "network-online.target" ]; # auto-start immediately after boot
|
||||||
|
};
|
||||||
|
|
||||||
|
services.udev.extraRules = let
|
||||||
|
chmod = "${pkgs.coreutils}/bin/chmod";
|
||||||
|
chown = "${pkgs.coreutils}/bin/chown";
|
||||||
|
in lib.optionalString cfg.enabled ''
|
||||||
|
# make Modem controllable by user
|
||||||
|
DRIVER=="modem-power", RUN+="${chmod} g+w /sys%p/powered", RUN+="${chown} :networkmanager /sys%p/powered"
|
||||||
|
'';
|
||||||
|
}
|
|
@ -9,7 +9,7 @@
|
||||||
sane.programs.element-desktop = {
|
sane.programs.element-desktop = {
|
||||||
packageUnwrapped = (pkgs.element-desktop.override {
|
packageUnwrapped = (pkgs.element-desktop.override {
|
||||||
# use pre-built electron because otherwise it takes 4 hrs to build from source.
|
# use pre-built electron because otherwise it takes 4 hrs to build from source.
|
||||||
electron = pkgs.electron_28-bin;
|
electron = pkgs.electron-bin;
|
||||||
}).overrideAttrs (upstream: {
|
}).overrideAttrs (upstream: {
|
||||||
# fix to use wayland instead of Xwayland:
|
# fix to use wayland instead of Xwayland:
|
||||||
# - replace `NIXOS_OZONE_WL` non-empty check with `WAYLAND_DISPLAY`
|
# - replace `NIXOS_OZONE_WL` non-empty check with `WAYLAND_DISPLAY`
|
||||||
|
@ -25,6 +25,8 @@
|
||||||
"gnome-keyring"
|
"gnome-keyring"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
buildCost = 1;
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.net = "clearnet";
|
sandbox.net = "clearnet";
|
||||||
sandbox.whitelistAudio = true;
|
sandbox.whitelistAudio = true;
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
"tmp"
|
"tmp"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
buildCost = 2;
|
||||||
|
|
||||||
# XXX(2023/07/08): running on moby without `WEBKIT_DISABLE_SANDBOX...` fails, with:
|
# XXX(2023/07/08): running on moby without `WEBKIT_DISABLE_SANDBOX...` fails, with:
|
||||||
# - `bwrap: Can't make symlink at /var/run: File exists`
|
# - `bwrap: Can't make symlink at /var/run: File exists`
|
||||||
# this could be due to:
|
# this could be due to:
|
||||||
|
|
21
hosts/common/programs/errno.nix
Normal file
21
hosts/common/programs/errno.nix
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.programs.errno = {
|
||||||
|
# packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.moreutils "bin/errno";
|
||||||
|
# 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: {
|
||||||
|
makeFlags = (base.makeFlags or []) ++ [
|
||||||
|
"BINS=errno"
|
||||||
|
"MANS=errno.1"
|
||||||
|
"PERLSCRIPTS=errno" #< Makefile errors if empty, but this works :)
|
||||||
|
"INSTALL_BIN=install"
|
||||||
|
];
|
||||||
|
#v disable the perl-specific stuff
|
||||||
|
propagatedBuildInputs = [];
|
||||||
|
postInstall = "";
|
||||||
|
});
|
||||||
|
|
||||||
|
sandbox.method = "landlock";
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
sane.programs.evince = {
|
sane.programs.evince = {
|
||||||
|
buildCost = 1;
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.autodetectCliPaths = true;
|
sandbox.autodetectCliPaths = "existingFile";
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
mime.associations."application/pdf" = "org.gnome.Evince.desktop";
|
mime.associations."application/pdf" = "org.gnome.Evince.desktop";
|
||||||
|
|
|
@ -207,6 +207,10 @@ in
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
i-still-dont-care-about-cookies = {
|
||||||
|
package = pkgs.firefox-extensions.i-still-dont-care-about-cookies;
|
||||||
|
enable = lib.mkDefault false; #< obsoleted by uBlock Origin annoyances/cookies lists
|
||||||
|
};
|
||||||
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;
|
||||||
|
@ -222,7 +226,7 @@ in
|
||||||
};
|
};
|
||||||
ublacklist = {
|
ublacklist = {
|
||||||
package = pkgs.firefox-extensions.ublacklist;
|
package = pkgs.firefox-extensions.ublacklist;
|
||||||
enable = lib.mkDefault true;
|
enable = lib.mkDefault false;
|
||||||
};
|
};
|
||||||
ublock-origin = {
|
ublock-origin = {
|
||||||
package = pkgs.firefox-extensions.ublock-origin;
|
package = pkgs.firefox-extensions.ublock-origin;
|
||||||
|
@ -282,24 +286,35 @@ in
|
||||||
# env.BROWSER = "${package}/bin/${cfg.browser.libName}";
|
# env.BROWSER = "${package}/bin/${cfg.browser.libName}";
|
||||||
env.BROWSER = cfg.browser.libName; # used by misc tools like xdg-email, as fallback
|
env.BROWSER = cfg.browser.libName; # used by misc tools like xdg-email, as fallback
|
||||||
|
|
||||||
# uBlock filter list configuration.
|
# uBlock configuration:
|
||||||
# specifically, enable the GDPR cookie prompt blocker.
|
fs."${cfg.browser.dotDir}/managed-storage/uBlock0@raymondhill.net.json".symlink.target = cfg.addons.ublock-origin.package.makeConfig {
|
||||||
# data.toOverwrite.filterLists is additive (i.e. it supplements the default filters)
|
# more filter lists are available here:
|
||||||
# this configuration method is documented here:
|
# - <https://easylist.to>
|
||||||
# - <https://github.com/gorhill/uBlock/issues/2986#issuecomment-364035002>
|
# - <https://github.com/easylist/easylist.git>
|
||||||
# the specific attribute path is found via scraping ublock code here:
|
# - <https://github.com/yokoffing/filterlists>
|
||||||
# - <https://github.com/gorhill/uBlock/blob/master/src/js/storage.js>
|
filterFiles = let
|
||||||
# - <https://github.com/gorhill/uBlock/blob/master/assets/assets.json>
|
getUasset = n: "${pkgs.uassets}/share/filters/${n}.txt";
|
||||||
fs."${cfg.browser.dotDir}/managed-storage/uBlock0@raymondhill.net.json".symlink.text = ''
|
in [
|
||||||
{
|
# default ublock filters:
|
||||||
"name": "uBlock0@raymondhill.net",
|
(getUasset "ublock-filters")
|
||||||
"description": "ignored",
|
(getUasset "ublock-badware")
|
||||||
"type": "storage",
|
(getUasset "ublock-privacy")
|
||||||
"data": {
|
(getUasset "ublock-quick-fixes")
|
||||||
"toOverwrite": "{\"filterLists\": [\"fanboy-cookiemonster\"]}"
|
(getUasset "ublock-unbreak")
|
||||||
}
|
(getUasset "easylist")
|
||||||
}
|
(getUasset "easyprivacy")
|
||||||
'';
|
# (getUasset "urlhaus-1") #< TODO: i think this is the same as urlhaus-filter-online
|
||||||
|
(getUasset "urlhaus-filter-online")
|
||||||
|
# (getUasset "plowe-0") #< TODO: where does this come from?
|
||||||
|
# (getUasset "ublock-cookies-adguard") #< TODO: where does this come from?
|
||||||
|
# filters i've added:
|
||||||
|
(getUasset "easylist-annoyances") #< blocks in-page popups, "social media content" (e.g. FB like button; improves loading time)
|
||||||
|
(getUasset "easylist-cookies") #< blocks GDPR cookie consent popovers (e.g. at stackoverflow.com)
|
||||||
|
# (getUasset "ublock-annoyances-others")
|
||||||
|
# (getUasset "ublock-annoyances-cookies")
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
# TODO: this is better suited in `extraPrefs` during `wrapFirefox` call
|
# TODO: this is better suited in `extraPrefs` during `wrapFirefox` call
|
||||||
fs."${cfg.browser.dotDir}/${cfg.browser.libName}.overrides.cfg".symlink.text = ''
|
fs."${cfg.browser.dotDir}/${cfg.browser.libName}.overrides.cfg".symlink.text = ''
|
||||||
// if we can't query the revocation status of a SSL cert because the issuer is offline,
|
// if we can't query the revocation status of a SSL cert because the issuer is offline,
|
||||||
|
@ -310,8 +325,8 @@ in
|
||||||
// scrollbar configuration, see: <https://artemis.sh/2023/10/12/scrollbars.html>
|
// scrollbar configuration, see: <https://artemis.sh/2023/10/12/scrollbars.html>
|
||||||
// style=4 gives rectangular scrollbars
|
// style=4 gives rectangular scrollbars
|
||||||
// could also enable "always show scrollbars" in about:preferences -- not sure what the actual pref name for that is
|
// could also enable "always show scrollbars" in about:preferences -- not sure what the actual pref name for that is
|
||||||
// note that too-large scrollbars (like 50px wide) tend to obscure content (and make buttons unclickable)
|
// note that too-large scrollbars (like 50px wide, even 20px) tend to obscure content (and make buttons unclickable)
|
||||||
defaultPref("widget.non-native-theme.scrollbar.size.override", 20);
|
defaultPref("widget.non-native-theme.scrollbar.size.override", 14);
|
||||||
defaultPref("widget.non-native-theme.scrollbar.style", 4);
|
defaultPref("widget.non-native-theme.scrollbar.style", 4);
|
||||||
|
|
||||||
// disable inertial/kinetic/momentum scrolling because it just gets in the way on touchpads
|
// disable inertial/kinetic/momentum scrolling because it just gets in the way on touchpads
|
||||||
|
@ -323,6 +338,8 @@ in
|
||||||
defaultPref("widget.use-xdg-desktop-portal.open-uri", 1);
|
defaultPref("widget.use-xdg-desktop-portal.open-uri", 1);
|
||||||
|
|
||||||
defaultPref("browser.toolbars.bookmarks.visibility", "never");
|
defaultPref("browser.toolbars.bookmarks.visibility", "never");
|
||||||
|
// configure which extensions are visible by default (TODO: requires a lot of trial and error)
|
||||||
|
// defaultPref("browser.uiCustomization.state", ...);
|
||||||
|
|
||||||
// auto-open mpv:// URIs without prompting.
|
// auto-open mpv:// URIs without prompting.
|
||||||
// can do this with other protocols too (e.g. matrix?). see about:config for common handlers.
|
// can do this with other protocols too (e.g. matrix?). see about:config for common handlers.
|
||||||
|
@ -347,7 +364,7 @@ in
|
||||||
|
|
||||||
# TODO: env.PASSWORD_STORE_DIR only needs to be present within the browser session.
|
# TODO: env.PASSWORD_STORE_DIR only needs to be present within the browser session.
|
||||||
env.PASSWORD_STORE_DIR = "/home/colin/knowledge/secrets/accounts";
|
env.PASSWORD_STORE_DIR = "/home/colin/knowledge/secrets/accounts";
|
||||||
# alternative to PASSWORD_STORE_DIR, but firejail doesn't handle this symlink well
|
# alternative to PASSWORD_STORE_DIR:
|
||||||
# fs.".password-store".symlink.target = lib.mkIf cfg.addons.browserpass-extension.enable "knowledge/secrets/accounts";
|
# fs.".password-store".symlink.target = lib.mkIf cfg.addons.browserpass-extension.enable "knowledge/secrets/accounts";
|
||||||
|
|
||||||
# flush the cache to disk to avoid it taking up too much tmp.
|
# flush the cache to disk to avoid it taking up too much tmp.
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
{ lib, config, ... }:
|
|
||||||
{
|
|
||||||
sane.programs.firejail = {};
|
|
||||||
|
|
||||||
programs.firejail = lib.mkIf config.sane.programs.firejail.enabled {
|
|
||||||
enable = true; #< install the suid binary
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -16,13 +16,11 @@ let
|
||||||
# - (message bubble)
|
# - (message bubble)
|
||||||
# - (phone)
|
# - (phone)
|
||||||
# - (weather/sun-behind-clouds)
|
# - (weather/sun-behind-clouds)
|
||||||
# used particularly by sxmo utilities, but also a few of my own (e.g. conky)
|
# i use these icons mostly in conky, swaync.
|
||||||
#
|
#
|
||||||
# nerdfonts is very heavy. each font is 20-900 MiB (2 MiB per "variation")
|
# nerdfonts is very heavy. each font is 20-900 MiB (2 MiB per "variation")
|
||||||
# lots of redundant data inside there, but no deduplication except whatever nix or the fs does implicitly.
|
# lots of redundant data inside there, but no deduplication except whatever nix or the fs does implicitly.
|
||||||
wantedNerdfonts = [
|
wantedNerdfonts = [
|
||||||
# used explicitly by SXMO
|
|
||||||
# "DejaVuSansMono" # 25 MiB
|
|
||||||
# good terminal/coding font. grab via nerdfonts for more emoji/unicode support
|
# good terminal/coding font. grab via nerdfonts for more emoji/unicode support
|
||||||
"Hack" # 26 MiB
|
"Hack" # 26 MiB
|
||||||
"Noto" # 861 MiB
|
"Noto" # 861 MiB
|
||||||
|
@ -30,6 +28,30 @@ let
|
||||||
nerdfontPkgs = builtins.map
|
nerdfontPkgs = builtins.map
|
||||||
(f: pkgs.nerdfonts.override { fonts = [ f ]; })
|
(f: pkgs.nerdfonts.override { fonts = [ f ]; })
|
||||||
wantedNerdfonts;
|
wantedNerdfonts;
|
||||||
|
|
||||||
|
# see: <repo:nixos/nixpkgs:nixos/modules/config/fonts/fontconfig.nix>
|
||||||
|
# and: <repo:nixos/nixpkgs:pkgs/development/libraries/fontconfig/make-fonts-cache.nix>
|
||||||
|
# nixpkgs creates a fontconfig cache, but only when *not* cross compiling.
|
||||||
|
# but the alternative is that fonts are cached purely at runtime, in ~/.cache/fontconfig,
|
||||||
|
# and that needs to either be added to the sandbox of *every* app,
|
||||||
|
# or font-heavy apps are several *seconds* slower to launch.
|
||||||
|
#
|
||||||
|
# TODO: upstream this into `make-fonts-cache.nix`?
|
||||||
|
cache = (pkgs.makeFontsCache { fontDirectories = config.fonts.packages; }).overrideAttrs (upstream: {
|
||||||
|
buildCommand = lib.replaceStrings
|
||||||
|
[ "fc-cache" ]
|
||||||
|
[ "${pkgs.stdenv.hostPlatform.emulator pkgs.buildPackages} ${pkgs.fontconfig.bin}/bin/fc-cache" ]
|
||||||
|
upstream.buildCommand
|
||||||
|
;
|
||||||
|
});
|
||||||
|
cacheConf = pkgs.writeTextDir "etc/fonts/conf.d/01-nixos-cache-cross.conf" ''
|
||||||
|
<?xml version='1.0'?>
|
||||||
|
<!DOCTYPE fontconfig SYSTEM 'urn:fontconfig:fonts.dtd'>
|
||||||
|
<fontconfig>
|
||||||
|
<!-- Pre-generated font caches -->
|
||||||
|
<cachedir>${cache}</cachedir>
|
||||||
|
</fontconfig>
|
||||||
|
'';
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
sane.programs.fontconfig = {
|
sane.programs.fontconfig = {
|
||||||
|
@ -64,6 +86,8 @@ in
|
||||||
"DejaVu Sans"
|
"DejaVu Sans"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
# nixpkgs builds a cache file, but only for non-cross. i want it always, so add my own cache -- but ONLY for cross.
|
||||||
|
fontconfig.confPackages = lib.mkIf (pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform) [ cacheConf ];
|
||||||
#vvv enables dejavu_fonts, freefont_ttf, gyre-fonts, liberation_ttf, unifont, noto-fonts-emoji
|
#vvv enables dejavu_fonts, freefont_ttf, gyre-fonts, liberation_ttf, unifont, noto-fonts-emoji
|
||||||
enableDefaultPackages = false;
|
enableDefaultPackages = false;
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
|
|
|
@ -24,8 +24,7 @@ in
|
||||||
{
|
{
|
||||||
sane.programs.fractal = {
|
sane.programs.fractal = {
|
||||||
packageUnwrapped = pkgs.fractal-nixified.optimized;
|
packageUnwrapped = pkgs.fractal-nixified.optimized;
|
||||||
# packageUnwrapped = pkgs.fractal-latest;
|
# packageUnwrapped = pkgs.fractal;
|
||||||
# packageUnwrapped = pkgs.fractal-next;
|
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.net = "clearnet";
|
sandbox.net = "clearnet";
|
||||||
|
|
|
@ -2,11 +2,6 @@
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
sane.programs.frozen-bubble = {
|
sane.programs.frozen-bubble = {
|
||||||
sandbox.method = "bwrap";
|
|
||||||
sandbox.net = "clearnet"; # net play
|
|
||||||
sandbox.whitelistAudio = true;
|
|
||||||
sandbox.whitelistWayland = true;
|
|
||||||
|
|
||||||
packageUnwrapped = pkgs.frozen-bubble.overrideAttrs (upstream: {
|
packageUnwrapped = pkgs.frozen-bubble.overrideAttrs (upstream: {
|
||||||
# patch so it stores its dot-files not in root ~.
|
# patch so it stores its dot-files not in root ~.
|
||||||
postPatch = (upstream.postPatch or "") + ''
|
postPatch = (upstream.postPatch or "") + ''
|
||||||
|
@ -14,6 +9,12 @@
|
||||||
--replace-fail '$FBHOME = "$ENV{HOME}/.frozen-bubble"' '$FBHOME = "$ENV{HOME}/.local/share/frozen-bubble"'
|
--replace-fail '$FBHOME = "$ENV{HOME}/.frozen-bubble"' '$FBHOME = "$ENV{HOME}/.local/share/frozen-bubble"'
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
|
buildCost = 1;
|
||||||
|
|
||||||
|
sandbox.method = "bwrap";
|
||||||
|
sandbox.net = "clearnet"; # net play
|
||||||
|
sandbox.whitelistAudio = true;
|
||||||
|
sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
persist.byStore.plaintext = [
|
persist.byStore.plaintext = [
|
||||||
".local/share/frozen-bubble" # preferences, high scores
|
".local/share/frozen-bubble" # preferences, high scores
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
sane.programs.g4music = {
|
sane.programs.g4music = {
|
||||||
|
buildCost = 1;
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.whitelistAudio = true;
|
sandbox.whitelistAudio = true;
|
||||||
sandbox.whitelistDbus = [ "user" ]; # mpris
|
sandbox.whitelistDbus = [ "user" ]; # mpris
|
||||||
|
|
|
@ -37,7 +37,7 @@ in
|
||||||
# fs.".config/geary".dir = {};
|
# fs.".config/geary".dir = {};
|
||||||
# fs.".local/share/folks".dir = {};
|
# fs.".local/share/folks".dir = {};
|
||||||
|
|
||||||
slowToBuild = true; # uses webkitgtk 4.1
|
buildCost = 3; # uses webkitgtk 4.1
|
||||||
persist.byStore.private = [
|
persist.byStore.private = [
|
||||||
# attachments, and email -- contained in a sqlite db
|
# attachments, and email -- contained in a sqlite db
|
||||||
".local/share/geary"
|
".local/share/geary"
|
||||||
|
|
24
hosts/common/programs/gnome-clocks.nix
Normal file
24
hosts/common/programs/gnome-clocks.nix
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{ pkgs, ... }: {
|
||||||
|
sane.programs."gnome.gnome-clocks" = {
|
||||||
|
packageUnwrapped = pkgs.gnome.gnome-clocks.overrideAttrs (upstream: {
|
||||||
|
# TODO: upstream this
|
||||||
|
buildInputs = upstream.buildInputs ++ (with pkgs; [
|
||||||
|
# gnome-clocks needs `playbin` (gst-plugins-base) and `scaletempo` (gst-plugins-good)
|
||||||
|
# to play the alarm when a timer expires
|
||||||
|
gst_all_1.gstreamer
|
||||||
|
gst_all_1.gst-plugins-base
|
||||||
|
gst_all_1.gst-plugins-good
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
buildCost = 1;
|
||||||
|
sandbox.method = "bwrap";
|
||||||
|
sandbox.whitelistAudio = true;
|
||||||
|
sandbox.whitelistDbus = [ "user" ]; #< required (alongside .config/dconf) to remember timers
|
||||||
|
sandbox.whitelistWayland = true;
|
||||||
|
sandbox.extraPaths = [
|
||||||
|
".config/dconf" # required (alongside dbus) to remember timers
|
||||||
|
];
|
||||||
|
suggestedPrograms = [ "dconf" ];
|
||||||
|
};
|
||||||
|
}
|
|
@ -3,6 +3,8 @@
|
||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
sane.programs."gnome.gnome-weather" = {
|
sane.programs."gnome.gnome-weather" = {
|
||||||
|
buildCost = 1;
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.wrapperType = "inplace"; #< /share/org.gnome.Weather/org.gnome.Weather file refers to bins by full path
|
sandbox.wrapperType = "inplace"; #< /share/org.gnome.Weather/org.gnome.Weather file refers to bins by full path
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
|
|
|
@ -2,8 +2,20 @@
|
||||||
# - turn the tv off and on again (no, really...)
|
# - turn the tv off and on again (no, really...)
|
||||||
#
|
#
|
||||||
# SANITY CHECKS:
|
# SANITY CHECKS:
|
||||||
# - `go2tv -u 'https://uninsane.org/share/AmenBreak.mp4'`
|
# - `go2tv -u 'https://uninsane.org/share/Milkbags/AmenBreak.mp4'`
|
||||||
# - LGTV: works, but not seekable
|
# - LGTV: works, but not seekable
|
||||||
|
# - Samsung: "Cannot play video."
|
||||||
|
# - `go2tv -v /mnt/servo/media/Videos/Milkbags/AmenBreak.mp4`
|
||||||
|
# - Samsung: works
|
||||||
|
# - `go2tv -v /mnt/servo/media/Videos/Milkbags/COLIN.webm`
|
||||||
|
# - Samsung: works
|
||||||
|
# - `go2tv -v /mnt/servo/media/Videos/Shows/Lucky.Star/S01/S01E01-The.Girl.who.Dashes.Off.mkv`
|
||||||
|
# - Samsung: error 500
|
||||||
|
# - `go2tv -tc -v /mnt/servo/media/Videos/Shows/Lucky.Star/S01/S01E01-The.Girl.who.Dashes.Off.mkv`
|
||||||
|
# - Samsung: error 500
|
||||||
|
# - note that it still advertized .mkv to the TV
|
||||||
|
# - `cp /mnt/servo/media/Videos/Shows/Lucky.Star/S01/S01E01-The.Girl.who.Dashes.Off.mkv S01E01-The.Girl.who.Dashes.Off.mp4 && go2tv -v S01E01-The.Girl.who.Dashes.Off.mp4`
|
||||||
|
# - Samsung: WORKS
|
||||||
# - `go2tv -u 'https://youtu.be/p3G5IXn0K7A'`
|
# - `go2tv -u 'https://youtu.be/p3G5IXn0K7A'`
|
||||||
# - LGTV: FAILS ("this file cannot be recognized")
|
# - LGTV: FAILS ("this file cannot be recognized")
|
||||||
# - no fix via transcoding, altering the URI, etc.
|
# - no fix via transcoding, altering the URI, etc.
|
||||||
|
@ -17,6 +29,8 @@
|
||||||
# - LGTV: works
|
# - LGTV: works
|
||||||
#
|
#
|
||||||
# WHEN TO TRANSCODE:
|
# WHEN TO TRANSCODE:
|
||||||
|
# - mkv container + *:
|
||||||
|
# - Samsung: rename to .mp4 and cast that: no need to transcode
|
||||||
# - mkv container + mpeg-2 video + AC-3/48k stereo audio:
|
# - mkv container + mpeg-2 video + AC-3/48k stereo audio:
|
||||||
# - LGTV: no transcoding needed
|
# - LGTV: no transcoding needed
|
||||||
# - mkv container + H.264 video + AAC/48k 5.1 audio:
|
# - mkv container + H.264 video + AAC/48k 5.1 audio:
|
||||||
|
@ -27,6 +41,7 @@
|
||||||
# - LGTV: no transcoding needed
|
# - LGTV: no transcoding needed
|
||||||
# - mkv container + H.265 video + E-AC-3/48k stereo audio:
|
# - mkv container + H.265 video + E-AC-3/48k stereo audio:
|
||||||
# - LGTV: no transcoding needed
|
# - LGTV: no transcoding needed
|
||||||
|
#
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
let
|
let
|
||||||
cfg = config.sane.programs.go2tv;
|
cfg = config.sane.programs.go2tv;
|
||||||
|
@ -35,7 +50,7 @@ in
|
||||||
sane.programs.go2tv = {
|
sane.programs.go2tv = {
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.net = "clearnet";
|
sandbox.net = "clearnet";
|
||||||
sandbox.autodetectCliPaths = true;
|
sandbox.autodetectCliPaths = "existingFile";
|
||||||
# for GUI invocation, allow the common media directories
|
# for GUI invocation, allow the common media directories
|
||||||
sandbox.extraHomePaths = [
|
sandbox.extraHomePaths = [
|
||||||
"Music"
|
"Music"
|
||||||
|
|
24
hosts/common/programs/gst-device-monitor.nix
Normal file
24
hosts/common/programs/gst-device-monitor.nix
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# gst-device-monitor: gstreamer debugging tool.
|
||||||
|
# - `gst-device-monitor-1.0 Audio/Sink` #< show all audio sinks
|
||||||
|
# - `gst-device-monitor-1.0 Audio/Source` #< show all audio sources (microphones)
|
||||||
|
# - `gst-device-monitor-1.0 Video/Source` #< show all video sources (cameras)
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.programs.gst-device-monitor = {
|
||||||
|
packageUnwrapped = (pkgs.linkIntoOwnPackage pkgs.gst_all_1.gst-plugins-base [
|
||||||
|
"bin/gst-device-monitor-1.0"
|
||||||
|
"share/man/man1/gst-device-monitor-1.0.1.gz"
|
||||||
|
]).overrideAttrs (base: {
|
||||||
|
# XXX the binaries need `GST_PLUGIN_SYSTEM_PATH_1_0` set to function,
|
||||||
|
# but nixpkgs doesn't set those (TODO: upstream this!)
|
||||||
|
nativeBuildInputs = (base.nativeBuildInputs or []) ++ [
|
||||||
|
pkgs.wrapGAppsNoGuiHook
|
||||||
|
];
|
||||||
|
buildInputs = (base.buildInputs or []) ++ [
|
||||||
|
pkgs.gst_all_1.gst-plugins-base #< required to find Audio/Sink
|
||||||
|
pkgs.gst_all_1.gst-plugins-good #< required to find Audio/Source and Video/Source
|
||||||
|
pkgs.pipewire #< required for Video/Source (video4linux)
|
||||||
|
];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
20
hosts/common/programs/gvfs.nix
Normal file
20
hosts/common/programs/gvfs.nix
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# gvfs is used by e.g. nautilus to mount remote filesystems (ftp://, etc)
|
||||||
|
# TODO: gvfs depends on udisks, depends on gnupg,
|
||||||
|
# and as part of this `keyboxd` gpg daemon gets started and does background work every minute even though i totally don't use it.
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs.gvfs;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.gvfs = {
|
||||||
|
packageUnwrapped = pkgs.gvfs.override {
|
||||||
|
# i don't need to mount samba shares, and samba build is expensive/flaky (mostly for cross, but even problematic on native)
|
||||||
|
samba = null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.gvfs = {
|
||||||
|
inherit (cfg) package;
|
||||||
|
enable = cfg.enabled;
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
sane.programs.handbrake = {
|
sane.programs.handbrake = {
|
||||||
|
buildCost = 1;
|
||||||
|
|
||||||
sandbox.method = "landlock"; #< also supports bwrap, but landlock ensures we don't write to non-mounted tmpfs dir
|
sandbox.method = "landlock"; #< also supports bwrap, but landlock ensures we don't write to non-mounted tmpfs dir
|
||||||
sandbox.whitelistDbus = [ "user" ]; # notifications
|
sandbox.whitelistDbus = [ "user" ]; # notifications
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
|
@ -15,7 +17,7 @@
|
||||||
|
|
||||||
# disable expensive sambda dependency; i don't use it.
|
# disable expensive sambda dependency; i don't use it.
|
||||||
packageUnwrapped = pkgs.handbrake.override {
|
packageUnwrapped = pkgs.handbrake.override {
|
||||||
ffmpeg-full = pkgs.ffmpeg-full.override {
|
ffmpeg_7-full = pkgs.ffmpeg_7-full.override {
|
||||||
withSamba = false;
|
withSamba = false;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,7 +45,7 @@ sort_direction=-1
|
||||||
tree_sort_direction=1
|
tree_sort_direction=1
|
||||||
tree_view_always_by_pid=0
|
tree_view_always_by_pid=0
|
||||||
all_branches_collapsed=0
|
all_branches_collapsed=0
|
||||||
screen:Main=PID USER TTY NICE M_RESIDENT M_PRIV STATE PERCENT_CPU PERCENT_MEM TIME Command
|
screen:Main=PID USER TTY PRIORITY NICE M_RESIDENT M_PRIV STATE PERCENT_CPU PERCENT_MEM TIME Command
|
||||||
.sort_key=PERCENT_CPU
|
.sort_key=PERCENT_CPU
|
||||||
.tree_sort_key=PID
|
.tree_sort_key=PID
|
||||||
.tree_view_always_by_pid=0
|
.tree_view_always_by_pid=0
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
sane.programs.imagemagick = {
|
sane.programs.imagemagick = {
|
||||||
|
buildCost = 1;
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.wrapperType = "inplace"; # /etc/ImageMagick-7/delegates.xml refers to bins by absolute path
|
sandbox.wrapperType = "inplace"; # /etc/ImageMagick-7/delegates.xml refers to bins by absolute path
|
||||||
sandbox.whitelistPwd = true;
|
sandbox.whitelistPwd = true;
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
{ 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;
|
||||||
|
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.extraHomePaths = [
|
sandbox.extraHomePaths = [
|
||||||
"Music"
|
"Music"
|
||||||
|
@ -14,12 +23,5 @@
|
||||||
sandbox.whitelistDbus = [ "user" ]; # notifications
|
sandbox.whitelistDbus = [ "user" ]; # notifications
|
||||||
sandbox.whitelistDri = true;
|
sandbox.whitelistDri = true;
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
packageUnwrapped = pkgs.kdenlive.override {
|
|
||||||
ffmpeg-full = pkgs.ffmpeg-full.override {
|
|
||||||
# avoid expensive samba build for a feature i don't use
|
|
||||||
withSamba = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
sandbox.whitelistDri = true; #< required
|
sandbox.whitelistDri = true; #< required
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
|
|
||||||
|
buildCost = 2;
|
||||||
|
|
||||||
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.
|
||||||
persist.byStore.plaintext = [
|
persist.byStore.plaintext = [
|
||||||
|
|
|
@ -47,6 +47,7 @@ in {
|
||||||
packageUnwrapped = pkgs.koreader-from-src;
|
packageUnwrapped = pkgs.koreader-from-src;
|
||||||
sandbox.method = "bwrap"; # sandboxes fine under landlock too, except for FTP
|
sandbox.method = "bwrap"; # sandboxes fine under landlock too, except for FTP
|
||||||
sandbox.net = "clearnet";
|
sandbox.net = "clearnet";
|
||||||
|
sandbox.whitelistDbus = [ "user" ]; # for opening the web browser via portal
|
||||||
sandbox.whitelistDri = true; # reduces startup time and subjective page flip time
|
sandbox.whitelistDri = true; # reduces startup time and subjective page flip time
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
sandbox.extraHomePaths = [
|
sandbox.extraHomePaths = [
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
sane.programs.lemoa = {
|
sane.programs.lemoa = {
|
||||||
|
buildCost = 1;
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.net = "clearnet";
|
sandbox.net = "clearnet";
|
||||||
sandbox.whitelistDbus = [ "user" ]; # for clicking links
|
sandbox.whitelistDbus = [ "user" ]; # for clicking links
|
||||||
|
|
13
hosts/common/programs/lftp.nix
Normal file
13
hosts/common/programs/lftp.nix
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.programs.lftp = {
|
||||||
|
sandbox.method = "bwrap";
|
||||||
|
sandbox.net = "all";
|
||||||
|
sandbox.extraPaths = [
|
||||||
|
"Music"
|
||||||
|
"Videos/local"
|
||||||
|
"Videos/servo"
|
||||||
|
"tmp"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
|
@ -8,7 +8,7 @@
|
||||||
packageUnwrapped = pkgs.libreoffice-fresh;
|
packageUnwrapped = pkgs.libreoffice-fresh;
|
||||||
sandbox.method = "bwrap";
|
sandbox.method = "bwrap";
|
||||||
sandbox.whitelistWayland = true;
|
sandbox.whitelistWayland = true;
|
||||||
sandbox.autodetectCliPaths = true;
|
sandbox.autodetectCliPaths = "existingFile";
|
||||||
sandbox.extraHomePaths = [
|
sandbox.extraHomePaths = [
|
||||||
# allow a spot to save files.
|
# allow a spot to save files.
|
||||||
# with bwrap sandboxing, saving to e.g. ~/ succeeds but the data is inaccessible outside the sandbox,
|
# with bwrap sandboxing, saving to e.g. ~/ succeeds but the data is inaccessible outside the sandbox,
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
"tmp"
|
"tmp"
|
||||||
];
|
];
|
||||||
|
|
||||||
slowToBuild = true;
|
buildCost = 3;
|
||||||
|
|
||||||
# disable first-run stuff
|
# disable first-run stuff
|
||||||
fs.".config/libreoffice/4/user/registrymodifications.xcu".symlink.text = ''
|
fs.".config/libreoffice/4/user/registrymodifications.xcu".symlink.text = ''
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
mime.associations = {
|
mime.associations = {
|
||||||
|
"image/avif" = "org.gnome.Loupe.desktop";
|
||||||
"image/gif" = "org.gnome.Loupe.desktop";
|
"image/gif" = "org.gnome.Loupe.desktop";
|
||||||
"image/heif" = "org.gnome.Loupe.desktop"; # apple codec
|
"image/heif" = "org.gnome.Loupe.desktop"; # apple codec
|
||||||
"image/png" = "org.gnome.Loupe.desktop";
|
"image/png" = "org.gnome.Loupe.desktop";
|
||||||
|
|
|
@ -1,6 +1,23 @@
|
||||||
{ ... }:
|
# config is loaded from the first one found:
|
||||||
|
# - $PWD/config/%model.conf
|
||||||
|
# - /etc/megapixels/config/%model.conf (SYSCONFDIR)
|
||||||
|
# - /usr/share/megapixels/config/%model.conf (DATADIR -- maybe this is the package's own directory?)
|
||||||
|
# debug with:
|
||||||
|
# - LIBMEGAPIXELS_DEBUG=2 megapixels
|
||||||
|
# 2 = log level debug. no higher values signify anything
|
||||||
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
sane.programs.megapixels = {
|
sane.programs.megapixels = {
|
||||||
|
packageUnwrapped = pkgs.megapixels.overrideAttrs (upstream: {
|
||||||
|
postPatch = (upstream.postPatch or "") + ''
|
||||||
|
# 2024/04/21: patch it to save photos in a more specific directory
|
||||||
|
substituteInPlace src/process_pipeline.c \
|
||||||
|
--replace-fail 'XDG_PICTURES_DIR' 'XDG_PHOTOS_DIR'
|
||||||
|
# 2024/04/21: patch it so the folder button works
|
||||||
|
substituteInPlace src/main.c \
|
||||||
|
--replace-fail 'g_get_user_special_dir(G_USER_DIRECTORY_PICTURES)' 'getenv("XDG_PHOTOS_DIR")'
|
||||||
|
'';
|
||||||
|
});
|
||||||
# megapixels sandboxing is tough:
|
# megapixels sandboxing is tough:
|
||||||
# if misconfigured, preview will alternately be OK, black, or only 1/4 of it will be rendered -- with no obvious pattern.
|
# if misconfigured, preview will alternately be OK, black, or only 1/4 of it will be rendered -- with no obvious pattern.
|
||||||
# adding all of ~ to the sandbox will sometimes (?) fix the flakiness, even when `strace` doesn't show it accessing any files...
|
# adding all of ~ to the sandbox will sometimes (?) fix the flakiness, even when `strace` doesn't show it accessing any files...
|
||||||
|
@ -16,10 +33,8 @@
|
||||||
sandbox.extraHomePaths = [
|
sandbox.extraHomePaths = [
|
||||||
".config/dconf" #< else it segfaults during post-process
|
".config/dconf" #< else it segfaults during post-process
|
||||||
# ".config/megapixels"
|
# ".config/megapixels"
|
||||||
".local/share/applications" #< needed for viewing photos, until i can sort out the portal stuff
|
|
||||||
".cache/mesa_shader_cache" # loads way faster
|
".cache/mesa_shader_cache" # loads way faster
|
||||||
"tmp"
|
"Pictures/Photos"
|
||||||
"Pictures" #< TODO: make this Pictures/Photos and save photos there
|
|
||||||
# also it addresses a lot via relative path.
|
# also it addresses a lot via relative path.
|
||||||
];
|
];
|
||||||
sandbox.extraPaths = [
|
sandbox.extraPaths = [
|
||||||
|
@ -37,6 +52,10 @@
|
||||||
sandbox.extraRuntimePaths = [
|
sandbox.extraRuntimePaths = [
|
||||||
"dconf" #< else it's very spammy, and slow
|
"dconf" #< else it's very spammy, and slow
|
||||||
];
|
];
|
||||||
|
# XXX(2024/04/21): without this it fails to convert .dng -> .jpg.
|
||||||
|
# "bwrap: open /proc/34/ns/ns failed: No such file or directory"
|
||||||
|
sandbox.isolatePids = false;
|
||||||
|
|
||||||
suggestedPrograms = [ "dconf" ]; #< not sure if necessary
|
suggestedPrograms = [ "dconf" ]; #< not sure if necessary
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ in
|
||||||
desktopName = "Mimeo";
|
desktopName = "Mimeo";
|
||||||
exec = "mimeo %U";
|
exec = "mimeo %U";
|
||||||
comment = "Open files by MIME-type or file name using regular expressions.";
|
comment = "Open files by MIME-type or file name using regular expressions.";
|
||||||
|
noDisplay = true;
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
12
hosts/common/programs/mmcli.nix
Normal file
12
hosts/common/programs/mmcli.nix
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.programs.mmcli = {
|
||||||
|
packageUnwrapped = pkgs.modemmanager-split.mmcli.overrideAttrs (upstream: {
|
||||||
|
meta = upstream.meta // {
|
||||||
|
mainProgram = "mmcli";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
# TODO: sandbox
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
80
hosts/common/programs/modemmanager.nix
Normal file
80
hosts/common/programs/modemmanager.nix
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs.modemmanager;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.modemmanager = {
|
||||||
|
packageUnwrapped = pkgs.modemmanager-split.daemon.overrideAttrs (upstream: {
|
||||||
|
postInstall = (upstream.postInstall or "") + ''
|
||||||
|
sed 's/"root"/"networkmanager"/g' $out/share/dbus-1/system.d/org.freedesktop.ModemManager1.conf \
|
||||||
|
> $out/share/dbus-1/system.d/networkmanager-org.freedesktop.ModemManager1.conf
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = upstream.meta // {
|
||||||
|
mainProgram = "ModemManager";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
# mmcli needs /run/current-system/sw/share/dbus-1 files to function
|
||||||
|
enableFor.system = lib.mkIf (builtins.any (en: en) (builtins.attrValues cfg.enableFor.user)) true;
|
||||||
|
|
||||||
|
suggestedPrograms = [ "mmcli" ];
|
||||||
|
|
||||||
|
# bwrap sandboxing works, but requires the real user to be root.
|
||||||
|
# landlock sandboxing works, and allows the real user to be someone else (like `networkmanager`).
|
||||||
|
# non-root is very important, because of how many things in e.g. /dev are r/w based on uid=0.
|
||||||
|
# TODO: have the services run as `networkmanager` user
|
||||||
|
sandbox.method = "bwrap";
|
||||||
|
# sandbox.method = "landlock";
|
||||||
|
sandbox.wrapperType = "inplace"; #< .pc files, GIR files with absolute paths,
|
||||||
|
sandbox.net = "all"; #< needed for modem bringup
|
||||||
|
# sandbox.isolatePids = false;
|
||||||
|
sandbox.capabilities = [
|
||||||
|
"net_admin"
|
||||||
|
"net_raw"
|
||||||
|
];
|
||||||
|
sandbox.extraPaths = lib.warn "TODO: modemmanager: sandbox more aggressively" [
|
||||||
|
# "/"
|
||||||
|
"/dev" #v modem-power + net are not enough
|
||||||
|
# "/dev/modem-power"
|
||||||
|
# "/dev/net"
|
||||||
|
"/proc"
|
||||||
|
# /run #v can likely be reduced more
|
||||||
|
"/run/dbus"
|
||||||
|
"/run/NetworkManager"
|
||||||
|
"/run/resolvconf"
|
||||||
|
"/run/systemd"
|
||||||
|
"/run/udev"
|
||||||
|
"/sys"
|
||||||
|
# "/var"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.ModemManager = lib.mkIf cfg.enabled {
|
||||||
|
aliases = [ "dbus-org.freedesktop.ModemManager1.service" ];
|
||||||
|
after = [ "polkit.service" ];
|
||||||
|
requires = [ "polkit.service" ];
|
||||||
|
wantedBy = [ "network.target" ];
|
||||||
|
path = [ "/run/current-system/sw" ]; #< so it can find `sanebox`
|
||||||
|
|
||||||
|
serviceConfig.Type = "dbus";
|
||||||
|
serviceConfig.BusName = "org.freedesktop.ModemManager1";
|
||||||
|
|
||||||
|
# only if started with `--debug` does mmcli let us issue AT commands like
|
||||||
|
# `mmcli --modem any --command=<AT_CMD>`
|
||||||
|
serviceConfig.ExecStart = "${lib.getExe cfg.package} --debug";
|
||||||
|
# --debug sets DEBUG level logging: so reset
|
||||||
|
serviceConfig.ExecStartPost = "${lib.getExe config.sane.programs.mmcli.package} --set-logging=INFO";
|
||||||
|
|
||||||
|
serviceConfig.Restart = "on-abort";
|
||||||
|
serviceConfig.StandardError = "null";
|
||||||
|
serviceConfig.CapabilityBoundingSet = "CAP_SYS_ADMIN CAP_NET_ADMIN";
|
||||||
|
serviceConfig.ProtectSystem = true;
|
||||||
|
serviceConfig.ProtectHome = true;
|
||||||
|
serviceConfig.PrivateTmp = true;
|
||||||
|
serviceConfig.RestrictAddressFamilies = "AF_NETLINK AF_UNIX AF_QIPCRTR";
|
||||||
|
serviceConfig.NoNewPrivileges = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# so that ModemManager can discover when the modem appears
|
||||||
|
services.udev.packages = lib.mkIf cfg.enabled [ cfg.package ];
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user