Compare commits
351 Commits
wip-trust-
...
test-nm-ni
Author | SHA1 | Date | |
---|---|---|---|
d629db4e45 | |||
f5e5d1bcc4 | |||
30d41f82f2 | |||
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 |
@@ -16,7 +16,6 @@ building [hosts/](./hosts/) will require [sops][sops].
|
||||
|
||||
you might specifically be interested in these files (elaborated further in #key-points-of-interest):
|
||||
- ~~[`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.
|
||||
- [my implementation of impermanence](./modules/persist/default.nix)
|
||||
- my way of deploying dotfiles/configuring programs per-user:
|
||||
|
56
TODO.md
56
TODO.md
@@ -1,25 +1,33 @@
|
||||
## BUGS
|
||||
- moby: my mobile ISP is adding spoofed AAAA records that break things like wireguard
|
||||
- it only does this when i use their DNS resolvers though: if i run my own recursive resolver, they won't mess with it.
|
||||
- moby: mpv uosc always starts at 40% volume
|
||||
- is this just mpv remembering its last-played volume?
|
||||
- moby: rofi crashes sporadically
|
||||
- `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
|
||||
- i accidentally create sub-splits in sway all the time
|
||||
- especially on moby => unusable
|
||||
- like toplevel is split L/R, and then the L is a tabbed view and the R is a tabbed view
|
||||
- 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
|
||||
- sway mouse/kb hotplug doesn't work
|
||||
- `nix` operations from lappy hang when `desko` is unreachable
|
||||
- could at least direct the cache to `http://desko-hn:5001`
|
||||
- sysvol (volume overlay): when casting with `blast`, sysvol doesn't react to volume changes
|
||||
- moby: kaslr is effectively disabled
|
||||
- `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:
|
||||
- REMOVE DEPRECATED `crypt` from sftpgo_auth_hook
|
||||
- add import checks to my Python nix-shell scripts
|
||||
- consolidate ~/dev and ~/ref
|
||||
- ~/dev becomes a link to ~/ref/cat/mine
|
||||
- fold hosts/common/home/ssh.nix -> hosts/common/users/colin.nix
|
||||
@@ -36,15 +44,20 @@
|
||||
|
||||
### upstreaming
|
||||
- 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
|
||||
- gtk: build schemas even on cross compilation: <https://github.com/NixOS/nixpkgs/pull/247844>
|
||||
|
||||
|
||||
## 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
|
||||
- add FTPS support for WAN users of uninsane.org (and possibly require it?)
|
||||
- validate duplicity backups!
|
||||
- encrypt more ~ dirs (~/archives, ~/records, ..?)
|
||||
- best to do this after i know for sure i have good backups
|
||||
@@ -61,19 +74,19 @@
|
||||
- <https://github.com/flatpak/xdg-dbus-proxy>
|
||||
- remove `.ssh` access from Firefox!
|
||||
- limit access to `~/knowledge/secrets` through an agent that requires GUI approval, so a firefox exploit can't steal all my logins
|
||||
- port 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.
|
||||
- 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
|
||||
- i.e. per-app dconf profiles for those which need it. possible static config.
|
||||
- canaries for important services
|
||||
- e.g. daily email checks; daily backup checks
|
||||
- integrate `nix check` into Gitea actions?
|
||||
|
||||
#### sudo-free world
|
||||
- `systemctl restart FOO`: needs `sudo`
|
||||
|
||||
### user experience
|
||||
- rofi: sort items case-insensitively
|
||||
- give `mpv` better `nice`ness?
|
||||
- xdg-desktop-portal shouldn't kill children on exit
|
||||
- *maybe* a job for `setsid -f`?
|
||||
- replace starship prompt with something more efficient
|
||||
@@ -86,7 +99,7 @@
|
||||
- offline docs viewer (gtk): <https://github.com/workbenchdev/Biblioteca>
|
||||
- some type of games manager/launcher
|
||||
- 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/>
|
||||
- OSK overlay specifically for mobile gaming
|
||||
- i.e. mock joysticks, for use with SuperTux and SuperTuxKart
|
||||
@@ -115,6 +128,7 @@
|
||||
- direct mepo to prefer gpsd, with fallback to geoclue, for better accuracy?
|
||||
- configure geoclue to do some smoothing?
|
||||
- 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: improve gPodder launch time
|
||||
- moby: theme GTK apps (i.e. non-adwaita styles)
|
||||
@@ -143,6 +157,10 @@
|
||||
|
||||
### perf
|
||||
- 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
|
||||
- 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!
|
||||
|
56
flake.lock
generated
56
flake.lock
generated
@@ -61,11 +61,11 @@
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715515815,
|
||||
"narHash": "sha256-yaLScMHNFCH6SbB0HSA/8DWDgK0PyOhCXoFTdHlWkhk=",
|
||||
"lastModified": 1716725378,
|
||||
"narHash": "sha256-bNTVDAVBLFSSTU+q54cJnntmFKBi+F/D8sSqlZwBGiM=",
|
||||
"owner": "nix-community",
|
||||
"repo": "lib-aggregate",
|
||||
"rev": "09883ca828e8cfaacdb09e29190a7b84ad1d9925",
|
||||
"rev": "dbc9130fe1455e0f6ee4d8f5f799f9be551f866b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -99,11 +99,11 @@
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715248291,
|
||||
"narHash": "sha256-npC9Swu4VIlRIiEP0XFGoIukd6vOufS/M3PdHk6rQpc=",
|
||||
"lastModified": 1715804156,
|
||||
"narHash": "sha256-GtIHP86Cz1kD9xZO/cKbNQACHKdoT9WFbLJAq6W2EDY=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-eval-jobs",
|
||||
"rev": "63154bdfb22091041b307d17863bdc0e01a32a00",
|
||||
"rev": "bb95091f6c6f38f6cfc215a1797a2dd466312c8b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -152,11 +152,11 @@
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1715474941,
|
||||
"narHash": "sha256-CNCqCGOHdxuiVnVkhTpp2WcqSSmSfeQjubhDOcgwGjU=",
|
||||
"lastModified": 1716684580,
|
||||
"narHash": "sha256-sIbMJWJr4hl2PWd9/iWlh89QfVzBn1NJ3u5RjeZADuM=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "58e03b95f65dfdca21979a081aa62db0eed6b1d8",
|
||||
"rev": "d0d27192931680482081aa1c38389da2af84a651",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -167,11 +167,11 @@
|
||||
},
|
||||
"nixpkgs-next-unpatched": {
|
||||
"locked": {
|
||||
"lastModified": 1715601680,
|
||||
"narHash": "sha256-Gmz6U8NMZVVnP6AGX4sMl4X6RcQBASPl/2Gj9R5k1Pk=",
|
||||
"lastModified": 1717243271,
|
||||
"narHash": "sha256-M3VxP6DtREz5Lq6MKg1gQ2EeVdIbq6AEp/N1tDSrvoc=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "eda36d7cf3391ad06097009b08822fb74acd5e00",
|
||||
"rev": "f7de25c01e4c073c06e0525226a0c2311d530cee",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -183,11 +183,11 @@
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1715458492,
|
||||
"narHash": "sha256-q0OFeZqKQaik2U8wwGDsELEkgoZMK7gvfF6tTXkpsqE=",
|
||||
"lastModified": 1716655032,
|
||||
"narHash": "sha256-kQ25DAiCGigsNR/Quxm3v+JGXAEXZ8I7RAF4U94bGzE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8e47858badee5594292921c2668c11004c3b0142",
|
||||
"rev": "59a450646ec8ee0397f5fa54a08573e8240eb91f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -199,11 +199,11 @@
|
||||
},
|
||||
"nixpkgs-unpatched": {
|
||||
"locked": {
|
||||
"lastModified": 1715616096,
|
||||
"narHash": "sha256-rxh2XECb5hRzgNR4Xqj3aAjg6821LmNTVRfF6sUW6fI=",
|
||||
"lastModified": 1717242134,
|
||||
"narHash": "sha256-2X835ZESUaQ/KZEuG9HkoEB7h0USG5uvkSUmLzFkxAE=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "0a949cf2618e8eab83aa008f1f8e03db137ed36c",
|
||||
"rev": "61c1d282153dbfcb5fe413c228d172d0fe7c2a7e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -223,11 +223,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715609745,
|
||||
"narHash": "sha256-z2lQ7G1AxljvYeqrHWjc1ctOI4QZP06vPtvLYJWfZSc=",
|
||||
"lastModified": 1717175759,
|
||||
"narHash": "sha256-KiM5ue/UNQt8ktoqCV4yFqhHxM31U94Mf/piKW9dZ4c=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs-wayland",
|
||||
"rev": "ed18785b8816fa878bdd9df7f2e8722695401ef8",
|
||||
"rev": "93b225ddba91179248b378913a91defbc6aeb899",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -254,11 +254,11 @@
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715482972,
|
||||
"narHash": "sha256-y1uMzXNlrVOWYj1YNcsGYLm4TOC2aJrwoUY1NjQs9fM=",
|
||||
"lastModified": 1716692524,
|
||||
"narHash": "sha256-sALodaA7Zkp/JD6ehgwc0UCBrSBfB4cX66uFGTsqeFU=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "b6cb5de2ce57acb10ecdaaf9bbd62a5ff24fa02e",
|
||||
"rev": "962797a8d7f15ed7033031731d0bb77244839960",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -311,11 +311,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1713198740,
|
||||
"narHash": "sha256-8SUaqMJdAkMOI9zhvlToL7eCr5Sl+2o2pDQ7nq+HoJU=",
|
||||
"lastModified": 1715894399,
|
||||
"narHash": "sha256-h1EdA/h74zgNPNEYbH+0mgOMlJgLVcxuZ8/ewsZlgEc=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "af8420d1c256d990b5e24de14ad8592a5d85bf77",
|
||||
"revCount": 239,
|
||||
"rev": "e6f88f563bdd1700c04018951de4f69862646dd1",
|
||||
"revCount": 240,
|
||||
"type": "git",
|
||||
"url": "https://git.uninsane.org/colin/uninsane"
|
||||
},
|
||||
|
10
flake.nix
10
flake.nix
@@ -113,7 +113,6 @@
|
||||
modules = [
|
||||
{
|
||||
nixpkgs.buildPlatform.system = local;
|
||||
# nixpkgs.config.replaceStdenv = { pkgs }: pkgs.ccacheStdenv;
|
||||
}
|
||||
(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.
|
||||
@@ -290,7 +289,7 @@
|
||||
# - sandbox friendliness (especially: `git` doesn't have to be run as root)
|
||||
|
||||
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).
|
||||
# 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.
|
||||
@@ -318,11 +317,8 @@
|
||||
commandArgv = pkg.updateScript.command or pkg.updateScript;
|
||||
command = pkgs.lib.escapeShellArgs commandArgv;
|
||||
in builtins.toString (pkgs.writeShellScript "update-${strAttrPath}" ''
|
||||
export UPDATE_NIX_NAME=${pkg.name}
|
||||
export UPDATE_NIX_PNAME=${pkg.pname}
|
||||
export UPDATE_NIX_OLD_VERSION=${pkg.version}
|
||||
export UPDATE_NIX_ATTR_PATH=${strAttrPath}
|
||||
${command}
|
||||
set -x
|
||||
env UPDATE_NIX_NAME=${pkg.name} UPDATE_NIX_PNAME=${pkg.pname} UPDATE_NIX_OLD_VERSION=${pkg.version} UPDATE_NIX_ATTR_PATH=${strAttrPath} ${command}
|
||||
'');
|
||||
};
|
||||
mkUpdatersNoAliases = opts: basePath: pkgs.lib.concatMapAttrs
|
||||
|
@@ -1,40 +1,37 @@
|
||||
{ config, pkgs, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
./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;
|
||||
|
||||
# services.distccd.enable = true;
|
||||
# sane.programs.distcc.enableFor.user.guest = true;
|
||||
|
||||
# TODO: remove emulation, but need to fix nixos-rebuild to moby for that.
|
||||
# sane.roles.build-machine.emulation = true;
|
||||
# don't enable wifi by default: it messes with connectivity.
|
||||
# systemd.services.iwd.enable = false;
|
||||
# systemd.services.wpa_supplicant.enable = false;
|
||||
sane.programs.wpa_supplicant.enableFor.user.colin = lib.mkForce false;
|
||||
sane.programs.wpa_supplicant.enableFor.system = lib.mkForce false;
|
||||
|
||||
sops.secrets.colin-passwd.neededForUsers = true;
|
||||
|
||||
sane.ports.openFirewall = true; # for e.g. nix-serve
|
||||
|
||||
sane.roles.build-machine.enable = true;
|
||||
sane.roles.client = true;
|
||||
sane.roles.dev-machine = true;
|
||||
sane.roles.pc = true;
|
||||
sane.services.wg-home.enable = true;
|
||||
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.nixserve.secretKeyFile = config.sops.secrets.nix_serve_privkey.path;
|
||||
|
||||
sane.nixcache.substituters.desko = false;
|
||||
sane.nixcache.remote-builders.desko = false;
|
||||
|
||||
sane.programs.cups.enableFor.user.colin = true;
|
||||
sane.programs.sway.enableFor.user.colin = true;
|
||||
sane.programs.iphoneUtils.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.signal-desktop.config.autostart = true;
|
||||
|
||||
@@ -44,10 +41,6 @@
|
||||
# needed to use libimobiledevice/ifuse, for iphone sync
|
||||
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
|
||||
# defaults to something like:
|
||||
# - hourly snapshots
|
||||
|
@@ -9,12 +9,13 @@
|
||||
sane.roles.pc = true;
|
||||
sane.services.wg-home.enable = true;
|
||||
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;
|
||||
boot.loader.efi.canTouchEfiVariables = false;
|
||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||
|
||||
sane.programs.cups.enableFor.user.colin = true;
|
||||
sane.programs.stepmania.enableFor.user.colin = true;
|
||||
sane.programs.sway.enableFor.user.colin = true;
|
||||
|
||||
|
@@ -1,7 +1,4 @@
|
||||
# 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, ...:
|
||||
# - Linux Phone Apps: <https://linuxphoneapps.org/>
|
||||
@@ -21,13 +18,11 @@
|
||||
|
||||
sane.roles.client = 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.ip = config.sane.hosts.by-name."moby".wg-home.ip;
|
||||
|
||||
# for some reason desko -> moby deploys are super flaky when desko is also a nixcache (not true of desko -> lappy deploys, though!)
|
||||
# > unable to download 'http://desko:5001/<hash>.narinfo': Server returned nothing (no headers, no data) (52)
|
||||
sane.nixcache.substituters.desko = false;
|
||||
sane.ovpn.addrV4 = "172.24.87.255";
|
||||
# sane.ovpn.addrV6 = "fd00:0000:1337:cafe:1111:1111:18cd:a72b";
|
||||
|
||||
# XXX colin: phosh doesn't work well with passwordless login,
|
||||
# so set this more reliable default password should anything go wrong
|
||||
@@ -36,7 +31,6 @@
|
||||
|
||||
sops.secrets.colin-passwd.neededForUsers = true;
|
||||
|
||||
# sane.gui.sxmo.enable = true;
|
||||
sane.programs.sway.enableFor.user.colin = true;
|
||||
sane.programs.swaylock.enableFor.user.colin = false; #< not usable on touch
|
||||
sane.programs.schlock.enableFor.user.colin = true;
|
||||
@@ -114,7 +108,7 @@
|
||||
'';
|
||||
|
||||
# enable rotation sensor
|
||||
hardware.sensor.iio.enable = true;
|
||||
# hardware.sensor.iio.enable = true;
|
||||
|
||||
services.udev.extraRules = let
|
||||
chmod = "${pkgs.coreutils}/bin/chmod";
|
||||
|
@@ -40,35 +40,213 @@ let
|
||||
'';
|
||||
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_latest;
|
||||
|
||||
# alternatively, apply patches directly to stock nixos 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 becomes stdenv.hostPlatform.linux-kernel
|
||||
nixpkgs.hostPlatform.linux-kernel = {
|
||||
# defaults:
|
||||
name = "aarch64-multiplatform";
|
||||
baseConfig = "defconfig";
|
||||
DTB = true;
|
||||
autoModules = true;
|
||||
preferBuiltin = true;
|
||||
# extraConfig = ...
|
||||
# ^-- raspberry pi stuff: we don't need it.
|
||||
# baseConfig: defaults to "defconfig";
|
||||
# baseConfig = "pinephone_defconfig"; #< N.B.: ignored by `pkgs.linux-megous`
|
||||
DTB = true; #< DTB: compile device tree blobs
|
||||
# autoModules (default: true): for config options not manually specified, answer `m` to anything which supports it.
|
||||
# - this effectively builds EVERY MODULE SUPPORTED.
|
||||
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.gz"; # <-- compress the kernel image
|
||||
# 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.
|
||||
# the filtering/calibration is bad that it causes the screen to go fully dark at times.
|
||||
boot.blacklistedKernelModules = [ "stk3310" ];
|
||||
# boot.blacklistedKernelModules = [ "stk3310" ];
|
||||
|
||||
boot.kernelParams = [
|
||||
# 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.
|
||||
# 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.
|
||||
"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:
|
||||
# - <https://gitlab.com/postmarketOS/pmaports/-/issues/805#note_890467824>
|
||||
"lima.sched_timeout_ms=2000"
|
||||
];
|
||||
|
||||
# services.xserver.displayManager.job.preStart = ensureHWReady;
|
||||
# systemd.services.greetd.preStart = ensureHWReady;
|
||||
systemd.services.unl0kr.preStart = ensureHWReady;
|
||||
}
|
||||
|
@@ -15,20 +15,21 @@
|
||||
};
|
||||
|
||||
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 = [
|
||||
"consoleMediaUtils" # notably, for go2tv / casting
|
||||
"pcConsoleUtils"
|
||||
"sane-scripts.stop-all-servo"
|
||||
];
|
||||
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.visibleToWan = true;
|
||||
sane.services.wg-home.forwardToWan = true;
|
||||
sane.services.wg-home.routeThroughServo = false;
|
||||
sane.services.wg-home.ip = config.sane.hosts.by-name."servo".wg-home.ip;
|
||||
sane.nixcache.substituters.servo = false;
|
||||
sane.nixcache.substituters.desko = false;
|
||||
sane.ovpn.addrV4 = "172.23.174.114";
|
||||
# sane.ovpn.addrV6 = "fd00:0000:1337:cafe:1111:1111:8df3:14b0";
|
||||
sane.nixcache.remote-builders.desko = false;
|
||||
sane.nixcache.remote-builders.servo = false;
|
||||
# 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
|
||||
# '';
|
||||
|
||||
# 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):
|
||||
# DOCS: https://nixos.wiki/wiki/WireGuard
|
||||
# if you `systemctl restart wireguard-wg-ovpns`, make sure to also restart any other services in `NetworkNamespacePath = .../ovpns`.
|
||||
|
@@ -29,6 +29,13 @@
|
||||
# - 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, ... }:
|
||||
let
|
||||
# TURN port range (inclusive).
|
||||
@@ -110,16 +117,19 @@ in
|
||||
services.coturn.realm = "turn.uninsane.org";
|
||||
services.coturn.cert = "/var/lib/acme/turn.uninsane.org/fullchain.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.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.max-port = turnPortHigh;
|
||||
# services.coturn.secure-stun = true;
|
||||
services.coturn.extraConfig = lib.concatStringsSep "\n" [
|
||||
"verbose"
|
||||
# "Verbose" #< even MORE verbosity than "verbose"
|
||||
# "no-multicast-peers" # disables sending to IPv4 broadcast addresses (e.g. 224.0.0.0/3)
|
||||
# "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)
|
||||
# "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"
|
||||
|
||||
|
@@ -20,7 +20,6 @@
|
||||
./navidrome.nix
|
||||
./nginx.nix
|
||||
./nixos-prebuild.nix
|
||||
./nixserve.nix
|
||||
./ntfy
|
||||
./pict-rs.nix
|
||||
./pleroma.nix
|
||||
|
@@ -15,6 +15,7 @@
|
||||
# - could maybe be done with some mount option?
|
||||
|
||||
{ config, lib, ... }:
|
||||
lib.mkIf false #< TODO: remove nfs altogether! it's not exactly the most secure
|
||||
{
|
||||
services.nfs.server.enable = true;
|
||||
|
||||
|
@@ -12,6 +12,7 @@ let
|
||||
external_auth_hook = pkgs.static-nix-shell.mkPython3Bin {
|
||||
pname = "external_auth_hook";
|
||||
srcRoot = ./.;
|
||||
pyPkgs = [ "passlib" ];
|
||||
};
|
||||
# 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
|
||||
@@ -59,18 +60,8 @@ in
|
||||
enable = true;
|
||||
group = "export";
|
||||
|
||||
package = lib.warnIf (lib.versionOlder "2.5.6" pkgs.sftpgo.version) "sftpgo update: safe to use nixpkgs' sftpgo but keep my own `patches`" pkgs.buildGoModule {
|
||||
inherit (pkgs.sftpgo) name ldflags nativeBuildInputs doCheck subPackages postInstall passthru meta;
|
||||
version = "2.5.6-unstable-2024-04-18";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
# need to use > 2.5.6 for sftpgo_safe_fileinfo.patch to apply
|
||||
owner = "drakkan";
|
||||
repo = "sftpgo";
|
||||
rev = "950cf67e4c03a12c7e439802cabbb0b42d4ee5f5";
|
||||
hash = "sha256-UfiFd9NK3DdZ1J+FPGZrM7r2mo9xlKi0dsSlLEinYXM=";
|
||||
};
|
||||
vendorHash = "sha256-n1/9A2em3BCtFX+132ualh4NQwkwewMxYIMOphJEamg=";
|
||||
patches = (pkgs.sftpgo.patches or []) ++ [
|
||||
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
|
||||
@@ -79,7 +70,7 @@ in
|
||||
# the full set of bits, from which i filter, is found here: <https://pkg.go.dev/io/fs#FileMode>
|
||||
./safe_fileinfo.patch
|
||||
];
|
||||
};
|
||||
});
|
||||
|
||||
settings = {
|
||||
ftpd = {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/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 :
|
||||
#
|
||||
# available environment variables:
|
||||
@@ -37,9 +37,9 @@
|
||||
# - 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.
|
||||
|
||||
import crypt
|
||||
import json
|
||||
import os
|
||||
import passlib.hosts
|
||||
|
||||
from hmac import compare_digest
|
||||
|
||||
@@ -112,10 +112,8 @@ def isWireguard(ip: str) -> bool:
|
||||
|
||||
def isTrustedCred(password: str) -> bool:
|
||||
for cred in TRUSTED_CREDS:
|
||||
_, method, salt, hash_ = cred.split("$")
|
||||
# assert method == "6", f"unrecognized crypt entry: {cred}"
|
||||
if crypt.crypt(password, f"${method}${salt}") == cred:
|
||||
return True
|
||||
if passlib.hosts.linux_context.verify(password, cred):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
@@ -90,6 +90,8 @@
|
||||
];
|
||||
};
|
||||
|
||||
services.openssh.settings.UsePAM = true; #< required for `git` user to authenticate
|
||||
|
||||
# hosted git (web view and for `git <cmd>` use
|
||||
# TODO: enable publog?
|
||||
services.nginx.virtualHosts."git.uninsane.org" = {
|
||||
|
@@ -1,5 +1,6 @@
|
||||
{ lib, pkgs, ... }:
|
||||
|
||||
lib.mkIf false #< TODO: re-enable once confident of sandboxing
|
||||
{
|
||||
sane.persist.sys.byStore.plaintext = [
|
||||
# TODO: mode? we only need this to save Indexer creds ==> migrate to config?
|
||||
|
@@ -22,7 +22,7 @@ let
|
||||
# # "Change commandline flag to allow disabling video, since it is enabled by default"
|
||||
# postPatch = (upstream.postPatch or "") + ''
|
||||
# substituteInPlace src/validate.rs \
|
||||
# --replace 'if transcode_options.needs_reencode() {' 'if false {'
|
||||
# --replace-fail 'if transcode_options.needs_reencode() {' 'if false {'
|
||||
# '';
|
||||
# });
|
||||
in {
|
||||
|
@@ -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;
|
||||
}
|
@@ -9,8 +9,6 @@
|
||||
# - "Soulseek.AddressException: Failed to resolve address 'vps.slsknet.org': Resource temporarily unavailable"
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
# TODO: re-enable once i'm satisfied this isn't escaping the net sandbox
|
||||
lib.mkIf false
|
||||
{
|
||||
sane.persist.sys.byStore.plaintext = [
|
||||
{ user = "slskd"; group = "media"; path = "/var/lib/slskd"; method = "bind"; }
|
||||
|
@@ -82,6 +82,7 @@ let
|
||||
'';
|
||||
};
|
||||
in
|
||||
lib.mkIf false #< TODO: re-enable once confident of sandboxing
|
||||
{
|
||||
sane.persist.sys.byStore.plaintext = [
|
||||
# TODO: mode? we need this specifically for the stats tracking in .config/
|
||||
|
@@ -96,58 +96,58 @@ in
|
||||
{
|
||||
wan = {
|
||||
substitutions = mkSubstitutions "wan";
|
||||
listenAddrs = [
|
||||
listenAddrsIpv4 = [
|
||||
nativeAddrs."servo.lan"
|
||||
bindOvpn
|
||||
];
|
||||
};
|
||||
lan = {
|
||||
substitutions = mkSubstitutions "lan";
|
||||
listenAddrs = [ nativeAddrs."servo.lan" ];
|
||||
listenAddrsIpv4 = [ nativeAddrs."servo.lan" ];
|
||||
port = 1053;
|
||||
};
|
||||
hn = {
|
||||
substitutions = mkSubstitutions "hn";
|
||||
listenAddrs = [ nativeAddrs."servo.hn" ];
|
||||
listenAddrsIpv4 = [ nativeAddrs."servo.hn" ];
|
||||
port = 1053;
|
||||
};
|
||||
hn-resolver = {
|
||||
# don't need %AWAN% here because we forward to the hn instance.
|
||||
listenAddrs = [ 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;
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
# 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 = [
|
||||
|
@@ -86,6 +86,7 @@ let
|
||||
(fromDb "lexfridman.com/podcast" // rat)
|
||||
(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 "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
|
||||
@@ -191,6 +192,7 @@ let
|
||||
(fromDb "uninsane.org" // tech)
|
||||
(fromDb "unintendedconsequenc.es" // rat)
|
||||
(fromDb "vitalik.eth.limo" // tech) # Vitalik Buterin
|
||||
(fromDb "weekinethereumnews.com" // tech)
|
||||
(fromDb "willow.phantoma.online") # wizard@xyzzy.link
|
||||
(fromDb "xn--gckvb8fzb.com" // tech)
|
||||
(mkSubstack "astralcodexten" // rat // daily) # Scott Alexander
|
||||
@@ -244,6 +246,7 @@ let
|
||||
images = [
|
||||
(fromDb "catandgirl.com" // img // humor)
|
||||
(fromDb "davidrevoy.com" // img // art)
|
||||
(fromDb "grumpy.website" // img // humor)
|
||||
(fromDb "miniature-calendar.com" // img // art // daily)
|
||||
(fromDb "pbfcomics.com" // img // humor)
|
||||
(fromDb "poorlydrawnlines.com/feed" // img // humor)
|
||||
|
@@ -80,14 +80,12 @@
|
||||
# - query details with `sudo cpupower frequency-info`
|
||||
powerManagement.cpuFreqGovernor = "ondemand";
|
||||
|
||||
services.logind.extraConfig = ''
|
||||
# see: `man logind.conf`
|
||||
# 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.
|
||||
HandlePowerKey=lock
|
||||
HandlePowerKeyLongPress=poweroff
|
||||
HandleLidSwitch=lock
|
||||
'';
|
||||
# see: `man logind.conf`
|
||||
# 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.
|
||||
services.logind.powerKey = "lock";
|
||||
services.logind.powerKeyLongPress = "poweroff";
|
||||
services.logind.lidSwitch = "lock";
|
||||
|
||||
# services.snapper.configs = {
|
||||
# root = {
|
||||
|
@@ -7,6 +7,17 @@
|
||||
"usb_storage" # rpi needed this to boot from usb storage, i think.
|
||||
"nvme" # to boot from nvme devices
|
||||
# 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
|
||||
|
@@ -50,7 +50,7 @@ let
|
||||
localShareApplicationsPkg = (pkgs.symlinkJoin {
|
||||
name = "user-local-share-applications";
|
||||
paths = builtins.map
|
||||
(p: "${p.package}")
|
||||
(p: builtins.toString p.package)
|
||||
(enabledProgramsWithPackage ++ [ { package=mimeappsListPkg; } ]);
|
||||
}).overrideAttrs (orig: {
|
||||
# like normal symlinkJoin, but don't error if the path doesn't exist
|
||||
|
@@ -23,11 +23,5 @@
|
||||
# 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.".profile".symlink.text = ''
|
||||
# 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
|
||||
'';
|
||||
sane.user.fs.".config/environment.d/30-user-dirs.conf".symlink.target = "../user-dirs.dirs";
|
||||
}
|
||||
|
@@ -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
|
||||
sane.ids.dhcpcd.gid = 991;
|
||||
sane.ids.dhcpcd.uid = 992;
|
||||
@@ -18,7 +21,7 @@
|
||||
sane.ids.matrix-appservice-irc.uid = 993;
|
||||
sane.ids.matrix-appservice-irc.gid = 992;
|
||||
|
||||
# greetd (used by sway)
|
||||
# greetd (legacy)
|
||||
sane.ids.greeter.uid = 999;
|
||||
sane.ids.greeter.gid = 999;
|
||||
|
||||
@@ -78,6 +81,7 @@
|
||||
|
||||
# found on graphical hosts
|
||||
sane.ids.nm-iodine.uid = 2101; # desko/moby/lappy
|
||||
sane.ids.seat.gid = 2102;
|
||||
|
||||
# found on desko host
|
||||
# from services.usbmuxd
|
||||
|
@@ -1,7 +1,6 @@
|
||||
# things to consider when changing these parameters:
|
||||
# - temporary VPN access (`sane-vpn up ...`)
|
||||
# - 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:
|
||||
# - /etc/nsswitch.conf:
|
||||
@@ -18,17 +17,22 @@
|
||||
# - modern implementations hardcodes `127.0.0.53` and then systemd-resolved proxies everything (and caches).
|
||||
#
|
||||
# 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 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.
|
||||
{ lib, ... }:
|
||||
# - this is fixed by either removing `/var/run/nscd/socket` from the namespace, or disabling nscd altogether.
|
||||
{ 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.
|
||||
# /etc/resolv.conf isn't sophisticated enough to use different servers per net namespace (or link).
|
||||
# instead, running the stub resolver on a known address in the root ns lets us rewrite packets
|
||||
# in 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?)
|
||||
# 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`.
|
||||
# without DNSSEC:
|
||||
# - dig matrix.org => works
|
||||
@@ -44,7 +48,8 @@
|
||||
# stub resolver (just forwards upstream) lives on 127.0.0.54
|
||||
"127.0.0.53"
|
||||
];
|
||||
|
||||
})
|
||||
{
|
||||
# nscd -- the Name Service Caching Daemon -- caches DNS query responses
|
||||
# in a way that's unaware of my VPN routing, so routes are frequently poor against
|
||||
# services which advertise different IPs based on geolocation.
|
||||
@@ -65,3 +70,4 @@
|
||||
services.nscd.enable = false;
|
||||
system.nssModules = lib.mkForce [];
|
||||
}
|
||||
]
|
||||
|
@@ -7,50 +7,62 @@
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
def-ovpn = name: { endpoint, publicKey, addrV4, id }: {
|
||||
sane.vpn."ovpnd-${name}" = {
|
||||
inherit endpoint publicKey addrV4 id;
|
||||
privateKeyFile = config.sops.secrets."wg/ovpnd_${name}_privkey".path;
|
||||
# N.B.: OVPN issues each key (i.e. device) a different IP (addrV4), and requires you use it.
|
||||
# the IP it issues can be used to connect to any of their VPNs.
|
||||
# effectively the IP and key map 1-to-1.
|
||||
# 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 = [
|
||||
"46.227.67.134"
|
||||
"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.
|
||||
owner = "systemd-network";
|
||||
};
|
||||
};
|
||||
in lib.mkMerge [
|
||||
(def-ovpn "us" {
|
||||
endpoint = "vpn31.prd.losangeles.ovpn.com:9929";
|
||||
publicKey = "VW6bEWMOlOneta1bf6YFE25N/oMGh1E1UFBCfyggd0k=";
|
||||
id = 1;
|
||||
addrV4 = "172.27.237.218";
|
||||
# addrV6 = "fd00:0000:1337:cafe:1111:1111:ab00:4c8f";
|
||||
})
|
||||
# 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 = [
|
||||
# "172.21.182.178/32"
|
||||
# "fd00:0000:1337:cafe:1111:1111:cfcb:27e3/128"
|
||||
# ];
|
||||
# })
|
||||
(def-ovpn "us-mi" {
|
||||
endpoint = "vpn34.prd.miami.ovpn.com:9929";
|
||||
publicKey = "VtJz2irbu8mdkIQvzlsYhU+k9d55or9mx4A2a14t0V0=";
|
||||
id = 2;
|
||||
addrV4 = "172.21.182.178";
|
||||
# addrV6 = "fd00:0000:1337:cafe:1111:1111:cfcb:27e3";
|
||||
})
|
||||
(def-ovpn "ukr" {
|
||||
endpoint = "vpn96.prd.kyiv.ovpn.com:9929";
|
||||
publicKey = "CjZcXDxaaKpW8b5As1EcNbI6+42A6BjWahwXDCwfVFg=";
|
||||
id = 3;
|
||||
addrV4 = "172.18.180.159";
|
||||
# addrV6 = "fd00:0000:1337:cafe:1111:1111:ec5c:add3";
|
||||
})
|
||||
]
|
||||
in {
|
||||
options = with lib; {
|
||||
sane.ovpn.addrV4 = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
ovpn issues one IP address per device.
|
||||
set `null` to disable OVPN for this host.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkMerge [
|
||||
(def-ovpn "us" {
|
||||
endpoint = "vpn31.prd.losangeles.ovpn.com:9929";
|
||||
publicKey = "VW6bEWMOlOneta1bf6YFE25N/oMGh1E1UFBCfyggd0k=";
|
||||
id = 1;
|
||||
})
|
||||
(def-ovpn "us-mi" {
|
||||
endpoint = "vpn34.prd.miami.ovpn.com:9929";
|
||||
publicKey = "VtJz2irbu8mdkIQvzlsYhU+k9d55or9mx4A2a14t0V0=";
|
||||
id = 2;
|
||||
})
|
||||
(def-ovpn "ukr" {
|
||||
endpoint = "vpn96.prd.kyiv.ovpn.com:9929";
|
||||
publicKey = "CjZcXDxaaKpW8b5As1EcNbI6+42A6BjWahwXDCwfVFg=";
|
||||
id = 3;
|
||||
})
|
||||
# TODO: us-atl disabled until i need it again, i guess.
|
||||
# (def-ovpn "us-atl" {
|
||||
# endpoint = "vpn18.prd.atlanta.ovpn.com:9929";
|
||||
# publicKey = "Dpg/4v5s9u0YbrXukfrMpkA+XQqKIFpf8ZFgyw0IkE0=";
|
||||
# id = 4;
|
||||
# })
|
||||
];
|
||||
}
|
||||
|
@@ -65,10 +65,10 @@
|
||||
|
||||
# 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`.
|
||||
environment.etc."nixos" = lib.mkIf (config.sane.maxBuildCost >= 2) {
|
||||
environment.etc."nixos" = lib.mkIf (config.sane.maxBuildCost >= 3) {
|
||||
source = ../../..;
|
||||
};
|
||||
environment.etc."nix/registry.json" = lib.mkIf (config.sane.maxBuildCost < 2) {
|
||||
environment.etc."nix/registry.json" = lib.mkIf (config.sane.maxBuildCost < 3) {
|
||||
enable = false;
|
||||
};
|
||||
|
||||
|
@@ -1,72 +1,216 @@
|
||||
# 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
|
||||
environment.defaultPackages = [];
|
||||
# remove a few items from /run/wrappers we don't need.
|
||||
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.
|
||||
# this is defaulted in <repo:nixos/nixpkgs:nixos/modules/programs/environment.nix>,
|
||||
# without being gated by any higher config.
|
||||
environment.profiles = lib.mkForce [
|
||||
"/etc/profiles/per-user/$USER"
|
||||
"/run/current-system/sw"
|
||||
];
|
||||
options.environment.systemPackages = lib.mkOption {
|
||||
# see: <repo:nixos/nixpkgs:nixos/modules/config/system-path.nix>
|
||||
# it's 31 "requiredPackages", with no explanation of why they're "required"...
|
||||
# most of these can be safely removed without breaking the *boot*,
|
||||
# but some core system services DO implicitly depend on them.
|
||||
# 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>.
|
||||
# that's never existed on my system and everything does fine without it set empty (no nixpkgs API to forcibly *unset* it).
|
||||
environment.variables.NIXPKGS_CONFIG = lib.mkForce "";
|
||||
# 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 [];
|
||||
options.system.fsPackages = lib.mkOption {
|
||||
# <repo:nixos/nixpkgs:nixos/modules/tasks/filesystems/vfat.nix> adds `mtools` and `dosfstools`
|
||||
# dosfstools actually makes its way into the initrd (`fsck.vfat`).
|
||||
# mtools is like "MS-DOS for Linux", ancient functionality i'll never use.
|
||||
apply = lib.filter (p: p != pkgs.mtools);
|
||||
};
|
||||
|
||||
# disable nixos' portal module, otherwise /share/applications gets linked into the system and complicates things (sandboxing).
|
||||
# instead, i manage portals myself via the sane.programs API (e.g. sane.programs.xdg-desktop-portal).
|
||||
xdg.portal.enable = false;
|
||||
xdg.menus.enable = false; #< links /share/applications, and a bunch of other empty (i.e. unused) dirs
|
||||
config = {
|
||||
# disable non-required packages like nano, perl, rsync, strace
|
||||
environment.defaultPackages = [];
|
||||
|
||||
# xdg.autostart.enable defaults to true, and links /etc/xdg/autostart into the environment, populated with .desktop files.
|
||||
# see: <repo:nixos/nixpkgs:nixos/modules/config/xdg/autostart.nix>
|
||||
# .desktop files are a questionable way to autostart things: i generally prefer a service manager for that.
|
||||
xdg.autostart.enable = false;
|
||||
# remove all the non-existent default directories from XDG_DATA_DIRS, XDG_CONFIG_DIRS to simplify debugging.
|
||||
# this is defaulted in <repo:nixos/nixpkgs:nixos/modules/programs/environment.nix>,
|
||||
# without being gated by any higher config.
|
||||
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`
|
||||
# <repo:nixos/nixpkgs:nixos/modules/config/nix-channel.nix>
|
||||
# TODO: may want to recreate NIX_PATH, nix.settings.nix-path
|
||||
nix.channel.enable = false;
|
||||
# NIXPKGS_CONFIG defaults to "/etc/nix/nixpkgs-config.nix" in <nixos/modules/programs/environment.nix>.
|
||||
# that's never existed on my system and everything does fine without it set empty (no nixpkgs API to forcibly *unset* it).
|
||||
environment.variables.NIXPKGS_CONFIG = lib.mkForce "";
|
||||
# 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,
|
||||
# so as to inform when trying to run a non-nixos binary?
|
||||
# IMO that's confusing: i thought /lib/ld-linux.so was some file actually required by nix.
|
||||
environment.stub-ld.enable = false;
|
||||
# disable nixos' portal module, otherwise /share/applications gets linked into the system and complicates things (sandboxing).
|
||||
# instead, i manage portals myself via the sane.programs API (e.g. sane.programs.xdg-desktop-portal).
|
||||
xdg.portal.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.
|
||||
# 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 "";
|
||||
# xdg.autostart.enable defaults to true, and links /etc/xdg/autostart into the environment, populated with .desktop files.
|
||||
# see: <repo:nixos/nixpkgs:nixos/modules/config/xdg/autostart.nix>
|
||||
# .desktop files are a questionable way to autostart things: i generally prefer a service manager for that.
|
||||
xdg.autostart.enable = false;
|
||||
|
||||
# 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
|
||||
];
|
||||
# nix.channel.enable: populates `/nix/var/nix/profiles/per-user/root/channels`, `/root/.nix-channels`, `$HOME/.nix-defexpr/channels`
|
||||
# <repo:nixos/nixpkgs:nixos/modules/config/nix-channel.nix>
|
||||
# TODO: may want to recreate NIX_PATH, nix.settings.nix-path
|
||||
nix.channel.enable = false;
|
||||
|
||||
# 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)";
|
||||
# environment.stub-ld: populate /lib/ld-linux.so with an object that unconditionally errors on launch,
|
||||
# so as to inform when trying to run a non-nixos binary?
|
||||
# IMO that's confusing: i thought /lib/ld-linux.so was some file actually required by nix.
|
||||
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.
|
||||
# see: <https://github.com/alsa-project/alsa-ucm-conf/pull/134>
|
||||
# these audio files come from some revision of:
|
||||
# - <https://gitlab.manjaro.org/manjaro-arm/packages/community/phosh/alsa-ucm-pinephone>
|
||||
# - still true as of 2024-05-26
|
||||
# - see: <https://github.com/alsa-project/alsa-ucm-conf/pull/134>
|
||||
#
|
||||
# alternative to patching is to plumb `ALSA_CONFIG_UCM2 = "${./ucm2}"` environment variable into the relevant places
|
||||
# e.g. `systemd.services.pulseaudio.environment`.
|
||||
# that leaves more opportunity for gaps (i.e. missing a service),
|
||||
# on the other hand this method causes about 500 packages to be rebuilt (including qt5 and webkitgtk).
|
||||
# we can substitute working UCM conf in two ways:
|
||||
# 1. nixpkgs' override for the `alsa-ucm-conf` package
|
||||
# - that forces a rebuild of ~500 packages (including 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:
|
||||
# - headphones work.
|
||||
# - "internal earpiece" works.
|
||||
# - "internal speaker" doesn't work (but that's probably because i broke the ribbon cable)
|
||||
# - "analog output" doesn't work.
|
||||
packageUnwrapped = pkgs.alsa-ucm-conf.overrideAttrs (upstream: {
|
||||
postPatch = (upstream.postPatch or "") + ''
|
||||
cp ${./ucm2/PinePhone}/* ucm2/Allwinner/A64/PinePhone/
|
||||
# alsa-ucm-pinephone-manjaro (2024-05-26):
|
||||
# - headphones work
|
||||
# - "internal earpiece" works
|
||||
# - "internal speaker" is silent (maybe hardware issue)
|
||||
# - 3.5mm connection is flapping when playing to my car, which eventually breaks audio and requires restarting wireplumber
|
||||
# packageUnwrapped = pkgs.alsa-ucm-pinephone-manjaro.override {
|
||||
# inherit (cfg.config) preferEarpiece;
|
||||
# };
|
||||
# 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
|
||||
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
|
||||
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.
|
||||
# but ALSA_CONFIG_UCM2 is an env var that can override that.
|
||||
|
@@ -34,6 +34,7 @@ in
|
||||
];
|
||||
|
||||
sysadminUtils = declPackageSet [
|
||||
"ausyscall"
|
||||
"bridge-utils" # for brctl; debug linux "bridge" inet devices
|
||||
"btrfs-progs"
|
||||
"cacert.unbundled" # some services require unbundled /etc/ssl/certs
|
||||
@@ -43,6 +44,7 @@ in
|
||||
"dtc" # device tree [de]compiler
|
||||
"e2fsprogs" # resize2fs
|
||||
"efibootmgr"
|
||||
"errno"
|
||||
"ethtool"
|
||||
"fatresize"
|
||||
"fd"
|
||||
@@ -66,6 +68,8 @@ in
|
||||
"lftp"
|
||||
# "libcap_ng" # for `netcap`
|
||||
"lsof"
|
||||
"man-pages"
|
||||
"man-pages-posix"
|
||||
# "miniupnpc"
|
||||
"nano"
|
||||
# "ncdu" # ncurses disk usage. doesn't cross compile (zig)
|
||||
@@ -207,6 +211,175 @@ in
|
||||
# "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
|
||||
|
||||
@@ -234,14 +407,6 @@ in
|
||||
bridge-utils.sandbox.method = "bwrap"; #< bwrap, landlock: both work
|
||||
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.autodetectCliPaths = "existing"; # e.g. `btrfs filesystem df /my/fs`
|
||||
|
||||
@@ -302,7 +467,7 @@ in
|
||||
];
|
||||
|
||||
dtc.sandbox.method = "bwrap";
|
||||
dtc.sandbox.autodetectCliPaths = true; # TODO:sandbox: untested
|
||||
dtc.sandbox.autodetectCliPaths = "existingFile"; # TODO:sandbox: untested
|
||||
|
||||
duplicity = {};
|
||||
|
||||
@@ -338,10 +503,9 @@ in
|
||||
ethtool.sandbox.capabilities = [ "net_admin" ];
|
||||
|
||||
# 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 = "bwrap";
|
||||
eza.sandbox.autodetectCliPaths = true;
|
||||
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 = "existing";
|
||||
eza.sandbox.whitelistPwd = true;
|
||||
eza.sandbox.extraHomePaths = [
|
||||
# so that e.g. `eza -l ~` can show which symlink exist
|
||||
@@ -353,7 +517,7 @@ in
|
||||
fatresize.sandbox.autodetectCliPaths = "parent"; # /dev/sda1 -> needs /dev/sda
|
||||
|
||||
fd.sandbox.method = "landlock";
|
||||
fd.sandbox.autodetectCliPaths = true;
|
||||
fd.sandbox.autodetectCliPaths = "existing";
|
||||
fd.sandbox.whitelistPwd = true;
|
||||
fd.sandbox.extraHomePaths = [
|
||||
# let it follow symlinks to non-sensitive data
|
||||
@@ -366,10 +530,10 @@ in
|
||||
ffmpeg.sandbox.autodetectCliPaths = "existingFileOrParent"; # it outputs uncreated files -> parent dir needs mounting
|
||||
|
||||
file.sandbox.method = "bwrap";
|
||||
file.sandbox.autodetectCliPaths = true;
|
||||
file.sandbox.autodetectCliPaths = "existing"; #< file OR directory, yes
|
||||
|
||||
findutils.sandbox.method = "bwrap";
|
||||
findutils.sandbox.autodetectCliPaths = true;
|
||||
findutils.sandbox.autodetectCliPaths = "existing";
|
||||
findutils.sandbox.whitelistPwd = true;
|
||||
findutils.sandbox.extraHomePaths = [
|
||||
# let it follow symlinks to non-sensitive data
|
||||
@@ -388,9 +552,7 @@ in
|
||||
});
|
||||
|
||||
forkstat.sandbox.method = "landlock"; #< doesn't seem to support bwrap
|
||||
forkstat.sandbox.extraConfig = [
|
||||
"--sane-sandbox-keep-namespace" "pid"
|
||||
];
|
||||
forkstat.sandbox.isolatePids = false;
|
||||
forkstat.sandbox.extraPaths = [
|
||||
"/proc"
|
||||
];
|
||||
@@ -404,7 +566,7 @@ in
|
||||
|
||||
gawk.sandbox.method = "bwrap"; # TODO:sandbox: untested
|
||||
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.method = "landlock"; # permission denied when trying to attach, even as root
|
||||
@@ -445,11 +607,6 @@ in
|
||||
"gnome.gnome-calendar".sandbox.method = "bwrap";
|
||||
"gnome.gnome-calendar".sandbox.whitelistWayland = true;
|
||||
|
||||
"gnome.gnome-clocks".buildCost = 1;
|
||||
"gnome.gnome-clocks".sandbox.method = "bwrap";
|
||||
"gnome.gnome-clocks".sandbox.whitelistWayland = true;
|
||||
"gnome.gnome-clocks".suggestedPrograms = [ "dconf" ];
|
||||
|
||||
# gnome-disks
|
||||
"gnome.gnome-disk-utility".buildCost = 1;
|
||||
"gnome.gnome-disk-utility".sandbox.method = "bwrap";
|
||||
@@ -505,7 +662,7 @@ in
|
||||
"gnome.hitori".sandbox.whitelistWayland = true;
|
||||
|
||||
gnugrep.sandbox.method = "bwrap";
|
||||
gnugrep.sandbox.autodetectCliPaths = true;
|
||||
gnugrep.sandbox.autodetectCliPaths = "existing";
|
||||
gnugrep.sandbox.whitelistPwd = true;
|
||||
gnugrep.sandbox.extraHomePaths = [
|
||||
# let it follow symlinks to non-sensitive data
|
||||
@@ -513,7 +670,6 @@ in
|
||||
".persist/plaintext"
|
||||
];
|
||||
|
||||
# sed: there is an edgecase of `--file=<foo>`, wherein `foo` won't be whitelisted.
|
||||
gnused.sandbox.method = "bwrap";
|
||||
gnused.sandbox.autodetectCliPaths = "existingFile";
|
||||
gnused.sandbox.whitelistPwd = true; #< `-i` flag creates a temporary file in pwd (?) and then moves it.
|
||||
@@ -539,7 +695,7 @@ in
|
||||
|
||||
# hdparm: has to be run as sudo. e.g. `sudo hdparm -i /dev/sda`
|
||||
hdparm.sandbox.method = "bwrap";
|
||||
hdparm.sandbox.autodetectCliPaths = true;
|
||||
hdparm.sandbox.autodetectCliPaths = "existingFile";
|
||||
|
||||
host.sandbox.method = "landlock";
|
||||
host.sandbox.net = "all"; #< technically, only needs to contact localhost's DNS server
|
||||
@@ -573,14 +729,17 @@ in
|
||||
];
|
||||
iotop.sandbox.capabilities = [ "net_admin" ];
|
||||
|
||||
# provides `ip`, `routel`, others
|
||||
iproute2.sandbox.method = "landlock";
|
||||
iproute2.sandbox.net = "all";
|
||||
iproute2.sandbox.capabilities = [ "net_admin" ];
|
||||
iproute2.sandbox.extraPaths = [
|
||||
"/run/netns" # for `ip netns ...` to work
|
||||
"/var/run/netns"
|
||||
];
|
||||
# provides `ip`, `routel`, `bridge`, others.
|
||||
# landlock works fine for most of these, but `ip netns exec` wants to attach to an existing namespace
|
||||
# and that means we can't use ANY sandboxer for it.
|
||||
iproute2.sandbox.enable = false;
|
||||
# iproute2.sandbox.net = "all";
|
||||
# iproute2.sandbox.capabilities = [ "net_admin" ];
|
||||
# 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.net = "all";
|
||||
@@ -619,6 +778,9 @@ in
|
||||
"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)
|
||||
|
||||
libnotify.sandbox.method = "bwrap";
|
||||
@@ -644,6 +806,9 @@ in
|
||||
|
||||
lua = {};
|
||||
|
||||
man-pages.sandbox.enable = false;
|
||||
man-pages-posix.sandbox.enable = false;
|
||||
|
||||
mercurial.sandbox.method = "bwrap"; # TODO:sandbox: untested
|
||||
mercurial.sandbox.net = "clearnet";
|
||||
mercurial.sandbox.whitelistPwd = true;
|
||||
@@ -686,9 +851,15 @@ in
|
||||
nixpkgs-review.sandbox.wrapperType = "inplace"; #< shell completions use full paths
|
||||
nixpkgs-review.sandbox.net = "clearnet";
|
||||
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 = [
|
||||
"/nix"
|
||||
];
|
||||
nixpkgs-review.persist.byStore.cryptClearOnBoot = [
|
||||
".cache/nixpkgs-review" #< help it not exhaust / tmpfs
|
||||
];
|
||||
|
||||
nmap.sandbox.method = "bwrap";
|
||||
nmap.sandbox.net = "all"; # clearnet and lan
|
||||
@@ -717,6 +888,8 @@ in
|
||||
# settings (electron app)
|
||||
obsidian.persist.byStore.plaintext = [ ".config/obsidian" ];
|
||||
|
||||
passt.sandbox.enable = false; #< sandbox helper (netns specifically)
|
||||
|
||||
parted.sandbox.method = "landlock";
|
||||
parted.sandbox.extraPaths = [
|
||||
"/dev"
|
||||
@@ -748,9 +921,7 @@ in
|
||||
|
||||
# procps: free, pgrep, pidof, pkill, ps, pwait, top, uptime, couple others
|
||||
procps.sandbox.method = "bwrap";
|
||||
procps.sandbox.extraConfig = [
|
||||
"--sane-sandbox-keep-namespace" "pid"
|
||||
];
|
||||
procps.sandbox.isolatePids = false;
|
||||
|
||||
pstree.sandbox.method = "landlock";
|
||||
pstree.sandbox.extraPaths = [
|
||||
@@ -788,15 +959,21 @@ in
|
||||
|
||||
rustc = {};
|
||||
|
||||
sane-cast = {}; #< TODO: sandbox this the same way i sandbox go2tv
|
||||
sane-cast.sandbox.method = "bwrap";
|
||||
sane-cast.sandbox.net = "clearnet";
|
||||
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
|
||||
|
||||
sequoia.sandbox.method = "bwrap"; # TODO:sandbox: untested
|
||||
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" ];
|
||||
@@ -818,6 +995,10 @@ in
|
||||
smartmontools.sandbox.autodetectCliPaths = "existing";
|
||||
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.extraHomePaths = [
|
||||
".config/sops"
|
||||
@@ -889,7 +1070,7 @@ in
|
||||
tokodon.persist.byStore.private = [ ".cache/KDE/tokodon" ];
|
||||
|
||||
tree.sandbox.method = "landlock";
|
||||
tree.sandbox.autodetectCliPaths = true;
|
||||
tree.sandbox.autodetectCliPaths = "existing";
|
||||
tree.sandbox.whitelistPwd = true;
|
||||
|
||||
tumiki-fighters.buildCost = 1;
|
||||
@@ -956,6 +1137,8 @@ in
|
||||
wl-clipboard.sandbox.whitelistWayland = true;
|
||||
|
||||
wtype = {};
|
||||
wtype.sandbox.method = "bwrap";
|
||||
wtype.sandbox.whitelistWayland = true;
|
||||
|
||||
xwayland.sandbox.method = "bwrap";
|
||||
xwayland.sandbox.wrapperType = "inplace"; #< consumers use it as a library (e.g. wlroots)
|
||||
@@ -974,7 +1157,44 @@ in
|
||||
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;
|
||||
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
|
||||
);
|
||||
};
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.whitelistAudio = true;
|
||||
sandbox.whitelistWayland = true;
|
||||
sandbox.autodetectCliPaths = true;
|
||||
sandbox.autodetectCliPaths = "existingFile";
|
||||
sandbox.extraHomePaths = [
|
||||
# support media imports via file->open dir to some common media directories
|
||||
"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
|
||||
{
|
||||
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.extraHomePaths = [
|
||||
".cache/fontconfig" #< else it complains, and is *way* slower
|
||||
|
@@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
|
||||
# map from known devices -> required flags
|
||||
DEVICE_MAP = {
|
||||
"Theater TV": [],
|
||||
"[LG] webOS TV OLED55C9PUA": [ "-usewav" ],
|
||||
"Cuddlevision": [ "-usewav" ],
|
||||
}
|
||||
|
||||
def get_ranked_ip_addrs():
|
||||
|
@@ -39,11 +39,9 @@ in
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.whitelistAudio = true;
|
||||
sandbox.net = "clearnet";
|
||||
sandbox.extraConfig = [
|
||||
# else it fails to reap its children (or, maybe, it fails to hook its parent's death signal?)
|
||||
# might be possible to remove this, but kinda hard to see a clean way.
|
||||
"--sane-sandbox-keep-namespace" "pid"
|
||||
];
|
||||
#v 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.
|
||||
sandbox.isolatePids = false;
|
||||
suggestedPrograms = [ "blast-ugjka" "sane-die-with-parent" ];
|
||||
};
|
||||
|
||||
|
@@ -103,19 +103,37 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
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.extraRuntimePaths = [
|
||||
"/" #< just needs "bonsai", but needs to create it first...
|
||||
"bonsai"
|
||||
];
|
||||
|
||||
services.bonsaid = {
|
||||
description = "bonsai: programmable input dispatcher";
|
||||
dependencyOf = [ "sway" ]; # to ensure `$XDG_RUNTIME_DIR/bonsai` exists before sway binds it
|
||||
partOf = [ "graphical-session" ];
|
||||
# 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)
|
||||
command = "nice -n -11 bonsaid -t $HOME/.config/bonsai/bonsai_tree.json";
|
||||
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
|
||||
"tmp"
|
||||
];
|
||||
sandbox.extraPaths = [
|
||||
"/tmp" # needed particularly if run from `sane-vpn do`
|
||||
];
|
||||
sandbox.whitelistAudio = true;
|
||||
sandbox.whitelistDri = 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
|
||||
# - <https://gitlab.gnome.org/GNOME/calls>
|
||||
# - both a dialer and a call handler.
|
||||
# - uses callaudiod dbus package.
|
||||
# - uses callaudiod dbus service.
|
||||
#
|
||||
# initial JMP.chat configuration:
|
||||
# - 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.
|
||||
# just copy those into gnome-calls' GUI configurator
|
||||
# - now gnome-calls can do outbound calls. inbound calls requires more chatting with the help bot
|
||||
#
|
||||
# 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, ... }:
|
||||
# - now gnome-calls can do outbound calls. inbound calls can be routed by messaging the bot: "configure calls"
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.sane.programs.calls;
|
||||
in
|
||||
@@ -25,31 +19,52 @@ in
|
||||
type = types.submodule {
|
||||
options.autostart = mkOption {
|
||||
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 = [
|
||||
# ".cache/folks" # contact avatars?
|
||||
# ".config/calls"
|
||||
".local/share/calls" # call "records"
|
||||
# .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;
|
||||
suggestedPrograms = [
|
||||
"callaudiod" # runtime dependency (optional, but probably needed for mic muting?)
|
||||
"feedbackd" # needs `phone-incoming-call`, in particular
|
||||
"gnome-keyring" # to remember the password
|
||||
];
|
||||
|
||||
services.gnome-calls = {
|
||||
# TODO: prevent gnome-calls from daemonizing when started manually
|
||||
description = "gnome-calls daemon to monitor incoming SIP calls";
|
||||
partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ];
|
||||
# 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,7 +1,18 @@
|
||||
{ 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 = {
|
||||
# TODO: non-sandboxed `conky` still ships via `sxmo-utils`, but unused
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.net = "clearnet"; #< for the scripts it calls (weather)
|
||||
sandbox.extraPaths = [
|
||||
@@ -12,18 +23,16 @@
|
||||
];
|
||||
sandbox.whitelistWayland = true;
|
||||
|
||||
fs.".config/conky/conky.conf".symlink.target =
|
||||
let
|
||||
# TODO: make this just another `suggestedPrograms`!
|
||||
battery_estimate = pkgs.static-nix-shell.mkBash {
|
||||
pname = "battery_estimate";
|
||||
srcRoot = ./.;
|
||||
};
|
||||
in pkgs.substituteAll {
|
||||
src = ./conky.conf;
|
||||
bat = "${battery_estimate}/bin/battery_estimate";
|
||||
weather = "timeout 20 ${pkgs.sane-weather}/bin/sane-weather";
|
||||
};
|
||||
suggestedPrograms = [
|
||||
"sane-battery-estimate"
|
||||
"sane-weather"
|
||||
];
|
||||
|
||||
fs.".config/conky/conky.conf".symlink.target = pkgs.substituteAll {
|
||||
src = ./conky.conf;
|
||||
bat = "sane-battery-estimate";
|
||||
weather = "timeout 20 sane-weather";
|
||||
};
|
||||
|
||||
services.conky = {
|
||||
description = "conky dynamic desktop background";
|
||||
|
@@ -1,4 +1,3 @@
|
||||
#!/bin/sh
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash
|
||||
|
||||
@@ -15,7 +14,7 @@ usage() {
|
||||
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_dis=("" "" "" "")
|
||||
suffix_icon=" " # thin space
|
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 = {
|
||||
description = "dconf configuration database/server";
|
||||
partOf = [ "graphical-session" ];
|
||||
partOf = [ "default" ];
|
||||
command = "${lib.getLib cfg.package}/libexec/dconf-service";
|
||||
};
|
||||
|
||||
|
@@ -9,11 +9,14 @@
|
||||
./animatch.nix
|
||||
./assorted.nix
|
||||
./audacity.nix
|
||||
./ausyscall.nix
|
||||
./bemenu.nix
|
||||
./blast-ugjka
|
||||
./bonsai.nix
|
||||
./brave.nix
|
||||
./brightnessctl.nix
|
||||
./bubblewrap.nix
|
||||
./callaudiod.nix
|
||||
./calls.nix
|
||||
./cantata.nix
|
||||
./catt.nix
|
||||
@@ -23,6 +26,7 @@
|
||||
./cozy.nix
|
||||
./cups.nix
|
||||
./curlftpfs.nix
|
||||
./dbus.nix
|
||||
./dconf.nix
|
||||
./deadd-notification-center
|
||||
./dialect.nix
|
||||
@@ -33,11 +37,11 @@
|
||||
./element-desktop.nix
|
||||
./engrampa.nix
|
||||
./epiphany.nix
|
||||
./errno.nix
|
||||
./evince.nix
|
||||
./fcitx5.nix
|
||||
./feedbackd.nix
|
||||
./firefox.nix
|
||||
./firejail.nix
|
||||
./flare-signal.nix
|
||||
./fontconfig.nix
|
||||
./fractal.nix
|
||||
@@ -48,6 +52,7 @@
|
||||
./gdbus.nix
|
||||
./geary.nix
|
||||
./git.nix
|
||||
./gnome-clocks.nix
|
||||
./gnome-feeds.nix
|
||||
./gnome-keyring
|
||||
./gnome-maps.nix
|
||||
@@ -55,6 +60,7 @@
|
||||
./go2tv.nix
|
||||
./gpodder.nix
|
||||
./grimshot.nix
|
||||
./gst-device-monitor.nix
|
||||
./gthumb.nix
|
||||
./gvfs.nix
|
||||
./handbrake.nix
|
||||
@@ -74,6 +80,7 @@
|
||||
./megapixels.nix
|
||||
./mepo.nix
|
||||
./mimeo
|
||||
./mmcli.nix
|
||||
./modemmanager.nix
|
||||
./mopidy.nix
|
||||
./mpv
|
||||
@@ -85,6 +92,7 @@
|
||||
./nheko.nix
|
||||
./nicotine-plus.nix
|
||||
./nix-index.nix
|
||||
./nmcli.nix
|
||||
./notejot.nix
|
||||
./ntfy-sh.nix
|
||||
./objdump.nix
|
||||
@@ -102,11 +110,14 @@
|
||||
./s6-rc.nix
|
||||
./sane-input-handler
|
||||
./sane-open.nix
|
||||
./sane-sandboxed.nix
|
||||
./sane-screenshot.nix
|
||||
./sane-scripts.nix
|
||||
./sane-theme.nix
|
||||
./sanebox.nix
|
||||
./schlock.nix
|
||||
./seatd.nix
|
||||
./sfeed.nix
|
||||
./shadow.nix
|
||||
./signal-desktop.nix
|
||||
./splatmoji.nix
|
||||
./spot.nix
|
||||
|
@@ -22,6 +22,8 @@ in
|
||||
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
|
||||
@@ -38,9 +40,7 @@ in
|
||||
ExecStart = "${cfg.package}/bin/eg25-control --ensure-agps-cache --verbose";
|
||||
Restart = "no";
|
||||
|
||||
User = "eg25-control";
|
||||
WorkingDirectory = "/var/lib/eg25-control";
|
||||
StateDirectory = "eg25-control";
|
||||
User = "colin";
|
||||
};
|
||||
startAt = "hourly"; # this is a bit more than necessary, but idk systemd calendar syntax
|
||||
after = [ "network-online.target" "nss-lookup.target" ];
|
||||
@@ -48,26 +48,10 @@ in
|
||||
# wantedBy = [ "network-online.target" ]; # auto-start immediately after boot
|
||||
};
|
||||
|
||||
users = lib.mkIf cfg.enabled {
|
||||
groups.eg25-control = {};
|
||||
users.eg25-control = {
|
||||
group = "eg25-control";
|
||||
isSystemUser = true;
|
||||
home = "/var/lib/eg25-control";
|
||||
extraGroups = [
|
||||
"dialout" # required to read /dev/ttyUSB1
|
||||
"networkmanager" # required to authenticate with mmcli
|
||||
];
|
||||
};
|
||||
};
|
||||
sane.persist.sys.byStore.plaintext = lib.mkIf cfg.enabled [
|
||||
# to persist agps data, i think.
|
||||
{ user = "eg25-control"; group = "eg25-control"; path = "/var/lib/eg25-control"; }
|
||||
];
|
||||
services.udev.extraRules = let
|
||||
chmod = "${pkgs.coreutils}/bin/chmod";
|
||||
chown = "${pkgs.coreutils}/bin/chown";
|
||||
in ''
|
||||
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 = {
|
||||
packageUnwrapped = (pkgs.element-desktop.override {
|
||||
# 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: {
|
||||
# fix to use wayland instead of Xwayland:
|
||||
# - replace `NIXOS_OZONE_WL` non-empty check with `WAYLAND_DISPLAY`
|
||||
|
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";
|
||||
};
|
||||
}
|
@@ -4,7 +4,7 @@
|
||||
buildCost = 1;
|
||||
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.autodetectCliPaths = true;
|
||||
sandbox.autodetectCliPaths = "existingFile";
|
||||
sandbox.whitelistWayland = true;
|
||||
|
||||
mime.associations."application/pdf" = "org.gnome.Evince.desktop";
|
||||
|
@@ -209,7 +209,7 @@ in
|
||||
};
|
||||
i-still-dont-care-about-cookies = {
|
||||
package = pkgs.firefox-extensions.i-still-dont-care-about-cookies;
|
||||
enable = lib.mkDefault true;
|
||||
enable = lib.mkDefault false; #< obsoleted by uBlock Origin annoyances/cookies lists
|
||||
};
|
||||
open-in-mpv = {
|
||||
# test: `open-in-mpv 'mpv:///open?url=https://www.youtube.com/watch?v=dQw4w9WgXcQ'`
|
||||
@@ -226,7 +226,7 @@ in
|
||||
};
|
||||
ublacklist = {
|
||||
package = pkgs.firefox-extensions.ublacklist;
|
||||
enable = lib.mkDefault true;
|
||||
enable = lib.mkDefault false;
|
||||
};
|
||||
ublock-origin = {
|
||||
package = pkgs.firefox-extensions.ublock-origin;
|
||||
@@ -286,24 +286,35 @@ in
|
||||
# env.BROWSER = "${package}/bin/${cfg.browser.libName}";
|
||||
env.BROWSER = cfg.browser.libName; # used by misc tools like xdg-email, as fallback
|
||||
|
||||
# uBlock filter list configuration.
|
||||
# specifically, enable the GDPR cookie prompt blocker.
|
||||
# data.toOverwrite.filterLists is additive (i.e. it supplements the default filters)
|
||||
# this configuration method is documented here:
|
||||
# - <https://github.com/gorhill/uBlock/issues/2986#issuecomment-364035002>
|
||||
# the specific attribute path is found via scraping ublock code here:
|
||||
# - <https://github.com/gorhill/uBlock/blob/master/src/js/storage.js>
|
||||
# - <https://github.com/gorhill/uBlock/blob/master/assets/assets.json>
|
||||
fs."${cfg.browser.dotDir}/managed-storage/uBlock0@raymondhill.net.json".symlink.text = ''
|
||||
{
|
||||
"name": "uBlock0@raymondhill.net",
|
||||
"description": "ignored",
|
||||
"type": "storage",
|
||||
"data": {
|
||||
"toOverwrite": "{\"filterLists\": [\"fanboy-cookiemonster\"]}"
|
||||
}
|
||||
}
|
||||
'';
|
||||
# uBlock configuration:
|
||||
fs."${cfg.browser.dotDir}/managed-storage/uBlock0@raymondhill.net.json".symlink.target = cfg.addons.ublock-origin.package.makeConfig {
|
||||
# more filter lists are available here:
|
||||
# - <https://easylist.to>
|
||||
# - <https://github.com/easylist/easylist.git>
|
||||
# - <https://github.com/yokoffing/filterlists>
|
||||
filterFiles = let
|
||||
getUasset = n: "${pkgs.uassets}/share/filters/${n}.txt";
|
||||
in [
|
||||
# default ublock filters:
|
||||
(getUasset "ublock-filters")
|
||||
(getUasset "ublock-badware")
|
||||
(getUasset "ublock-privacy")
|
||||
(getUasset "ublock-quick-fixes")
|
||||
(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
|
||||
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,
|
||||
@@ -327,6 +338,8 @@ in
|
||||
defaultPref("widget.use-xdg-desktop-portal.open-uri", 1);
|
||||
|
||||
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.
|
||||
// can do this with other protocols too (e.g. matrix?). see about:config for common handlers.
|
||||
@@ -351,7 +364,7 @@ in
|
||||
|
||||
# TODO: env.PASSWORD_STORE_DIR only needs to be present within the browser session.
|
||||
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";
|
||||
|
||||
# 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)
|
||||
# - (phone)
|
||||
# - (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")
|
||||
# lots of redundant data inside there, but no deduplication except whatever nix or the fs does implicitly.
|
||||
wantedNerdfonts = [
|
||||
# used explicitly by SXMO
|
||||
# "DejaVuSansMono" # 25 MiB
|
||||
# good terminal/coding font. grab via nerdfonts for more emoji/unicode support
|
||||
"Hack" # 26 MiB
|
||||
"Noto" # 861 MiB
|
||||
|
@@ -24,8 +24,7 @@ in
|
||||
{
|
||||
sane.programs.fractal = {
|
||||
packageUnwrapped = pkgs.fractal-nixified.optimized;
|
||||
# packageUnwrapped = pkgs.fractal-latest;
|
||||
# packageUnwrapped = pkgs.fractal-next;
|
||||
# packageUnwrapped = pkgs.fractal;
|
||||
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.net = "clearnet";
|
||||
|
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" ];
|
||||
};
|
||||
}
|
@@ -50,7 +50,7 @@ in
|
||||
sane.programs.go2tv = {
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.net = "clearnet";
|
||||
sandbox.autodetectCliPaths = true;
|
||||
sandbox.autodetectCliPaths = "existingFile";
|
||||
# for GUI invocation, allow the common media directories
|
||||
sandbox.extraHomePaths = [
|
||||
"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)
|
||||
];
|
||||
});
|
||||
};
|
||||
}
|
@@ -17,7 +17,7 @@
|
||||
|
||||
# disable expensive sambda dependency; i don't use it.
|
||||
packageUnwrapped = pkgs.handbrake.override {
|
||||
ffmpeg-full = pkgs.ffmpeg-full.override {
|
||||
ffmpeg_7-full = pkgs.ffmpeg_7-full.override {
|
||||
withSamba = false;
|
||||
};
|
||||
};
|
||||
|
@@ -8,7 +8,7 @@
|
||||
packageUnwrapped = pkgs.libreoffice-fresh;
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.whitelistWayland = true;
|
||||
sandbox.autodetectCliPaths = true;
|
||||
sandbox.autodetectCliPaths = "existingFile";
|
||||
sandbox.extraHomePaths = [
|
||||
# allow a spot to save files.
|
||||
# with bwrap sandboxing, saving to e.g. ~/ succeeds but the data is inaccessible outside the sandbox,
|
||||
|
@@ -1,3 +1,10 @@
|
||||
# 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 = {
|
||||
@@ -45,11 +52,9 @@
|
||||
sandbox.extraRuntimePaths = [
|
||||
"dconf" #< else it's very spammy, and slow
|
||||
];
|
||||
sandbox.extraConfig = [
|
||||
# XXX(2024/04/21): without this it fails to convert .dng -> .jpg.
|
||||
# "bwrap: open /proc/34/ns/ns failed: No such file or directory"
|
||||
"--sane-sandbox-keep-namespace" "pid"
|
||||
];
|
||||
# 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
|
||||
};
|
||||
|
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
|
||||
};
|
||||
}
|
||||
|
@@ -4,35 +4,83 @@ let
|
||||
in
|
||||
{
|
||||
sane.programs.modemmanager = {
|
||||
packageUnwrapped = pkgs.modemmanager-split.daemon.overrideAttrs (upstream: {
|
||||
postInstall = (upstream.postInstall or "") + ''
|
||||
substitute $out/share/dbus-1/system.d/org.freedesktop.ModemManager1.conf \
|
||||
$out/share/dbus-1/system.d/networkmanager-org.freedesktop.ModemManager1.conf \
|
||||
--replace-fail 'user="root"' 'group="networkmanager"'
|
||||
'';
|
||||
|
||||
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"
|
||||
];
|
||||
};
|
||||
|
||||
networking.modemmanager = lib.mkIf cfg.enabled {
|
||||
enable = true;
|
||||
package = cfg.package;
|
||||
};
|
||||
|
||||
systemd.services.ModemManager = lib.mkIf cfg.enabled {
|
||||
aliases = [ "dbus-org.freedesktop.ModemManager1.service" ];
|
||||
# aliases = [ "dbus-org.freedesktop.ModemManager1.service" ];
|
||||
after = [ "polkit.service" ];
|
||||
requires = [ "polkit.service" ];
|
||||
wantedBy = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
Type = "dbus";
|
||||
BusName = "org.freedesktop.ModemManager1";
|
||||
# only if started with `--debug` does mmcli let us issue AT commands like
|
||||
# `mmcli --modem any --command=<AT_CMD>`
|
||||
ExecStart = "${cfg.package}/bin/ModemManager --debug";
|
||||
# --debug sets DEBUG level logging: so reset
|
||||
ExecStartPost = "${cfg.package}/bin/mmcli --set-logging=INFO";
|
||||
path = [ "/run/current-system/sw" ]; #< so it can find `sanebox`
|
||||
|
||||
Restart = "on-abort";
|
||||
StandardError = "null";
|
||||
CapabilityBoundingSet = "CAP_SYS_ADMIN CAP_NET_ADMIN";
|
||||
ProtectSystem = true;
|
||||
ProtectHome = true;
|
||||
PrivateTmp = true;
|
||||
RestrictAddressFamilies = "AF_NETLINK AF_UNIX AF_QIPCRTR";
|
||||
NoNewPrivileges = true;
|
||||
};
|
||||
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 ];
|
||||
# services.udev.packages = lib.mkIf cfg.enabled [ cfg.package ];
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@
|
||||
# - <https://github.com/mpv-player/mpv/wiki>
|
||||
# extensions i use:
|
||||
# - <https://github.com/jonniek/mpv-playlistmanager>
|
||||
# - <https://github.com/ekisu/mpv-webm>
|
||||
# - <https://github.com/mfcc64/mpv-scripts/blob/master/visualizer.lua>
|
||||
# other extensions that could be useful:
|
||||
# - list: <https://github.com/stax76/awesome-mpv>
|
||||
# - list: <https://nudin.github.io/mpv-script-directory/>
|
||||
@@ -124,6 +126,15 @@ let
|
||||
'"cycle fullscreen",'
|
||||
'';
|
||||
});
|
||||
visualizer = pkgs.mpvScripts.visualizer.overrideAttrs (upstream: {
|
||||
postPatch = (upstream.postPatch or "") + ''
|
||||
# don't have the script register its own keybinding: i'll do it manually via input.conf.
|
||||
# substituteInPlace visualizer.lua --replace-fail \
|
||||
# 'mp.add_key_binding' '-- mp.add_key_binding'
|
||||
substituteInPlace visualizer.lua --replace-fail \
|
||||
'cycle_key = "c"' 'cycle_key = "v"'
|
||||
'';
|
||||
});
|
||||
mpv-unwrapped = pkgs.mpv-unwrapped.overrideAttrs (upstream: {
|
||||
version = "0.37.0-unstable-2024-03-31";
|
||||
src = lib.warnIf (lib.versionOlder "0.37.0" upstream.version) "mpv outdated; remove patch?" pkgs.fetchFromGitHub {
|
||||
@@ -148,7 +159,9 @@ in
|
||||
scripts = [
|
||||
pkgs.mpvScripts.mpris
|
||||
pkgs.mpvScripts.mpv-playlistmanager
|
||||
pkgs.mpvScripts.mpv-webm
|
||||
uosc
|
||||
visualizer
|
||||
# pkgs.mpv-uosc-latest
|
||||
];
|
||||
# extraMakeWrapperArgs = lib.optionals (cfg.config.vo != null) [
|
||||
@@ -190,7 +203,7 @@ in
|
||||
];
|
||||
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.autodetectCliPaths = true;
|
||||
sandbox.autodetectCliPaths = "parent"; #< especially for subtitle downloader; also nice for viewing albums
|
||||
sandbox.net = "all";
|
||||
sandbox.whitelistAudio = true;
|
||||
sandbox.whitelistDbus = [ "user" ]; #< mpris
|
||||
@@ -213,6 +226,9 @@ in
|
||||
# for `watch_later`
|
||||
".local/state/mpv"
|
||||
];
|
||||
persist.byStore.private = [
|
||||
"Videos/mpv"
|
||||
];
|
||||
fs.".config/mpv/scripts/sane_cast/main.lua".symlink.target = ./sane_cast/main.lua;
|
||||
fs.".config/mpv/scripts/sane_sysvol/main.lua".symlink.target = ./sane_sysvol/main.lua;
|
||||
fs.".config/mpv/scripts/sane_sysvol/non_blocking_popen.lua".symlink.target = ./sane_sysvol/non_blocking_popen.lua;
|
||||
@@ -222,6 +238,8 @@ in
|
||||
fs.".config/mpv/script-opts/console.conf".symlink.target = ./console.conf;
|
||||
fs.".config/mpv/script-opts/uosc.conf".symlink.target = ./uosc.conf;
|
||||
fs.".config/mpv/script-opts/playlistmanager.conf".symlink.target = ./playlistmanager.conf;
|
||||
fs.".config/mpv/script-opts/webm.conf".symlink.target = ./webm.conf;
|
||||
fs.".config/mpv/script-opts/visualizer.conf".symlink.target = ./visualizer.conf;
|
||||
|
||||
# mime.priority = 200; # default = 100; 200 means to yield to other apps
|
||||
mime.priority = 50; # default = 100; 50 in order to take precedence over vlc.
|
||||
|
@@ -4,7 +4,7 @@
|
||||
# - properties: <https://mpv.io/manual/master/#property-list>
|
||||
|
||||
# let volume/power keys be interpreted by the system.
|
||||
# this is important for sxmo.
|
||||
# this is important for moby/bonsai.
|
||||
# mpv defaults is POWER = close, VOLUME_{UP,DOWN} = adjust application-level volume
|
||||
POWER ignore
|
||||
VOLUME_UP ignore
|
||||
@@ -19,7 +19,7 @@ s script-binding uosc/subtitles #! Subtitles
|
||||
a script-binding uosc/audio #! Audio tracks
|
||||
q script-binding uosc/stream-quality #! Stream quality
|
||||
p script-binding uosc/items #! Playlist
|
||||
c script-binding uosc/chapters #! Chapters
|
||||
# c script-binding uosc/chapters #! Chapters
|
||||
> script-binding uosc/next #! Navigation > Next
|
||||
< script-binding uosc/prev #! Navigation > Prev
|
||||
o script-binding uosc/open-file #! Navigation > Open file
|
||||
@@ -35,3 +35,6 @@ O script-binding uosc/show-in-directory #! Utils > Show in directory
|
||||
# script-binding uosc/open-config-directory #! Utils > Open config directory
|
||||
ctrl+r script-binding sane_cast/blast #! Audiocast
|
||||
ctrl+t script-binding sane_cast/sane-cast #! Cast
|
||||
|
||||
# reserved: it uses this internally, isn't externally callable
|
||||
# v script-binding cycle-visualizer
|
||||
|
9
hosts/common/programs/mpv/visualizer.conf
Normal file
9
hosts/common/programs/mpv/visualizer.conf
Normal file
@@ -0,0 +1,9 @@
|
||||
# config:
|
||||
# - <https://raw.githubusercontent.com/mfcc64/mpv-scripts/master/visualizer.lua>
|
||||
name=off
|
||||
# height: {4..12}
|
||||
# - multi functional. for spectrograph, impacts the length of its tape
|
||||
height=4
|
||||
# quality: {verylow,low,medium,high,veryhigh}
|
||||
# - multi functional. seems to impact the FFT size, and thereby how quickly the spectrograph advances
|
||||
quality=medium
|
80
hosts/common/programs/mpv/webm.conf
Normal file
80
hosts/common/programs/mpv/webm.conf
Normal file
@@ -0,0 +1,80 @@
|
||||
# Defaults to shift+w
|
||||
keybind=c
|
||||
# If empty, saves on the same directory of the playing video.
|
||||
# A starting "~" will be replaced by the home dir.
|
||||
# This field is delimited by double-square-brackets - [[ and ]] - instead of
|
||||
# quotes, because Windows users might run into a issue when using
|
||||
# backslashes as a path separator. Examples of valid inputs for this field
|
||||
# would be: [[]] (the default, empty value), [[C:\Users\John]] (on Windows),
|
||||
# and [[/home/john]] (on Unix-like systems eg. Linux).
|
||||
# The [[]] delimiter is not needed when using from a configuration file
|
||||
# in the script-opts folder.
|
||||
output_directory=~/Videos/mpv
|
||||
run_detached=no
|
||||
# Template string for the output file
|
||||
# %f - Filename, with extension
|
||||
# %F - Filename, without extension
|
||||
# %T - Media title, if it exists, or filename, with extension (useful for some streams, such as YouTube).
|
||||
# %s, %e - Start and end time, with milliseconds
|
||||
# %S, %E - Start and end time, without milliseconds
|
||||
# %M - "-audio", if audio is enabled, empty otherwise
|
||||
# %R - "-(height)p", where height is the video's height, or scale_height, if it's enabled.
|
||||
# More specifiers are supported, see https://mpv.io/manual/master/#options-screenshot-template
|
||||
# Property expansion is supported (with %{} at top level, ${} when nested), see https://mpv.io/manual/master/#property-expansion
|
||||
output_template=%F-%S-%E
|
||||
# Scale video to a certain height, keeping the aspect ratio. -1 disables it.
|
||||
scale_height=-1
|
||||
# Change the FPS of the output video, dropping or duplicating frames as needed.
|
||||
# -1 means the FPS will be unchanged from the source.
|
||||
fps=-1
|
||||
# Target filesize, in kB. This will be used to calculate the bitrate
|
||||
# used on the encode. If this is set to <= 0, the video bitrate will be set
|
||||
# to 0, which might enable constant quality modes, depending on the
|
||||
# video codec that's used (VP8 and VP9, for example).
|
||||
target_filesize=7500
|
||||
# If true, will use stricter flags to ensure the resulting file doesn't
|
||||
# overshoot the target filesize. Not recommended, as constrained quality
|
||||
# mode should work well, unless you're really having trouble hitting
|
||||
# the target size.
|
||||
# strict_filesize_constraint=no
|
||||
# strict_bitrate_multiplier=0.95
|
||||
# In kilobits.
|
||||
strict_audio_bitrate=128
|
||||
# Sets the output format, from a few predefined ones.
|
||||
# Currently we have:
|
||||
# av1
|
||||
# hevc
|
||||
# webm-vp9 (libvpx-vp9/libopus)
|
||||
# avc (h264/AAC)
|
||||
# avc-nvenc (h264-NVENC/AAC)
|
||||
# webm-vp8 (libvpx/libvorbis)
|
||||
# gif
|
||||
# mp3 (libmp3lame)
|
||||
# and raw (rawvideo/pcm_s16le).
|
||||
output_format=avc
|
||||
twopass=yes
|
||||
# If set, applies the video filters currently used on the playback to the encode.
|
||||
apply_current_filters=yes
|
||||
# If set, writes the video's filename to the "Title" field on the metadata.
|
||||
write_filename_on_metadata=no
|
||||
# Set the number of encoding threads, for codecs libvpx and libvpx-vp9
|
||||
threads=4
|
||||
additional_flags=
|
||||
# Constant Rate Factor (CRF). The value meaning and limits may change,
|
||||
# from codec to codec. Set to -1 to disable.
|
||||
crf=10
|
||||
# Useful for flags that may impact output filesize, such as qmin, qmax etc
|
||||
# Won't be applied when strict_filesize_constraint is on.
|
||||
non_strict_additional_flags=
|
||||
# Display the encode progress, in %. Requires run_detached to be disabled.
|
||||
# On Windows, it shows a cmd popup. "auto" will display progress on non-Windows platforms.
|
||||
display_progress=auto
|
||||
# The font size used in the menu. Isn't used for the notifications (started encode, finished encode etc)
|
||||
font_size=28
|
||||
margin=30
|
||||
message_duration=20
|
||||
# gif dither mode, 0-5 for bayer w/ bayer_scale 0-5, 6 for paletteuse default (sierra2_4a)
|
||||
gif_dither=2
|
||||
# Force square pixels on output video
|
||||
# Some players like recent Firefox versions display videos with non-square pixels with wrong aspect ratio
|
||||
force_square_pixels=no
|
@@ -10,9 +10,9 @@
|
||||
]);
|
||||
}));
|
||||
|
||||
suggestedPrograms = [
|
||||
"gvfs" # browse ftp://, etc
|
||||
];
|
||||
# suggestedPrograms = [
|
||||
# "gvfs" # browse ftp://, etc (TODO: fix!)
|
||||
# ];
|
||||
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.whitelistDbus = [ "user" ]; # for portals launching apps
|
||||
@@ -36,11 +36,11 @@
|
||||
"/tmp"
|
||||
"/var"
|
||||
];
|
||||
sandbox.extraRuntimePaths = [
|
||||
# not sure if these are actually necessary
|
||||
"gvfs"
|
||||
"gvfsd"
|
||||
];
|
||||
# sandbox.extraRuntimePaths = [
|
||||
# # not sure if these are actually necessary
|
||||
# "gvfs"
|
||||
# "gvfsd"
|
||||
# ];
|
||||
|
||||
mime.priority = 150; #< default is 100, so higher means we fall-back to other apps that might be more specialized
|
||||
mime.associations = {
|
||||
|
@@ -151,8 +151,29 @@ in
|
||||
EOF
|
||||
'';
|
||||
};
|
||||
neovim-unwrapped' = with pkgs; (neovim-unwrapped.override {
|
||||
# optional: `neovim` defaults to luajit when not manually wrapping
|
||||
lua = luajit;
|
||||
}).overrideAttrs (upstream: {
|
||||
# fix cross compilation:
|
||||
# - neovim vendors lua `mpack` library,
|
||||
# which it tries to build for the wrong platform
|
||||
# and its vendored version has diverged in symbol names anyway
|
||||
postPatch = (upstream.postPatch or "") + ''
|
||||
substituteInPlace src/nvim/generators/preload.lua --replace-fail \
|
||||
"require 'nlua0'" "
|
||||
vim.mpack = require 'mpack'
|
||||
vim.mpack.encode = vim.mpack.pack
|
||||
vim.mpack.decode = vim.mpack.unpack
|
||||
vim.lpeg = require 'lpeg'
|
||||
"
|
||||
'' + lib.optionalString (!stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
|
||||
substituteInPlace runtime/CMakeLists.txt --replace-fail \
|
||||
'COMMAND $<TARGET_FILE:nvim_bin>' 'COMMAND ${pkgs.stdenv.hostPlatform.emulator pkgs.buildPackages} $<TARGET_FILE:nvim_bin>'
|
||||
'';
|
||||
});
|
||||
in pkgs.wrapNeovimUnstable
|
||||
pkgs.neovim-unwrapped
|
||||
neovim-unwrapped'
|
||||
# XXX(2024/05/13): manifestRc must be null for cross-compilation to work.
|
||||
# wrapper invokes `neovim` with all plugins enabled at build time i guess to generate caches and stuff?
|
||||
# alternative is to emulate `nvim-wrapper` during build.
|
||||
|
@@ -7,76 +7,224 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.sane.programs.networkmanager;
|
||||
networkmanager = pkgs.networkmanager.overrideAttrs (upstream: {
|
||||
src = pkgs.fetchFromGitea {
|
||||
domain = "git.uninsane.org";
|
||||
owner = "colin";
|
||||
repo = "NetworkManager";
|
||||
rev = "dev-sane-1.46.0";
|
||||
hash = "sha256-S5ZiOfCpwtVVVO+DP6OPodJqzSc/LW4waI42DRkT+RA=";
|
||||
};
|
||||
# patches = [];
|
||||
});
|
||||
networkmanager-split = pkgs.networkmanager-split.override { inherit networkmanager; };
|
||||
in
|
||||
{
|
||||
sane.programs.networkmanager = {
|
||||
suggestedPrograms = [ "wpa_supplicant" ];
|
||||
enableFor.system = lib.mkIf (builtins.any (en: en) (builtins.attrValues cfg.enableFor.user)) true;
|
||||
};
|
||||
config = lib.mkMerge [
|
||||
{
|
||||
sane.programs.networkmanager = {
|
||||
packageUnwrapped = networkmanager-split.daemon.overrideAttrs (upstream: {
|
||||
# postPatch = (upstream.postPatch or "") + ''
|
||||
# substituteInPlace src/{core/org.freedesktop.NetworkManager,nm-dispatcher/nm-dispatcher}.conf --replace-fail \
|
||||
# 'user="root"' 'user="networkmanager"'
|
||||
# '';
|
||||
postInstall = (upstream.postInstall or "") + ''
|
||||
# allow the bus to owned by either root or networkmanager users
|
||||
# use the group here, that way ordinary users can be elevated to control networkmanager
|
||||
# (via e.g. `nmcli`)
|
||||
for f in org.freedesktop.NetworkManager.conf nm-dispatcher.conf ; do
|
||||
substitute $out/share/dbus-1/system.d/$f \
|
||||
$out/share/dbus-1/system.d/networkmanager-$f \
|
||||
--replace-fail 'user="root"' 'group="networkmanager"'
|
||||
done
|
||||
|
||||
# add to systemd.packages so we get the service file it ships, then override what we need to customize (taken from nixpkgs)
|
||||
systemd.packages = lib.mkIf cfg.enabled [ cfg.package ];
|
||||
systemd.services.NetworkManager = lib.mkIf cfg.enabled {
|
||||
wantedBy = [ "network.target" ];
|
||||
aliases = [ "dbus-org.freedesktop.NetworkManager.service" ];
|
||||
# remove unused services to prevent any unexpected interactions
|
||||
rm $out/etc/systemd/system/{nm-cloud-setup.service,nm-cloud-setup.timer,nm-priv-helper.service}
|
||||
'';
|
||||
});
|
||||
|
||||
serviceConfig = {
|
||||
StateDirectory = "NetworkManager";
|
||||
StateDirectoryMode = 755; # not sure if this really needs to be 755
|
||||
};
|
||||
};
|
||||
suggestedPrograms = [ "nmcli" "wpa_supplicant" ];
|
||||
enableFor.system = lib.mkIf (builtins.any (en: en) (builtins.attrValues cfg.enableFor.user)) true;
|
||||
|
||||
systemd.services.NetworkManager-wait-online = lib.mkIf cfg.enabled{
|
||||
wantedBy = [ "network-online.target" ];
|
||||
};
|
||||
# this contains both the NetworkManager service and the NetworkManager-dispatcher service
|
||||
# the latter of which calls a lot of user code.
|
||||
# as a result, this needs all the perms which my hook in modules/services/trust-dns/trust-dns-nmhook needs.
|
||||
sandbox.method = "landlock";
|
||||
sandbox.capabilities = [
|
||||
# "dac_override"
|
||||
"net_admin"
|
||||
"net_raw"
|
||||
"net_bind_service" #< TODO: is this needed? why? (DNS?)
|
||||
# "sys_module"
|
||||
"audit_write" #< allow writing to the audit log
|
||||
# "kill"
|
||||
];
|
||||
sandbox.extraPaths = [
|
||||
"/proc/net"
|
||||
"/proc/sys/net"
|
||||
"/run/NetworkManager"
|
||||
"/run/systemd" # for trust-dns-nmhook
|
||||
"/run/udev"
|
||||
# "/run/wg-home.priv"
|
||||
"/sys/class" #< TODO: specify this more precisely
|
||||
"/sys/devices"
|
||||
"/var/lib/NetworkManager"
|
||||
"/var/lib/trust-dns" #< for trust-dns-nmhook
|
||||
];
|
||||
|
||||
environment.etc = lib.mkIf cfg.enabled {
|
||||
"NetworkManager/NetworkManager.conf".text = ''
|
||||
# TODO: much of this is likely not needed.
|
||||
[connection]
|
||||
ethernet.cloned-mac-address=preserve
|
||||
wifi.cloned-mac-address=preserve
|
||||
wifi.powersave=null
|
||||
sandbox.whitelistDbus = [ "system" ];
|
||||
};
|
||||
}
|
||||
|
||||
[device]
|
||||
wifi.backend=wpa_supplicant
|
||||
wifi.scan-rand-mac-address=true
|
||||
(lib.mkIf cfg.enabled {
|
||||
# add to systemd.packages so we get the service file it ships, then override what we need to customize (taken from nixpkgs)
|
||||
# systemd.packages = [ cfg.package ];
|
||||
networking.networkmanager.enable = true;
|
||||
networking.networkmanager.enableDefaultPlugins = false;
|
||||
networking.networkmanager.package = cfg.package;
|
||||
systemd.services.NetworkManager = {
|
||||
# wantedBy = [ "network.target" ];
|
||||
aliases = [ "dbus-org.freedesktop.NetworkManager.service" ];
|
||||
|
||||
[keyfile]
|
||||
# keyfile.path: where to check for connection credentials
|
||||
path=/var/lib/NetworkManager/system-connections
|
||||
unmanaged-devices=null
|
||||
path = [ "/run/current-system/sw" ]; #< so it can find `sanebox`
|
||||
serviceConfig.RuntimeDirectory = "NetworkManager"; #< tells systemd to create /run/NetworkManager
|
||||
# serviceConfig.StateDirectory = "NetworkManager"; #< tells systemd to create /var/lib/NetworkManager
|
||||
serviceConfig.User = "networkmanager";
|
||||
serviceConfig.Group = "networkmanager";
|
||||
serviceConfig.AmbientCapabilities = [
|
||||
# "CAP_DAC_OVERRIDE"
|
||||
"CAP_NET_ADMIN"
|
||||
"CAP_NET_RAW"
|
||||
"CAP_NET_BIND_SERVICE" #< this *does* seem to be necessary, though i don't understand why. DHCP?
|
||||
# "CAP_SYS_MODULE"
|
||||
"CAP_AUDIT_WRITE" #< allow writing to the audit log
|
||||
# "CAP_KILL"
|
||||
];
|
||||
};
|
||||
|
||||
[logging]
|
||||
audit=false
|
||||
level=WARN
|
||||
systemd.services.NetworkManager-wait-online = {
|
||||
path = [ "/run/current-system/sw" ]; #< so `nm-online` can find `sanebox`
|
||||
# wantedBy = [ "network-online.target" ];
|
||||
serviceConfig.User = "networkmanager";
|
||||
serviceConfig.Group = "networkmanager";
|
||||
};
|
||||
|
||||
[main]
|
||||
dhcp=internal
|
||||
dns=systemd-resolved
|
||||
plugins=keyfile
|
||||
rc-manager=unmanaged
|
||||
'';
|
||||
};
|
||||
hardware.wirelessRegulatoryDatabase = lib.mkIf cfg.enabled true;
|
||||
networking.useDHCP = lib.mkIf cfg.enabled false;
|
||||
users.groups = lib.mkIf cfg.enabled {
|
||||
networkmanager.gid = config.ids.gids.networkmanager;
|
||||
};
|
||||
services.udev.packages = lib.mkIf cfg.enabled [ cfg.package ];
|
||||
security.polkit.enable = lib.mkIf cfg.enabled true;
|
||||
security.polkit.extraConfig = ''
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (
|
||||
subject.isInGroup("networkmanager")
|
||||
&& (action.id.indexOf("org.freedesktop.NetworkManager.") == 0
|
||||
|| action.id.indexOf("org.freedesktop.ModemManager") == 0
|
||||
))
|
||||
{ return polkit.Result.YES; }
|
||||
});
|
||||
'';
|
||||
systemd.services.NetworkManager-dispatcher = {
|
||||
# wantedBy = [ "NetworkManager.service" ];
|
||||
after = [ "trust-dns-localhost.service" ]; #< so that /var/lib/trust-dns will exist
|
||||
path = [ "/run/current-system/sw" ]; #< so it can find `sanebox`
|
||||
# to debug, add NM_DISPATCHER_DEBUG_LOG=1
|
||||
serviceConfig.ExecStart = [
|
||||
"" # first blank line is to clear the upstream `ExecStart` field.
|
||||
"${cfg.package}/libexec/nm-dispatcher --persist" # --persist is needed for it to actually run as a daemon
|
||||
];
|
||||
serviceConfig.Restart = "always";
|
||||
serviceConfig.RestartSec = "1s";
|
||||
serviceConfig.User = "networkmanager";
|
||||
serviceConfig.Group = "networkmanager";
|
||||
};
|
||||
|
||||
boot.kernelModules = [ "ctr" ]; #< TODO: needed (what even is this)?
|
||||
# TODO: polkit?
|
||||
# TODO: NetworkManager-ensure-profiles?
|
||||
networking.networkmanager.settings = {
|
||||
# wifi.backend = "wpa_supplicant";
|
||||
# wifi.scan-rand-mac-address = true;
|
||||
|
||||
# logging.audit = false;
|
||||
logging.level = "INFO";
|
||||
|
||||
# main.dhcp = "internal";
|
||||
main.dns = if config.services.resolved.enable then
|
||||
"systemd-resolved"
|
||||
else if config.sane.services.trust-dns.enable && config.sane.services.trust-dns.asSystemResolver then
|
||||
"none"
|
||||
else
|
||||
"internal"
|
||||
;
|
||||
main.systemd-resolved = false;
|
||||
};
|
||||
|
||||
environment.etc = {
|
||||
"NetworkManager/system-connections".source = "/var/lib/NetworkManager/system-connections";
|
||||
# "NetworkManager/NetworkManager.conf".text = ''
|
||||
# [device]
|
||||
# # wifi.backend: wpa_supplicant or iwd
|
||||
# wifi.backend=wpa_supplicant
|
||||
# wifi.scan-rand-mac-address=true
|
||||
|
||||
# [logging]
|
||||
# audit=false
|
||||
# # level: TRACE, DEBUG, INFO, WARN, ERR, OFF
|
||||
# level=INFO
|
||||
# # domain=...
|
||||
|
||||
# [main]
|
||||
# # dhcp:
|
||||
# # - `internal` (default)
|
||||
# # - `dhclient` (requires dhclient to be installed)
|
||||
# # - `dhcpcd` (requires dhcpcd to be installed)
|
||||
# dhcp=internal
|
||||
# # dns:
|
||||
# # - `default`: update /etc/resolv.conf with nameservers provided by the active connection
|
||||
# # - `none`: NM won't update /etc/resolv.conf
|
||||
# # - `systemd-resolved`: push DNS config to systemd-resolved
|
||||
# # - `dnsmasq`: run a local caching nameserver
|
||||
# dns=${if config.services.resolved.enable then
|
||||
# "systemd-resolved"
|
||||
# else if config.sane.services.trust-dns.enable && config.sane.services.trust-dns.asSystemResolver then
|
||||
# "none"
|
||||
# else
|
||||
# "internal"
|
||||
# }
|
||||
# plugins=keyfile
|
||||
# # rc-manager: how NM should write to /etc/resolv.conf
|
||||
# # - regardless of this setting, NM will write /var/lib/NetworkManager/resolv.conf
|
||||
# rc-manager=unmanaged
|
||||
# # systemd-resolved: send DNS config to systemd-resolved?
|
||||
# # this setting has no effect if dns="systemd-resolved"; it's supplementary, not absolute.
|
||||
# systemd-resolved=false
|
||||
# # debug=... (see also: NM_DEBUG env var)
|
||||
# '';
|
||||
};
|
||||
|
||||
# hardware.wirelessRegulatoryDatabase = true;
|
||||
# networking.useDHCP = false;
|
||||
# services.udev.packages = [ cfg.package ];
|
||||
# security.polkit.enable = lib.mkDefault true;
|
||||
|
||||
# security.polkit.extraConfig = lib.concatStringsSep "\n" [
|
||||
# # allow networkmanager unbounded control over modemmanager.
|
||||
# # i believe this was sourced from the default nixpkgs config.
|
||||
# ''
|
||||
# polkit.addRule(function(action, subject) {
|
||||
# if (subject.isInGroup("networkmanager")
|
||||
# && (
|
||||
# action.id.indexOf("org.freedesktop.NetworkManager.") == 0
|
||||
# || action.id.indexOf("org.freedesktop.ModemManager") == 0
|
||||
# )
|
||||
# ) {
|
||||
# return polkit.Result.YES;
|
||||
# }
|
||||
# });
|
||||
# ''
|
||||
|
||||
# allow networkmanager to control systemd-resolved,
|
||||
# which it needs to do to apply new DNS settings when using systemd-resolved.
|
||||
security.polkit.extraConfig = ''
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (subject.isInGroup("networkmanager") && action.id.indexOf("org.freedesktop.resolve1.") == 0) {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
});
|
||||
'';
|
||||
|
||||
# users.groups.networkmanager.gid = config.ids.gids.networkmanager;
|
||||
users.users.networkmanager = {
|
||||
isSystemUser = true;
|
||||
group = "networkmanager";
|
||||
extraGroups = [ "trust-dns" ];
|
||||
};
|
||||
|
||||
# boot.kernelModules = [ "ctr" ]; #< TODO: needed (what even is this)?
|
||||
# TODO: NetworkManager-ensure-profiles?
|
||||
})
|
||||
];
|
||||
}
|
||||
|
@@ -2,15 +2,7 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
sane.programs.nicotine-plus = {
|
||||
packageUnwrapped = pkgs.nicotine-plus.overrideAttrs (upstream: {
|
||||
postInstall = (upstream.postInstall or "") + ''
|
||||
# XXX: nixpkgs creates this symlink, seemingly just for convenience;
|
||||
# third-party tools like `firejail` lack a profile for "nicotine-plus", and just for "nicotine" instead.
|
||||
rm $out/bin/nicotine-plus
|
||||
'';
|
||||
});
|
||||
|
||||
sandbox.method = "firejail";
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.whitelistWayland = true;
|
||||
sandbox.net = "vpn";
|
||||
|
||||
|
7
hosts/common/programs/nmcli.nix
Normal file
7
hosts/common/programs/nmcli.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
sane.programs.nmcli = {
|
||||
packageUnwrapped = pkgs.networkmanager-split.nmcli;
|
||||
# TODO: sandbox
|
||||
};
|
||||
}
|
@@ -3,7 +3,8 @@
|
||||
sane.programs.notejot = {
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.whitelistWayland = true;
|
||||
sandbox.extraPaths = [ ".config/dconf" ]; #< for legacy notes (moby), loaded via dconf
|
||||
sandbox.whitelistDri = true; #< otherwise intolerably slow on moby
|
||||
sandbox.extraHomePaths = [ ".config/dconf" ]; #< for legacy notes (moby), loaded via dconf
|
||||
suggestedPrograms = [ "dconf" ]; #< else it can't persist notes
|
||||
|
||||
persist.byStore.private = [
|
||||
|
@@ -41,6 +41,9 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# disabling systemd causes pipewire to be built with direct udev support instead
|
||||
packageUnwrapped = pkgs.pipewire.override { enableSystemd = false; };
|
||||
|
||||
suggestedPrograms = [
|
||||
# "rtkit"
|
||||
"wireplumber"
|
||||
@@ -60,9 +63,7 @@ in
|
||||
# "system"
|
||||
# ];
|
||||
sandbox.wrapperType = "inplace"; #< its config files refer to its binaries by full path
|
||||
sandbox.extraConfig = [
|
||||
"--sane-sandbox-keep-namespace" "pid"
|
||||
];
|
||||
sandbox.isolatePids = false; #< TODO: why?
|
||||
sandbox.capabilities = [
|
||||
# if rtkit isn't present, and sandboxing is via landlock, these capabilities allow pipewire to claim higher scheduling priority
|
||||
"ipc_lock"
|
||||
@@ -143,7 +144,7 @@ in
|
||||
# '';
|
||||
|
||||
# see: <https://docs.pipewire.org/page_module_protocol_native.html>
|
||||
# defaults to placing the socket in /run/user/$id/{pipewire-0,pipewire-0-manager,...}
|
||||
# defaults to placing the socket in $XDG_RUNTIME_DIR/{pipewire-0,pipewire-0-manager,...}
|
||||
# but that's trickier to sandbox
|
||||
env.PIPEWIRE_RUNTIME_DIR = "$XDG_RUNTIME_DIR/pipewire";
|
||||
|
||||
@@ -179,6 +180,9 @@ in
|
||||
];
|
||||
cleanupCommand = ''rm -f "$XDG_RUNTIME_DIR/pulse/{native,pid}"'';
|
||||
};
|
||||
|
||||
# bring up sound by default
|
||||
services."sound".partOf = [ "default" ];
|
||||
};
|
||||
|
||||
# taken from nixos/modules/services/desktops/pipewire/pipewire.nix
|
||||
|
@@ -24,11 +24,13 @@
|
||||
"/tmp"
|
||||
"/var"
|
||||
];
|
||||
sandbox.extraRuntimePaths = [
|
||||
# not sure if these are actually necessary
|
||||
"gvfs"
|
||||
"gvfsd"
|
||||
];
|
||||
# sandbox.extraRuntimePaths = [
|
||||
# # not sure if these are actually necessary
|
||||
# "gvfs"
|
||||
# "gvfsd"
|
||||
# ];
|
||||
|
||||
# suggestedPrograms = [ "gvfs" ]; #< TODO: fix (ftp:// share, USB drive browsing)
|
||||
|
||||
mime.priority = 160; #< default is 100, so higher means we fall-back to other apps that might be more specialized
|
||||
mime.associations = {
|
||||
|
@@ -2,7 +2,7 @@
|
||||
{
|
||||
sane.programs.ripgrep = {
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.autodetectCliPaths = true;
|
||||
sandbox.autodetectCliPaths = "existing";
|
||||
sandbox.whitelistPwd = true;
|
||||
sandbox.extraHomePaths = [
|
||||
# let it follow symlinks to non-sensitive data
|
||||
|
@@ -5,7 +5,7 @@
|
||||
# - use as a launcher/file browser
|
||||
# - `rofi -sidebar-mode`
|
||||
# - separate tabs for filebrowser, drun, etc.
|
||||
# - `rofi -pid /run/user/$UID/rofi.pid -replace`
|
||||
# - `rofi -pid $XDG_RUNTIME_DIR/rofi.pid -replace`
|
||||
# - single-instance mode
|
||||
# - pid is probably optional, just need `-replace`.
|
||||
#
|
||||
@@ -112,9 +112,7 @@ in
|
||||
"/mnt/servo/media"
|
||||
"/mnt/servo/playground"
|
||||
];
|
||||
sandbox.extraConfig = [
|
||||
"--sane-sandbox-keep-namespace" "pid" # for sane-open to toggle keyboard
|
||||
];
|
||||
sandbox.isolatePids = false; # for sane-open to toggle keyboard
|
||||
|
||||
fs.".config/rofi/config.rasi".symlink.target = ./config.rasi;
|
||||
fs."Apps".symlink.target = ".local/share/applications/rofi-applications.desktop";
|
||||
@@ -160,15 +158,15 @@ in
|
||||
})
|
||||
];
|
||||
};
|
||||
# if i could remove the sed, then maybe possible to not sandbox.
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.whitelistWayland = true;
|
||||
sandbox.extraHomePaths = [
|
||||
".cache/rofi"
|
||||
".config/rofi/config.rasi"
|
||||
];
|
||||
sandbox.enable = false; # all dependencies are sandboxed
|
||||
# sandbox.method = "bwrap";
|
||||
# sandbox.whitelistWayland = true;
|
||||
# sandbox.extraHomePaths = [
|
||||
# ".cache/rofi"
|
||||
# ".config/rofi/config.rasi"
|
||||
# ];
|
||||
|
||||
suggestedPrograms = [ "rofi" ];
|
||||
suggestedPrograms = [ "gnused" "rofi" "wtype" ];
|
||||
|
||||
fs.".config/rofi-snippets/public.txt".symlink.target = ./snippets.txt;
|
||||
secrets.".config/rofi-snippets/private.txt" = ../../../../secrets/common/snippets.txt.bin;
|
||||
|
@@ -4,7 +4,11 @@
|
||||
# "bookmarking"/snippets inspired by Luke Smith:
|
||||
# - <https://www.youtube.com/watch?v=d_11QaTlf1I>
|
||||
|
||||
snippet=$(cat ~/.config/rofi-snippets/public.txt ~/.config/rofi-snippets/private.txt | \
|
||||
rofi -dmenu | \
|
||||
sed 's/ #.*$//')
|
||||
wtype "$snippet"
|
||||
# rofi flags (see: `man rofi-dmenu`):
|
||||
# `-i`: case insensitive filtering
|
||||
# `-sync -ellipsize-mode middle`: for lengthy entries, replace the *middle* with an ellipsis instead of the end
|
||||
# requires rofi 1.7.6, and `-sync`, wich must come *before* the `-dmenu` flag
|
||||
cat ~/.config/rofi-snippets/public.txt ~/.config/rofi-snippets/private.txt | \
|
||||
rofi -sync -ellipsize-mode middle -dmenu -i | \
|
||||
sed -z -e 's/ *#.*$//' -e 's/\n$//' | \
|
||||
wtype -
|
||||
|
@@ -5,7 +5,6 @@ https://nixos.org/manual/nix/stable/language/builtins.html
|
||||
https://github.com/nixos/nixpkgs/pulls?q=
|
||||
https://nur.nix-community.org/
|
||||
https://repology.org/projects/?maintainer=colin@uninsane.org&inrepo=nix_unstable&outdated=1
|
||||
https://lists.sr.ht/~mil/sxmo-devel
|
||||
https://w.uninsane.org/viewer#search?books.name=wikipedia_en_all_maxi_2022-05&pattern=
|
||||
https://jackett.uninsane.org/UI/Dashboard#search=
|
||||
https://lemmy.uninsane.org
|
||||
|
@@ -16,7 +16,7 @@
|
||||
'';
|
||||
});
|
||||
|
||||
persist.private = [
|
||||
persist.byStore.private = [
|
||||
".local/share/s6/logs"
|
||||
];
|
||||
|
||||
|
@@ -36,29 +36,14 @@ let
|
||||
in assert terminal -> events == []; events;
|
||||
|
||||
# trigger ${button}_hold_N every `holdTime` ms until ${button} is released
|
||||
recurseHold = button: { count ? 1, maxHolds ? 5, prefix ? "", holdTime ? 600, ... }@opts: lib.optionalAttrs (count <= maxHolds) {
|
||||
"${button}_released".terminal = true; # end the hold -> back to root state
|
||||
timeout = {
|
||||
ms = holdTime;
|
||||
trigger = "${prefix}${button}_hold_${builtins.toString count}";
|
||||
} // (recurseHold button (opts // { count = count+1; }));
|
||||
};
|
||||
|
||||
# trigger volup_tap_N or voldown_tap_N on every tap.
|
||||
# if a volume button is held, then switch into `recurseHold`'s handling instead
|
||||
volumeActions = { count ? 1, maxTaps ? 5, prefix ? "", timeout ? 600, ... }@opts: lib.optionalAttrs (count != maxTaps) {
|
||||
volup_pressed = (recurseHold "volup" opts) // {
|
||||
volup_released = {
|
||||
trigger = "${prefix}volup_tap_${builtins.toString count}";
|
||||
timeout.ms = timeout;
|
||||
} // (volumeActions (opts // { count = count+1; }));
|
||||
};
|
||||
voldown_pressed = (recurseHold "voldown" opts) // {
|
||||
voldown_released = {
|
||||
trigger = "${prefix}voldown_tap_${builtins.toString count}";
|
||||
timeout.ms = timeout;
|
||||
} // (volumeActions (opts // { count = count+1; }));
|
||||
};
|
||||
recurseHold = button: { count ? 1, maxHolds ? 3, holdTime ? 1000 }@opts: {
|
||||
trigger = "${button}_hold_${builtins.toString count}";
|
||||
ms = holdTime;
|
||||
} // lib.optionalAttrs (count < maxHolds) {
|
||||
timeout = recurseHold button (opts // { count = count+1; });
|
||||
# end the hold -> back to root state
|
||||
# take care to omit this on the last hold though, so that there's always a strictly delay-driven path back to root
|
||||
"${button}_released".terminal = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
@@ -112,9 +97,7 @@ in
|
||||
sandbox.whitelistAudio = true;
|
||||
sandbox.whitelistDbus = [ "user" ]; #< to launch applications
|
||||
sandbox.extraRuntimePaths = [ "sway" ];
|
||||
sandbox.extraConfig = [
|
||||
"--sane-sandbox-keep-namespace" "pid"
|
||||
];
|
||||
sandbox.isolatePids = false; #< for toggling the keyboard
|
||||
};
|
||||
|
||||
# sane.programs.actkbd = {
|
||||
@@ -163,14 +146,16 @@ in
|
||||
power_pressed.voldown_pressed.trigger = "power_and_voldown";
|
||||
|
||||
# map: volume taps and holds
|
||||
volup_pressed = (volumeActions {}).volup_pressed // {
|
||||
trigger = "volup_start";
|
||||
};
|
||||
voldown_pressed = (volumeActions {}).voldown_pressed // {
|
||||
trigger = "voldown_start";
|
||||
};
|
||||
volup_pressed.trigger = "volup_start";
|
||||
volup_pressed.volup_released.trigger = "volup_tap_1";
|
||||
volup_pressed.timeout = recurseHold "volup" {};
|
||||
|
||||
voldown_pressed.trigger = "voldown_start";
|
||||
voldown_pressed.voldown_released.trigger = "voldown_tap_1";
|
||||
voldown_pressed.timeout = recurseHold "voldown" {};
|
||||
});
|
||||
|
||||
sane.programs.sway.sandbox.extraRuntimePaths = lib.mkIf cfg.enabled [ "bonsai" ];
|
||||
sane.programs.sway.config.extra_lines = lib.mkIf cfg.enabled (
|
||||
''
|
||||
# bindsym --input-device=... :
|
||||
|
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p coreutils -p jq -p killall -p playerctl -p procps -p sane-open -p sway -p util-linux -p wireplumber
|
||||
# vim: set filetype=bash :
|
||||
|
||||
# input map considerations
|
||||
# - using compound actions causes delays.
|
||||
@@ -60,6 +61,24 @@ KEYBOARD="${KEYBOARD:-wvkbd-mobintl}"
|
||||
|
||||
action="$1"
|
||||
|
||||
showHelp() {
|
||||
echo "usage: sane-input-handler <action>"
|
||||
echo ""
|
||||
echo "where action is one of:"
|
||||
echo "- power_tap_{1,2}"
|
||||
echo "- power_hold"
|
||||
echo "- power_tap_1_hold"
|
||||
echo "- power_and_volup"
|
||||
echo "- power_and_voldown"
|
||||
echo "- power_then_volup"
|
||||
echo "- power_then_voldown"
|
||||
echo "- volup_tap_{1,2,3}"
|
||||
echo "- volup_hold_{1,2,3}"
|
||||
echo "- voldown_tap_{1,2,3}"
|
||||
echo "- voldown_hold_{1,2,3}"
|
||||
echo "- voldown_start"
|
||||
}
|
||||
|
||||
log() {
|
||||
printf "sane-input-handler: %s\n" "$1"
|
||||
}
|
||||
@@ -241,19 +260,31 @@ dispatchInhibited() {
|
||||
esac
|
||||
}
|
||||
|
||||
_isAllOn="$(isAllOn && echo 1 || true)"
|
||||
dispatchToplevel() {
|
||||
_isAllOn="$(isAllOn && echo 1 || true)"
|
||||
|
||||
if [ -z "$_isAllOn" ]; then
|
||||
dispatchOff
|
||||
else
|
||||
_isInhibited="$(isInhibited && echo 1 || true)"
|
||||
if [ -n "$_isInhibited" ]; then
|
||||
dispatchInhibited
|
||||
if [ -z "$_isAllOn" ]; then
|
||||
dispatchOff
|
||||
else
|
||||
dispatchOn
|
||||
_isInhibited="$(isInhibited && echo 1 || true)"
|
||||
if [ -n "$_isInhibited" ]; then
|
||||
dispatchInhibited
|
||||
else
|
||||
dispatchOn
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
dispatchDefault
|
||||
dispatchDefault
|
||||
}
|
||||
|
||||
case "$action" in
|
||||
(--help)
|
||||
showHelp
|
||||
exit 0
|
||||
;;
|
||||
(*)
|
||||
dispatchToplevel
|
||||
handleWith unmapped
|
||||
;;
|
||||
esac
|
||||
|
||||
handleWith unmapped
|
||||
|
@@ -4,13 +4,11 @@
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.autodetectCliPaths = "existing"; # for when opening a file
|
||||
sandbox.whitelistDbus = [ "user" ];
|
||||
sandbox.extraConfig = [
|
||||
"--sane-sandbox-keep-namespace" "pid" # to toggle keyboard
|
||||
];
|
||||
sandbox.isolatePids = false; #< to toggle keyboard
|
||||
sandbox.extraHomePaths = [
|
||||
".local/share/applications"
|
||||
];
|
||||
sandbox.extraRuntimePaths = [ "sway" ];
|
||||
sandbox.extraRuntimePaths = [ "sway" ]; #< calls `swaymsg` to query rotation and see if there's room for a keyboard
|
||||
suggestedPrograms = [
|
||||
"gdbus"
|
||||
"xdg-utils"
|
||||
|
@@ -1,19 +0,0 @@
|
||||
{ config, pkgs, ... }:
|
||||
let
|
||||
cfg = config.sane.programs;
|
||||
in
|
||||
{
|
||||
sane.programs.sane-sandboxed = {
|
||||
packageUnwrapped = pkgs.sane-sandboxed.override {
|
||||
bubblewrap = cfg.bubblewrap.package;
|
||||
firejail = cfg.firejail.package;
|
||||
landlock-sandboxer = pkgs.landlock-sandboxer.override {
|
||||
# not strictly necessary (landlock ABI is versioned), however when sandboxer version != kernel version,
|
||||
# the sandboxer may nag about one or the other wanting to be updated.
|
||||
linux = config.boot.kernelPackages.kernel;
|
||||
};
|
||||
};
|
||||
|
||||
sandbox.enable = false;
|
||||
};
|
||||
}
|
@@ -229,7 +229,8 @@ in
|
||||
fwmark=${builtins.toString vpnCfg.fwmark}
|
||||
priorityMain=${builtins.toString vpnCfg.priorityMain}
|
||||
priorityFwMark=${builtins.toString vpnCfg.priorityFwMark}
|
||||
bridgeDevice=${vpnCfg.bridgeDevice}
|
||||
addrV4=${vpnCfg.addrV4}
|
||||
name=${vpnCfg.name}
|
||||
dns=(${lib.concatStringsSep " " vpnCfg.dns})
|
||||
'';
|
||||
} // (lib.optionalAttrs vpnCfg.isDefault {
|
||||
@@ -239,19 +240,14 @@ in
|
||||
{}
|
||||
(builtins.attrNames config.sane.vpn);
|
||||
"sane-scripts.vpn".sandbox = {
|
||||
method = "landlock"; #< bwrap can't handle `ip link` stuff even with cap_net_admin
|
||||
net = "all";
|
||||
capabilities = [ "net_admin" ];
|
||||
extraHomePaths = [ ".config/sane-vpn" ];
|
||||
enable = false; #< bwrap can't handle `ip link`, and landlock can't handle bwrap/pasta for `sane-vpn do`
|
||||
# method = "landlock"; #< bwrap can't handle `ip link` stuff even with cap_net_admin
|
||||
# net = "all";
|
||||
# capabilities = [ "net_admin" ];
|
||||
# extraHomePaths = [ ".config/sane-vpn" ];
|
||||
};
|
||||
|
||||
"sane-scripts.which".sandbox = {
|
||||
method = "bwrap";
|
||||
extraHomePaths = [
|
||||
# for SXMO
|
||||
".config/sxmo/hooks"
|
||||
];
|
||||
};
|
||||
"sane-scripts.which".sandbox.method = "bwrap";
|
||||
|
||||
"sane-scripts.wipe".sandbox = {
|
||||
method = "bwrap";
|
||||
|
@@ -1,15 +1,6 @@
|
||||
# gtk apps search XDG_ICON_DIRS for icons (nixos specific)
|
||||
# nixos ships the hi-color icon theme by default, which has *some* icons,
|
||||
# but leaves a lot of standard ones unavailable.
|
||||
#
|
||||
# system-wide theme components live in:
|
||||
# - /run/current-system/sw/share/color-schemes/${theme}
|
||||
# - /run/current-system/sw/share/icons/${theme}
|
||||
# - /run/current-system/sw/share/icons/${theme}/cursors (cursor-theme)
|
||||
# - /run/current-system/sw/share/themes/${theme}/gtk-4.0
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.sane.gui.gtk;
|
||||
cfg = config.sane.programs.sane-theme.config;
|
||||
unsortedThemes = {
|
||||
# crude assortment of themes in nixpkgs; some might not be gtk themes, some gtk themes might not be in this list
|
||||
inherit (pkgs)
|
||||
@@ -278,38 +269,62 @@ let
|
||||
};
|
||||
in
|
||||
{
|
||||
options = with lib; {
|
||||
sane.gui.gtk.enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = "apply theme to gtk4 apps";
|
||||
sane.programs.sane-theme = {
|
||||
configOption = with lib; mkOption {
|
||||
default = {};
|
||||
type = types.submodule {
|
||||
options = {
|
||||
all = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = "install all known gtk themes (for testing)";
|
||||
};
|
||||
color-scheme = mkOption {
|
||||
default = "default";
|
||||
type = types.str;
|
||||
};
|
||||
cursor-theme = mkOption {
|
||||
default = "Adwaita";
|
||||
type = types.str;
|
||||
};
|
||||
gtk-theme = mkOption {
|
||||
default = "Adwaita";
|
||||
type = types.str;
|
||||
};
|
||||
icon-theme = mkOption {
|
||||
default = "Adwaita";
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
sane.gui.gtk.all = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = "install all known gtk themes (for testing)";
|
||||
};
|
||||
sane.gui.gtk.color-scheme = mkOption {
|
||||
default = "default";
|
||||
type = types.str;
|
||||
};
|
||||
sane.gui.gtk.cursor-theme = mkOption {
|
||||
default = "Adwaita";
|
||||
type = types.str;
|
||||
};
|
||||
sane.gui.gtk.gtk-theme = mkOption {
|
||||
default = "Adwaita";
|
||||
type = types.str;
|
||||
};
|
||||
sane.gui.gtk.icon-theme = mkOption {
|
||||
default = "Adwaita";
|
||||
type = types.str;
|
||||
packageUnwrapped = pkgs.symlinkJoin {
|
||||
name = "sane-theme";
|
||||
paths = [
|
||||
themes.color-scheme."${cfg.color-scheme}"
|
||||
themes.cursor-theme."${cfg.cursor-theme}"
|
||||
themes.gtk-theme."${cfg.gtk-theme}"
|
||||
themes.icon-theme."${cfg.icon-theme}"
|
||||
] ++ lib.optionals cfg.all (lib.attrValues unsortedThemes);
|
||||
};
|
||||
sandbox.enable = false; #< no binaries
|
||||
|
||||
suggestedPrograms = [
|
||||
"sane-backgrounds"
|
||||
];
|
||||
};
|
||||
|
||||
config.sane.programs.dconf.config.site = lib.mkIf cfg.enable [
|
||||
sane.programs.sane-backgrounds = {
|
||||
sandbox.enable = false; #< no binaries
|
||||
};
|
||||
|
||||
|
||||
environment.pathsToLink = lib.mkIf config.sane.programs.sane-backgrounds.enabled [
|
||||
"/share/backgrounds"
|
||||
];
|
||||
sane.programs.dconf.config.site = lib.mkIf config.sane.programs.sane-theme.enabled [
|
||||
(pkgs.writeTextFile {
|
||||
name = "dconf-sway-settings";
|
||||
name = "sane-theme";
|
||||
destination = "/etc/dconf/db/site.d/10_gtk_settings";
|
||||
text = ''
|
||||
[org/gnome/desktop/interface]
|
||||
@@ -320,13 +335,6 @@ in
|
||||
'';
|
||||
})
|
||||
];
|
||||
# environment.systemPackages = lib.attrValues themes;
|
||||
config.environment.systemPackages = lib.mkIf cfg.enable ([
|
||||
themes.color-scheme."${cfg.color-scheme}"
|
||||
themes.cursor-theme."${cfg.cursor-theme}"
|
||||
themes.gtk-theme."${cfg.gtk-theme}"
|
||||
themes.icon-theme."${cfg.icon-theme}"
|
||||
] ++ lib.optionals cfg.all (lib.attrValues unsortedThemes));
|
||||
|
||||
# XXX(2024/02/05): set GSK_RENDERER=cairo to solve graphical edge-case on moby where some JPEGs would render as black!
|
||||
# - repro by loading komikku and viewing images. some fail (particularly mangadex onimai), some work.
|
||||
@@ -338,4 +346,5 @@ in
|
||||
# - upstream gtk recommends using mesa 24.0 (latest) specifically in response to the GSK renderers triggering new driver bugs,
|
||||
# so maybe i can update that before re-enabling GSK_RENDERER anywhere else.
|
||||
# environment.variables.GSK_RENDERER = "cairo";
|
||||
|
||||
}
|
68
hosts/common/programs/sanebox.nix
Normal file
68
hosts/common/programs/sanebox.nix
Normal file
@@ -0,0 +1,68 @@
|
||||
{ config, lib, pkgs, sane-lib, ... }:
|
||||
let
|
||||
cfg = config.sane.programs;
|
||||
# create an AttrSet[String -> String]
|
||||
# which maps symlink path -> symlink content
|
||||
# for every symlink known to nix
|
||||
fsSymlinksAsAttrs = lib.concatMapAttrs
|
||||
(path: value: lib.optionalAttrs
|
||||
((value.symlink or null) != null)
|
||||
{
|
||||
"${path}" = value.symlink.target;
|
||||
}
|
||||
)
|
||||
config.sane.fs
|
||||
;
|
||||
in
|
||||
{
|
||||
sane.programs.sanebox = {
|
||||
packageUnwrapped = pkgs.sanebox.override {
|
||||
bubblewrap = cfg.bubblewrap.package;
|
||||
passt = cfg.passt.package;
|
||||
libcap = cfg.libcap.package;
|
||||
landlock-sandboxer = pkgs.landlock-sandboxer.override {
|
||||
# not strictly necessary (landlock ABI is versioned), however when sandboxer version != kernel version,
|
||||
# the sandboxer may nag about one or the other wanting to be updated.
|
||||
linux = config.boot.kernelPackages.kernel;
|
||||
};
|
||||
};
|
||||
|
||||
sandbox.enable = false;
|
||||
};
|
||||
|
||||
environment.etc = lib.mkIf cfg.sanebox.enabled {
|
||||
"sanebox/symlink-cache".text = lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsToList
|
||||
(k: v: "${k}\t${v}")
|
||||
({
|
||||
"/bin/sh" = config.environment.binsh;
|
||||
"${builtins.unsafeDiscardStringContext config.environment.binsh}" = "bash";
|
||||
"/usr/bin/env" = config.environment.usrbinenv;
|
||||
"${builtins.unsafeDiscardStringContext config.environment.usrbinenv}" = "coreutils";
|
||||
|
||||
# "/run/current-system" = "${config.system.build.toplevel}";
|
||||
# XXX: /run/current-system symlink can't be cached without forcing regular mass rebuilds:
|
||||
# mount it as if it were a directory instead.
|
||||
"/run/current-system" = "";
|
||||
} // lib.optionalAttrs config.hardware.opengl.enable {
|
||||
"/run/opengl-driver" = let
|
||||
gl = config.hardware.opengl;
|
||||
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/opengl.nix>
|
||||
package = pkgs.buildEnv {
|
||||
name = "opengl-drivers";
|
||||
paths = [ gl.package ] ++ gl.extraPackages;
|
||||
};
|
||||
in "${package}";
|
||||
} // lib.optionalAttrs (config.hardware.opengl.enable && config.hardware.opengl.driSupport32Bit) {
|
||||
"/run/opengl-driver-32" = let
|
||||
gl = config.hardware.opengl;
|
||||
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/opengl.nix>
|
||||
package = pkgs.buildEnv {
|
||||
name = "opengl-drivers-32bit";
|
||||
paths = [ gl.package32 ] ++ gl.extraPackages32;
|
||||
};
|
||||
in "${package}";
|
||||
} // fsSymlinksAsAttrs)
|
||||
);
|
||||
};
|
||||
}
|
52
hosts/common/programs/seatd.nix
Normal file
52
hosts/common/programs/seatd.nix
Normal file
@@ -0,0 +1,52 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.sane.programs.seatd;
|
||||
in
|
||||
lib.mkMerge [
|
||||
{
|
||||
sane.programs.seatd = {
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.capabilities = [
|
||||
"sys_tty_config" "sys_admin"
|
||||
"chown"
|
||||
"dac_override" #< TODO: is there no way to get rid of this?
|
||||
];
|
||||
sandbox.extraPaths = [
|
||||
"/dev" #< TODO: this can be removed if i have seatd restart on client error such that seatd can discover devices as they appear
|
||||
# "/dev/dri"
|
||||
# # "/dev/drm_dp_aux0"
|
||||
# # "/dev/drm_dp_aux1"
|
||||
# # "/dev/drm_dp_aux2"
|
||||
# # "/dev/fb0"
|
||||
# "/dev/input"
|
||||
# # "/dev/uinput"
|
||||
# "/dev/tty0"
|
||||
# "/dev/tty1"
|
||||
# "/proc"
|
||||
"/run" #< TODO: confine this to some subdirectory
|
||||
# "/sys"
|
||||
];
|
||||
};
|
||||
}
|
||||
(lib.mkIf cfg.enabled {
|
||||
users.groups.seat = {};
|
||||
|
||||
# TODO: /run/seatd.sock location can be configured, but only via compile-time flag
|
||||
systemd.services.seatd = {
|
||||
description = "Seat management daemon";
|
||||
documentation = [ "man:seatd(1)" ];
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
restartIfChanged = false;
|
||||
|
||||
path = [ "/run/current-system/sw" ]; #< so `sanebox` works
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStart = "${cfg.package}/bin/seatd -g seat";
|
||||
Group = "seat";
|
||||
# AmbientCapabilities = [ "CAP_SYS_TTY_CONFIG" "CAP_SYS_ADMIN" ];
|
||||
};
|
||||
};
|
||||
})
|
||||
]
|
@@ -1,6 +1,5 @@
|
||||
# simple RSS and Atom parser
|
||||
# - <https://codemadness.org/sfeed-simple-feed-parser.html>
|
||||
# - used by sxmo
|
||||
# - man 5 sfeedrc
|
||||
#
|
||||
# call `sfeed_update` to query each feed and populate entries in ~/.sfeed/feeds
|
||||
|
17
hosts/common/programs/shadow.nix
Normal file
17
hosts/common/programs/shadow.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.sane.programs.shadow;
|
||||
in
|
||||
{
|
||||
config = lib.mkMerge [
|
||||
{
|
||||
sane.programs.shadow = {
|
||||
sandbox.enable = false; #< `login` can't be sandboxed because it launches a user shell
|
||||
};
|
||||
}
|
||||
(lib.mkIf cfg.enabled {
|
||||
services.getty.loginProgram = "${cfg.package}/bin/login";
|
||||
security.pam.services.login.startSession = lib.mkForce false; #< disable systemd integration
|
||||
})
|
||||
];
|
||||
}
|
@@ -48,9 +48,7 @@ in
|
||||
description = "signal-desktop Signal Messenger client";
|
||||
# depends = [ "graphical-session" ];
|
||||
partOf = lib.mkIf cfg.config.autostart [ "graphical-session" ];
|
||||
|
||||
# for some reason the --ozone-platform-hint=auto flag fails when signal-desktop is launched from a service
|
||||
command = "env NIXOS_OZONE_WL=1 signal-desktop";
|
||||
command = "signal-desktop";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@
|
||||
# sway-config docs: `man 5 sway`
|
||||
let
|
||||
cfg = config.sane.programs.sway;
|
||||
enableXWayland = config.sane.programs.xwayland.enabled;
|
||||
wrapSway = configuredSway: let
|
||||
swayLauncher = pkgs.writeShellScriptBin "sway" ''
|
||||
test -e "$(dirname "$SWAYSOCK")" || \
|
||||
@@ -26,47 +27,59 @@ let
|
||||
];
|
||||
passthru.sway-unwrapped = configuredSway;
|
||||
};
|
||||
swayPackage = wrapSway (
|
||||
pkgs.waylandPkgs.sway-unwrapped.override {
|
||||
wlroots = (pkgs.waylandPkgs.wlroots.override {
|
||||
# wlroots seems to launch Xwayland itself, and i can't easily just do that myself externally.
|
||||
# so in order for the Xwayland it launches to be sandboxed, i need to patch the sandboxed version in here.
|
||||
xwayland = config.sane.programs.xwayland.package;
|
||||
}).overrideAttrs (upstream: {
|
||||
# 2023/09/08: fix so clicking a notification can activate the corresponding window.
|
||||
# - test: run dino, receive a message while tabbed away, click the desktop notification.
|
||||
# - if sway activates the dino window (i.e. colors the workspace and tab), then all good
|
||||
# - do all of this with only a touchscreen (e.g. on mobile phone) -- NOT a mouse/pointer
|
||||
# 2023/12/17: this patch is still necessary
|
||||
## what this patch does:
|
||||
# - allows any wayland window to request activation, at any time.
|
||||
# - traditionally, wayland only allows windows to request activation if
|
||||
# the client requesting to transfer control has some connection to a recent user interaction.
|
||||
# - e.g. the active window may transfer control to any window
|
||||
# - a window which was very recently active may transfer control to itself
|
||||
## alternative (longer-term) solutions:
|
||||
# - fix this class of bug in gtk:
|
||||
# - <https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/5782>
|
||||
# - N.B.: this linked PR doesn't actually fix it
|
||||
# - add xdg_activation_v1 support to SwayNC (my notification daemon):
|
||||
# - <https://github.com/ErikReider/SwayNotificationCenter/issues/71>
|
||||
# - mako notification daemon supports activation, can use as a reference
|
||||
# - all of ~30 LoC, looks straight-forward
|
||||
# - however, it's not clear that gtk4 (or dino) actually support this mode of activation.
|
||||
# - i.e. my experience with dino is the same using mako as with SwayNC
|
||||
postPatch = (upstream.postPatch or "") + ''
|
||||
substituteInPlace types/wlr_xdg_activation_v1.c \
|
||||
--replace-fail 'if (token->seat != NULL)' 'if (false && token->seat != NULL)'
|
||||
'';
|
||||
});
|
||||
|
||||
wlroots = (pkgs.waylandPkgs.wlroots.override {
|
||||
# wlroots seems to launch Xwayland itself, and i can't easily just do that myself externally.
|
||||
# so in order for the Xwayland it launches to be sandboxed, i need to patch the sandboxed version in here.
|
||||
xwayland = config.sane.programs.xwayland.package;
|
||||
}).overrideAttrs (upstream: {
|
||||
# 2023/09/08: fix so clicking a notification can activate the corresponding window.
|
||||
# - test: run dino, receive a message while tabbed away, click the desktop notification.
|
||||
# - if sway activates the dino window (i.e. colors the workspace and tab), then all good
|
||||
# - do all of this with only a touchscreen (e.g. on mobile phone) -- NOT a mouse/pointer
|
||||
# 2023/12/17: this patch is still necessary
|
||||
## what this patch does:
|
||||
# - allows any wayland window to request activation, at any time.
|
||||
# - traditionally, wayland only allows windows to request activation if
|
||||
# the client requesting to transfer control has some connection to a recent user interaction.
|
||||
# - e.g. the active window may transfer control to any window
|
||||
# - a window which was very recently active may transfer control to itself
|
||||
## alternative (longer-term) solutions:
|
||||
# - fix this class of bug in gtk:
|
||||
# - <https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/5782>
|
||||
# - N.B.: this linked PR doesn't actually fix it
|
||||
# - add xdg_activation_v1 support to SwayNC (my notification daemon):
|
||||
# - <https://github.com/ErikReider/SwayNotificationCenter/issues/71>
|
||||
# - mako notification daemon supports activation, can use as a reference
|
||||
# - all of ~30 LoC, looks straight-forward
|
||||
# - however, it's not clear that gtk4 (or dino) actually support this mode of activation.
|
||||
# - i.e. my experience with dino is the same using mako as with SwayNC
|
||||
postPatch = (upstream.postPatch or "") + ''
|
||||
substituteInPlace types/wlr_xdg_activation_v1.c \
|
||||
--replace-fail 'if (token->seat != NULL)' 'if (false && token->seat != NULL)'
|
||||
'';
|
||||
});
|
||||
swayPackage = wrapSway (
|
||||
(pkgs.waylandPkgs.sway-unwrapped.override {
|
||||
inherit wlroots;
|
||||
# about xwayland:
|
||||
# - required by many electron apps, though some electron apps support NIXOS_OZONE_WL=1 for native wayland.
|
||||
# - when xwayland is enabled, KOreader incorrectly chooses the X11 backend
|
||||
# -> slower; blurrier
|
||||
# - xwayland uses a small amount of memory (like 30MiB, IIRC?)
|
||||
enableXWayland = config.sane.programs.xwayland.enabled;
|
||||
}
|
||||
inherit enableXWayland;
|
||||
}).overrideAttrs (upstream: {
|
||||
# fix to create SWAYSOCK and WAYLAND_DISPLAY directly in a sandboxable subdirectory:
|
||||
# i can't simply move it after creation i think because that would
|
||||
# be an unsupported cross-device `mv`?
|
||||
postPatch = (upstream.postPatch or "") + ''
|
||||
substituteInPlace sway/ipc-server.c --replace-fail \
|
||||
'"%s/sway-ipc.%u.%i.sock", dir, getuid(), getpid())' \
|
||||
'"%s/sway/sway-ipc.sock", dir)'
|
||||
substituteInPlace sway/server.c --replace-fail \
|
||||
'"wayland-%u"' '"wl/wayland-%u"'
|
||||
'';
|
||||
})
|
||||
);
|
||||
in
|
||||
{
|
||||
@@ -87,9 +100,6 @@ in
|
||||
bindsym --locked XF86AudioLowerVolume exec $volume_down
|
||||
'';
|
||||
};
|
||||
background = mkOption {
|
||||
type = types.path;
|
||||
};
|
||||
font = mkOption {
|
||||
type = types.str;
|
||||
default = "pango:monospace 11";
|
||||
@@ -135,8 +145,11 @@ in
|
||||
"playerctl" # for waybar & particularly to have playerctld running
|
||||
"rofi" # menu/launcher
|
||||
"rofi-snippets"
|
||||
"s6-rc" # used by sway config
|
||||
"sane-screenshot"
|
||||
"sane-open"
|
||||
"sane-theme"
|
||||
"seatd"
|
||||
# "splatmoji" # used by sway config
|
||||
"sway-contrib.grimshot" # used by sway config
|
||||
"swayidle" # enable if you need it
|
||||
@@ -170,17 +183,20 @@ in
|
||||
];
|
||||
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.wrapperType = "inplace";
|
||||
sandbox.wrapperType = "inplace"; #< `sway` is a wrapper around `sway-unwrapped`, so cheap to sandbox
|
||||
sandbox.net = "all"; # TODO: shouldn't be needed! but without this, mouse/kb hotplug doesn't work.
|
||||
sandbox.whitelistAudio = true; # it runs playerctl directly
|
||||
sandbox.whitelistDbus = [ "system" "user" ]; # to e.g. launch apps
|
||||
sandbox.whitelistDri = true;
|
||||
sandbox.whitelistX = true; # sway invokes xwayland itself
|
||||
sandbox.whitelistWayland = true;
|
||||
sandbox.extraRuntimePaths = [ "/" ]; # TODO: should need just "sway". but even if i sandbox EVERY entry under run individually, it fails!
|
||||
sandbox.extraRuntimePaths = [
|
||||
"sway"
|
||||
];
|
||||
sandbox.extraPaths = [
|
||||
"/dev/input"
|
||||
"/run/systemd/sessions"
|
||||
# "/dev/input"
|
||||
"/run/seatd.sock" #< required if not using `logind` systemd login manager
|
||||
# "/run/systemd/sessions"
|
||||
"/run/udev"
|
||||
"/sys/class/backlight"
|
||||
"/sys/class/drm"
|
||||
@@ -203,13 +219,12 @@ in
|
||||
fs.".config/sway/config".symlink.target = pkgs.substituteAll {
|
||||
src = ./sway-config;
|
||||
inherit (cfg.config)
|
||||
background
|
||||
extra_lines
|
||||
font
|
||||
mod
|
||||
workspace_layout
|
||||
;
|
||||
xwayland = if config.sane.programs.xwayland.enabled then "enable" else "disable";
|
||||
xwayland = if enableXWayland then "enable" else "disable";
|
||||
};
|
||||
|
||||
env.XDG_CURRENT_DESKTOP = "sway";
|
||||
@@ -222,11 +237,19 @@ in
|
||||
env.DISPLAY = ":0";
|
||||
# docs: <https://discourse.ubuntu.com/t/environment-variables-for-wayland-hackers/12750>
|
||||
# N.B.: gtk apps support absolute paths for this; webkit apps (e.g. geary) support only relative paths (relative to $XDG_RUNTIME_DIR)
|
||||
env.WAYLAND_DISPLAY = "wayland/wayland-1";
|
||||
env.WAYLAND_DISPLAY = "wl/wayland-1";
|
||||
|
||||
services.sway = {
|
||||
description = "sway: tiling wayland desktop environment";
|
||||
dependencyOf = [ "graphical-session" ];
|
||||
partOf = [
|
||||
"wayland"
|
||||
] ++ lib.optionals enableXWayland [
|
||||
"x11"
|
||||
];
|
||||
# partOf = lib.mkMerge [
|
||||
# "wayland"
|
||||
# (lib.mkIf enableXWayland "x11")
|
||||
# ];
|
||||
command = pkgs.writeShellScript "sway-start" ''
|
||||
# have to create these directories before launching sway so that they're available in the sandbox
|
||||
mkdir -p "$(dirname "$SWAYSOCK")"
|
||||
@@ -236,28 +259,10 @@ in
|
||||
'';
|
||||
readiness.waitExists = [ "$SWAYSOCK" "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ];
|
||||
};
|
||||
# link the graphical-session into the default target, so sway gets auto-started
|
||||
services.graphical-session.partOf = [ "default" ];
|
||||
# launch all graphical apps by default
|
||||
services."graphical-session".partOf = [ "default" ];
|
||||
};
|
||||
|
||||
|
||||
sane.gui.gtk = lib.mkIf cfg.enabled {
|
||||
enable = lib.mkDefault true;
|
||||
# gtk-theme = lib.mkDefault "Fluent-Light-compact";
|
||||
gtk-theme = lib.mkDefault "Tokyonight-Light-B";
|
||||
# icon-theme = lib.mkDefault "HighContrast"; # 4/5 coverage on moby
|
||||
# icon-theme = lib.mkDefault "WhiteSur"; # 3.5/5 coverage on moby, but it provides a bunch for Fractal/Dino
|
||||
# icon-theme = lib.mkDefault "Humanity"; # 3.5/5 coverage on moby, but it provides the bookmark icon
|
||||
# icon-theme = lib.mkDefault "Paper"; # 3.5/5 coverage on moby, but it provides the bookmark icon
|
||||
# icon-theme = lib.mkDefault "Nordzy"; # 3/5 coverage on moby
|
||||
# icon-theme = lib.mkDefault "Fluent"; # 3/5 coverage on moby
|
||||
# icon-theme = lib.mkDefault "Colloid"; # 3/5 coverage on moby
|
||||
# icon-theme = lib.mkDefault "Qogir"; # 2.5/5 coverage on moby
|
||||
# icon-theme = lib.mkDefault "rose-pine-dawn"; # 2.5/5 coverage on moby
|
||||
# icon-theme = lib.mkDefault "Flat-Remix-Grey-Light"; # requires qtbase
|
||||
};
|
||||
|
||||
|
||||
# TODO: this can go elsewhere
|
||||
hardware.bluetooth.enable = lib.mkIf cfg.enabled true;
|
||||
services.blueman.enable = lib.mkIf cfg.enabled true;
|
||||
|
@@ -19,8 +19,9 @@ set $default_workspace_layout @workspace_layout@
|
||||
|
||||
set $out_tv "LG Electronics LG TV 0x01010101"
|
||||
set $out_projector "MS Telematica TV 0x00000001"
|
||||
set $out_desko_1 "LG Electronics LG ULTRAWIDE 0x00004E94"
|
||||
set $out_desko_2 "Samsung Electric Company S22C300 0x00007F35"
|
||||
# TODO: these 0x... numbers change on occassion: i should ignore them.
|
||||
set $out_desko_1 "LG Electronics LG ULTRAWIDE 0x000C4694"
|
||||
set $out_desko_2 "Samsung Electric Company S22C300 0x5A365335"
|
||||
set $out_lappy "BOE 0x0637 Unknown"
|
||||
# DSI-1 a.k.a. "Unknown Unknown Unknown"
|
||||
set $out_moby "DSI-1"
|
||||
@@ -37,8 +38,7 @@ client.focused_inactive #1f5e54 #5f676a #ffffff
|
||||
client.unfocused #1f5e54 #1f554c #b4b4b4
|
||||
client.urgent #ff968b #ff968b #ffffff
|
||||
|
||||
# TODO: populate background from /run/current-system/sw/etc/... instead of hard-coded nix path
|
||||
output '*' bg "@background@" fill
|
||||
output '*' bg `ls $(echo ${XDG_DATA_DIRS//:/\/backgrounds\/sane-nixos-bg.png })/backgrounds/sane-nixos-bg.png` fill
|
||||
|
||||
### pixel boundary between windows
|
||||
# hide_edge_borders --i3 means that single-window workspaces never show window bar
|
||||
@@ -79,7 +79,7 @@ bindsym --locked XF86MonBrightnessDown exec brightnessctl set 5%-
|
||||
#### special functions
|
||||
bindsym Print exec sane-open --application sane-screenshot.desktop
|
||||
bindsym $mod+Print exec sane-open --application sane-screenshot.desktop
|
||||
bindsym $mod+l exec sane-open --application swaylock.desktop
|
||||
bindsym $mod+l exec s6-rc -b start swaylock
|
||||
bindsym $mod+s exec sane-open --application rofi-snippets.desktop
|
||||
# bindsym $mod+slash exec sane-open splatmoji.desktop
|
||||
bindsym $mod+d exec sane-open --application rofi.desktop
|
||||
@@ -161,12 +161,13 @@ workspace TV output $out_tv $out_projector
|
||||
for_window [workspace="TV"] fullscreen enable
|
||||
|
||||
# mostly, messengers belong on WS 1
|
||||
assign [app_id="abaddon"] workspace number 1
|
||||
assign [app_id="geary"] workspace number 1
|
||||
assign [app_id="gnome-calls"] workspace number 1
|
||||
assign [app_id="im.dino.Dino"] workspace number 1
|
||||
assign [app_id="org.gnome.Fractal"] workspace number 1
|
||||
assign [app_id="geary"] workspace number 1
|
||||
assign [app_id="signal"] workspace number 1
|
||||
assign [app_id="so.libdb.dissent"] workspace number 1
|
||||
assign [app_id="abaddon"] workspace number 1
|
||||
|
||||
# window display settings
|
||||
# force KOReader to always display a titlebar, even when the only window being rendered.
|
||||
@@ -245,7 +246,7 @@ exec --no-startup-id mv $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY.lock $XDG_RUNTIME_DIR/
|
||||
set $$WAYLAND_DISPLAY "$(echo $DESIRED_WAYLAND_DISPLAY)"
|
||||
|
||||
|
||||
# manually export PATH here, since all my user services need that, and sane-sandboxed implementation depends on it.
|
||||
# manually export PATH here, since all my user services need that, and sanebox implementation depends on it.
|
||||
# also, manually export XDG_DATA_DIRS. glib fails in weird ways (e.g. thinks everything is application/x-octet-stream mime type) without it.
|
||||
# for more, see: <repo:nixos/nixpkgs:nixos/modules/programs/wayland/sway.nix>
|
||||
#
|
||||
|
@@ -1,23 +1,59 @@
|
||||
# icon sources:
|
||||
# - <https://www.vertex42.com/ExcelTips/unicode-symbols.html>
|
||||
# - <https://onlinetools.com/unicode/add-combining-characters>
|
||||
# - `font-manager`
|
||||
# - this one shows all the "private use" emoji, for e.g. font Noto
|
||||
# - nerd-fonts: <https://github.com/ryanoasis/nerd-fonts>
|
||||
# - grep `glyphnames.json` for the icon you want. about half of them are labeled usefully?
|
||||
|
||||
{ pkgs }:
|
||||
let
|
||||
serviceButton = svcType: name: label: {
|
||||
serviceButton = name: label: {
|
||||
inherit label;
|
||||
type = "toggle";
|
||||
command = "swaync-service-dispatcher toggle ${svcType} ${name}";
|
||||
update-command = "swaync-service-dispatcher print ${svcType} ${name}";
|
||||
command = "swaync-service-dispatcher toggle ${name}";
|
||||
update-command = "swaync-service-dispatcher print ${name}";
|
||||
active = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
gps = serviceButton "s6" "eg25-control-gps" ""; # GPS services; other icons: gps, ⌖, 🛰, 🌎,
|
||||
cell-modem = serviceButton "s6" "eg25-control-powered" ""; # icons: 5g, 📡, 📱, ᯤ, ⚡, , 🌐, 📶, 🗼, , , ,
|
||||
vpn = serviceButton "systemd" "wg-quick-vpn-servo" "vpn::hn";
|
||||
# icon sets:
|
||||
# - GPS
|
||||
# ⌖ 🛰 🌎
|
||||
# - modem
|
||||
# 📡 📱 ᯤ ⚡ 🌐 📶 🗼
|
||||
# - calls
|
||||
#
|
||||
# SIP ☏ ✆ ℡ 📞📱
|
||||
# - email
|
||||
# ✉ [E] E⃞
|
||||
#
|
||||
# 📧 📨 📩 📬 📫
|
||||
# - messaging
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
# …⃝ Θ
|
||||
# ⌨ ✍
|
||||
# 💬🗨️ 📟📤 📱📲
|
||||
# ⏏️ ⇪ ⇫ ⮸ ⭿ ⍐ ⎘
|
||||
# - XMPP
|
||||
# 🦕 🦖
|
||||
# - Signal
|
||||
# 🔵 🗣
|
||||
# - Matrix
|
||||
# 🇲 𝐌 ₘ m̄ m⃞ m̋⃞ M⃞
|
||||
# - discord
|
||||
# 🎮
|
||||
gps = serviceButton "eg25-control-gps" "";
|
||||
cell-modem = serviceButton "eg25-control-powered" "";
|
||||
|
||||
gnome-calls = serviceButton "s6" "gnome-calls" "SIP";
|
||||
geary = serviceButton "s6" "geary" ""; # email (Geary); other icons: ✉, [E], 📧,
|
||||
abaddon = serviceButton "s6" "abaddon" ""; # Discord chat client; icons: , 🎮
|
||||
dissent = serviceButton "s6" "dissent" ""; # Discord chat client; icons: , 🎮
|
||||
signal-desktop = serviceButton "s6" "signal-desktop" "💬"; # Signal messenger; other icons:
|
||||
dino = serviceButton "s6" "dino" "XMPP"; # XMPP calls (jingle)
|
||||
fractal = serviceButton "s6" "fractal" "[m]"; # Matrix messages
|
||||
gnome-calls = serviceButton "gnome-calls" "";
|
||||
geary = serviceButton "geary" "";
|
||||
abaddon = serviceButton "abaddon" " ";
|
||||
dissent = serviceButton "dissent" " ";
|
||||
signal-desktop = serviceButton "signal-desktop" "";
|
||||
dino = serviceButton "dino" "";
|
||||
fractal = serviceButton "fractal" "[m]";
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@
|
||||
# configuration:
|
||||
# - defaults: /run/current-system/etc/profiles/per-user/colin/etc/xdg/swaync/
|
||||
# - `man 5 swaync`
|
||||
# - view document tree: `GTK_DEBUG=interactive swaync` (`systemctl stop --user swaync` first)
|
||||
# - view document tree: `GTK_DEBUG=interactive swaync` (`s6 stop swaync` first)
|
||||
# - examples:
|
||||
# - thread: <https://github.com/ErikReider/SwayNotificationCenter/discussions/183>
|
||||
# - buttons-grid and menubar: <https://gist.github.com/JannisPetschenka/fb00eec3efea9c7fff8c38a01ce5d507>
|
||||
@@ -28,9 +28,10 @@ in
|
||||
pkgs = [
|
||||
"s6"
|
||||
"s6-rc"
|
||||
"systemd"
|
||||
];
|
||||
};
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.whitelistS6 = true;
|
||||
};
|
||||
|
||||
sane.programs.swaync-fbcli = {
|
||||
@@ -44,6 +45,9 @@ in
|
||||
"util-linux"
|
||||
];
|
||||
};
|
||||
sandbox.method = "bwrap";
|
||||
sandbox.whitelistDbus = [ "user" ];
|
||||
sandbox.isolatePids = false; # `swaync-fbcli stop` needs to be able to find the corresponding `swaync-fbcli start` process
|
||||
};
|
||||
|
||||
sane.programs.swaynotificationcenter = {
|
||||
@@ -62,7 +66,7 @@ in
|
||||
default = {};
|
||||
};
|
||||
|
||||
# prevent dbus from automatically activating swaync so i can manage it as a systemd service instead
|
||||
# prevent dbus from automatically activating swaync so i can manage it as a service instead
|
||||
packageUnwrapped = pkgs.rmDbusServices (pkgs.swaynotificationcenter.overrideAttrs (upstream: {
|
||||
version = "0.10.1-unstable-2024-04-16";
|
||||
# toggling the panel on 0.10.1 sometimes causes toggle-buttons to toggle.
|
||||
@@ -74,6 +78,14 @@ in
|
||||
rev = "8cb9be59708bb051616d7e14d9fa0b87b86985af";
|
||||
hash = "sha256-UAegyzqutGulp6H7KplEfwHV0MfFfOHgYNNu+AQHx3g=";
|
||||
};
|
||||
|
||||
postPatch = (upstream.postPatch or "") + ''
|
||||
# Gtk3 by default won't pack more than 7 items into one row of a FlowBox.
|
||||
# but i want tighter control over my icon placement than that:
|
||||
substituteInPlace src/controlCenter/widgets/buttonsGrid/buttonsGrid.vala --replace-fail \
|
||||
'container.set_selection_mode' \
|
||||
'container.max_children_per_line = 8; container.set_selection_mode'
|
||||
'';
|
||||
}));
|
||||
|
||||
suggestedPrograms = [
|
||||
@@ -94,23 +106,6 @@ in
|
||||
"/sys/class/backlight"
|
||||
"/sys/devices"
|
||||
];
|
||||
sandbox.extraRuntimePaths = [
|
||||
# systemd/private allows one to `systemctl --user {status,start,stop,...}`
|
||||
# notably, it does *not* allow for `systemd-run` (that's dbus: org.freedesktop.systemd1.Manager.StartTransientUnit).
|
||||
# that doesn't necessarily mean this is entirely safe against privilege escalation though.
|
||||
# TODO: audit the safety of this systemd sandboxing.
|
||||
# few alternatives:
|
||||
# - superd
|
||||
# - simply `xdg-open app://dino`, etc. `pkill` to stop, `pgrep` to query.
|
||||
# - more robust: `xdg-open sane-service://start?service=dino`
|
||||
# - still need `pgrep` to query if it's running, or have the service mark a pid file
|
||||
# - dbus activation for each app
|
||||
"systemd/private"
|
||||
];
|
||||
sandbox.extraConfig = [
|
||||
# systemctl calls seem to require same pid namespace
|
||||
"--sane-sandbox-keep-namespace" "pid"
|
||||
];
|
||||
|
||||
# glib/gio applications support many notification backends ("portal", "gtk", "freedesktop", ...).
|
||||
# swaync implements only the `org.freedesktop.Notifications` dbus interface ("freedesktop"/fdo).
|
||||
@@ -184,12 +179,12 @@ in
|
||||
lib.optionals config.sane.programs.eg25-control.enabled [
|
||||
buttons.gps
|
||||
buttons.cell-modem
|
||||
] ++ lib.optionals false [
|
||||
buttons.vpn
|
||||
] ++ lib.optionals config.sane.programs.calls.config.autostart [
|
||||
buttons.gnome-calls
|
||||
] ++ lib.optionals config.sane.programs."gnome.geary".enabled [
|
||||
buttons.geary
|
||||
] ++ lib.optionals config.sane.programs.dino.enabled [
|
||||
buttons.dino
|
||||
] ++ lib.optionals config.sane.programs.fractal.enabled [
|
||||
buttons.fractal
|
||||
# ] ++ lib.optionals config.sane.programs.abaddon.enabled [
|
||||
# # XXX: disabled in favor of dissent: abaddon has troubles auto-connecting at start
|
||||
# buttons.abaddon
|
||||
@@ -197,10 +192,8 @@ in
|
||||
buttons.dissent
|
||||
] ++ lib.optionals config.sane.programs.signal-desktop.enabled [
|
||||
buttons.signal-desktop
|
||||
] ++ lib.optionals config.sane.programs.dino.enabled [
|
||||
buttons.dino
|
||||
] ++ lib.optionals config.sane.programs.fractal.enabled [
|
||||
buttons.fractal
|
||||
] ++ lib.optionals config.sane.programs."gnome.geary".enabled [
|
||||
buttons.geary
|
||||
];
|
||||
};
|
||||
dnd = {
|
||||
|
@@ -30,7 +30,7 @@
|
||||
}
|
||||
|
||||
button {
|
||||
border-width: 2px;
|
||||
border-width: 1px;
|
||||
border-color: alpha(@bg1, 0.9);
|
||||
color: @fg0;
|
||||
background-color: @bg0;
|
||||
@@ -54,17 +54,33 @@ button:checked {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.widget-buttons-grid * {
|
||||
/* allow the buttons to be directly in contact with eachother */
|
||||
/* the full selector is .widget-buttons-grid > flowbox > flowboxchild */
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.widget-buttons-grid button.toggle {
|
||||
/* text color for inactive buttons, and "Clear All" button.*/
|
||||
/* padding defaults to 16px; tighten, so i can squish it all onto one row */
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
border-radius: 1px;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.widget-buttons-grid, .widget-backlight, .widget-volume {
|
||||
/* default padding is 8px: tighten */
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
.widget-buttons-grid {
|
||||
/* extend the buttons nearly all the way to the edge */
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
/* hierarchy is .horizontal > {label, scale > contents > trough > { slider, highlight } } */
|
||||
|
@@ -1,13 +1,12 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p s6 -p s6-rc -p systemd
|
||||
#!nix-shell -i bash -p s6 -p s6-rc
|
||||
|
||||
# for default $PATH to take precedence over nix-shell PATH if invoked interactively,
|
||||
# otherwise we invoke a s6-rc which does not know where to find files.
|
||||
export PATH="/etc/profiles/per-user/$(whoami)/bin:/run/current-system/sw/bin:$PATH"
|
||||
|
||||
action="$1"
|
||||
type="$2"
|
||||
service="$3"
|
||||
service="$2"
|
||||
|
||||
log() {
|
||||
if [ -n "$SWAYNC_DEBUG" ]; then
|
||||
@@ -16,38 +15,17 @@ log() {
|
||||
}
|
||||
|
||||
checkActive() {
|
||||
case "$type" in
|
||||
systemd)
|
||||
systemctl is-active "$service.service" > /dev/null && echo true || echo false
|
||||
;;
|
||||
s6)
|
||||
# simulate a dry-run start. if no actions would be performed, then the service is up.
|
||||
# alternative is s6-svstat, but that doesn't support oneshots
|
||||
test -z "$(s6-rc -n 0 -b start "$service")" && echo true || echo false
|
||||
;;
|
||||
esac
|
||||
# simulate a dry-run start. if no actions would be performed, then the service is up.
|
||||
# alternative is s6-svstat, but that doesn't support oneshots
|
||||
test -z "$(s6-rc -n 0 -b start "$service")" && echo true || echo false
|
||||
}
|
||||
startService() {
|
||||
log "startService: $service"
|
||||
case "$type" in
|
||||
systemd)
|
||||
/run/wrappers/bin/sudo systemctl start "$service"
|
||||
;;
|
||||
s6)
|
||||
s6-rc -b start "$service"
|
||||
;;
|
||||
esac
|
||||
s6-rc -b start "$service"
|
||||
}
|
||||
stopService() {
|
||||
log "stopService: $service"
|
||||
case "$type" in
|
||||
systemd)
|
||||
/run/wrappers/bin/sudo systemctl stop "$service"
|
||||
;;
|
||||
s6)
|
||||
s6-rc -b stop "$service"
|
||||
;;
|
||||
esac
|
||||
s6-rc -b stop "$service"
|
||||
}
|
||||
|
||||
case "$action" in
|
||||
|
@@ -9,13 +9,12 @@ let
|
||||
};
|
||||
launcher = pkgs.writeShellApplication {
|
||||
name = "unl0kr-login";
|
||||
runtimeInputs = [
|
||||
# TODO: since this invokes `login`, adding these deps to PATH is questionable
|
||||
cfg.package
|
||||
pkgs.shadow
|
||||
redirect-tty
|
||||
];
|
||||
text = ''
|
||||
extraPath=/run/current-system/sw/bin:/bin:${lib.makeBinPath [ cfg.package config.sane.programs.shadow.package redirect-tty ]}
|
||||
locate() {
|
||||
PATH=$PATH:$extraPath command -v "$1"
|
||||
}
|
||||
|
||||
# TODO: make this more robust to failure.
|
||||
# - if `unl0kr` fails, then the second `redirect-tty` sends a newline to `login`, causing it to exit and the service fails.
|
||||
# - if `redirect-tty` fails, then... the service is left hanging.
|
||||
@@ -25,8 +24,12 @@ let
|
||||
# but modified to not leak pword to CLI
|
||||
# - implement some sort of watchdog (e.g. detect spawned children?)
|
||||
# - set a timeout at the outer scope (which gets canceled upon successful login)
|
||||
bash -c 'redirect-tty "/dev/${tty}" unl0kr ; sleep 2 ; redirect-tty "/dev/${tty}" echo ""' &
|
||||
login -p ${cfg.config.user}
|
||||
PATH=$PATH:$extraPath sh -c 'redirect-tty "/dev/${tty}" unl0kr ; sleep 2 ; redirect-tty "/dev/${tty}" echo ""' &
|
||||
|
||||
# N.B.: invoke `login` by full path instead of modifying `PATH`,
|
||||
# because we don't want the user session to inherit the PATH of this script!
|
||||
_login="$(locate login)"
|
||||
"$_login" -p ${cfg.config.user}
|
||||
'';
|
||||
};
|
||||
in
|
||||
@@ -82,30 +85,22 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
fs.".profile".symlink.text = lib.mkMerge [
|
||||
(lib.mkBefore ''
|
||||
# setup primarySessionCommands here and let any other nix config populate it later
|
||||
primarySessionCommands=()
|
||||
initPrimarySession() {
|
||||
for c in "''${primarySessionCommands[@]}"; do
|
||||
eval "$c"
|
||||
done
|
||||
}
|
||||
'')
|
||||
# lib.mkAfter so that launching the DE happens *after* any other .profile setup.
|
||||
(lib.mkAfter ''
|
||||
# if already running a desktop environment, or if running from ssh, then `tty` will show /dev/pts/NN.
|
||||
if [ "$(tty)" = "/dev/${tty}" ]; then
|
||||
if (( ''${#primarySessionCommands[@]} )); then
|
||||
echo "launching primary session commands in ${builtins.toString cfg.config.delay}s: ''${primarySessionCommands[*]}"
|
||||
# if the `sleep` call here is `Ctrl+C'd`, then it'll exit false and the desktop isn't launched.
|
||||
sleep ${builtins.toString cfg.config.delay} && \
|
||||
initPrimarySession
|
||||
fi
|
||||
fi
|
||||
'')
|
||||
suggestedPrograms = [
|
||||
"shadow" #< for login
|
||||
];
|
||||
|
||||
fs.".profile".symlink.text = ''
|
||||
unl0krCheck() {
|
||||
# if already running a desktop environment, or if running from ssh, then `tty` will show /dev/pts/NN.
|
||||
# if the `sleep` call is `Ctrl+C'd`, then it'll exit false and the session commands won't be launched
|
||||
[ "$(tty)" = "/dev/${tty}" ] && (( ''${#primarySessionCommands[@]} )) \
|
||||
&& echo "launching primary session commands in ${builtins.toString cfg.config.delay}s: ''${primarySessionCommands[*]}" \
|
||||
&& sleep ${builtins.toString cfg.config.delay}
|
||||
}
|
||||
primarySessionChecks+=('unl0krCheck')
|
||||
|
||||
'';
|
||||
|
||||
# N.B.: this sandboxing applies to `unl0kr` itself -- the on-screen-keyboard;
|
||||
# NOT to the wrapper which invokes `login`.
|
||||
sandbox.method = "bwrap";
|
||||
@@ -136,10 +131,10 @@ in
|
||||
serviceConfig.ExecStart = "${pkgs.util-linux}/bin/agetty --login-program '${cfg.config.launcher}/bin/unl0kr-login' --noclear --skip-login --keep-baud ${tty} 115200,38400,9600 $TERM";
|
||||
|
||||
path = [
|
||||
# necessary for `sane-sandboxed` to be found. TODO: add this to every systemd service.
|
||||
# necessary for `sanebox` to be found. TODO: add this to every systemd service.
|
||||
"/run/current-system/sw" # `/bin` is appended
|
||||
];
|
||||
# needed to find sane-sandbox profiles (TODO: add this to every service)
|
||||
# needed to find sanebox profiles (TODO: add this to every service)
|
||||
environment.XDG_DATA_DIRS = "/run/current-system/sw/share";
|
||||
|
||||
serviceConfig.Type = "simple";
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user