Compare commits

...

184 Commits

Author SHA1 Message Date
d629db4e45 networkmanager/modemmanager: get closer to nixpkgs upstream
i've seen enough, that there's a path toward getting nixos proper to sandbox this in a way i'm happy with -- in time
2024-06-02 06:49:25 +00:00
f5e5d1bcc4 networkmanager: fix polkit integrations when running not as root
now nmcli/etc work
2024-06-02 05:10:11 +00:00
30d41f82f2 refactor: networkmanager: use substitute instead of sed when patching 2024-06-01 22:16:18 +00:00
62dbad3486 polyunfill: remove a few more default systemPackages 2024-06-01 21:06:40 +00:00
4287ecf0ed polyfill: don't ship unused mtools package 2024-06-01 20:15:04 +00:00
b13ca92b72 polyfill: remove boot.{enableContainers,bcache} 2024-06-01 20:14:49 +00:00
45e121eb1c make-sandboxed: preserve meta.mainProgram 2024-06-01 20:01:24 +00:00
53bbd611da nixpkgs-review: persist the ~/.cache/nixpkgs-review directory 2024-06-01 17:15:54 +00:00
f0128b9496 apply patch for when trust-dns is renamed to hickory-dns 2024-06-01 17:07:44 +00:00
368169d48d todo.md: start documenting sudo issues 2024-06-01 17:06:36 +00:00
cb1d5d53c6 feeds: add mintcast podcast 2024-06-01 16:28:42 +00:00
a5a635f00b sftpgo: simplify my package override now that sftpgo 2.6.0 is merged 2024-06-01 16:22:22 +00:00
6fe3d26b30 modemmanager: fix missing mmcli binary in service definition 2024-06-01 15:41:14 +00:00
8340cf059f nixpkgs-review: fix sandboxing 2024-06-01 15:26:23 +00:00
e0da3ece60 errno: simplify 2024-06-01 14:48:55 +00:00
8ea379d53b errno: ship on all platforms 2024-06-01 14:04:45 +00:00
c7dd49af91 errno: fix cross compilation by not building *all* of moreutils 2024-06-01 14:03:59 +00:00
e8b900c722 todo.md: add media looping controls 2024-06-01 13:37:51 +00:00
36f4fa3018 checkSandboxed: fix so that cross-built scripts can be checked again
how did this work earlier? does lappy have binfmt enabled??
2024-06-01 13:24:41 +00:00
d8d11de9bc sftpgo: replace deprecated "crypt" with "passlib" 2024-06-01 13:01:19 +00:00
07194d062a servo: nfs: disable 2024-06-01 12:45:10 +00:00
24c49df75f health-check: add a check that ftp://uninsane.org is operational 2024-06-01 12:42:53 +00:00
9f7e143d5e todo.md: add some kernel work to be done 2024-06-01 12:38:28 +00:00
0a382ae8a3 todo.md: remove completed "landlock sandboxer prints garbage" item 2024-06-01 12:35:46 +00:00
96f177ceb2 docs: overlays/cross: slightly tidy up the "outstanding issues" part 2024-06-01 12:24:00 +00:00
2aa3fa35b8 nixpkgs: 2024-05-31 -> 2024-06-01; nixpkgs-wayland -> 2024-05-31
```
• Updated input 'nixpkgs-next-unpatched':
    'github:nixos/nixpkgs/8a0a33b56d6279fec4827da602882561ef00f2fb' (2024-05-31)
  → 'github:nixos/nixpkgs/f7de25c01e4c073c06e0525226a0c2311d530cee' (2024-06-01)
• Updated input 'nixpkgs-unpatched':
    'github:nixos/nixpkgs/7ccd1516effbc5510391d3b498a7a3bef92a090b' (2024-05-31)
  → 'github:nixos/nixpkgs/61c1d282153dbfcb5fe413c228d172d0fe7c2a7e' (2024-06-01)
• Updated input 'nixpkgs-wayland':
    'github:nix-community/nixpkgs-wayland/1db9b79a45c8e346e03480767e6d9749fabfaf10' (2024-05-31)
  → 'github:nix-community/nixpkgs-wayland/93b225ddba91179248b378913a91defbc6aeb899' (2024-05-31)
```
2024-06-01 12:20:45 +00:00
8657cf1fcf ship ausyscall binary 2024-06-01 12:17:08 +00:00
f875db916d sandboxing: fix checkSandboxed to handle packages with multiple outputs 2024-06-01 12:12:46 +00:00
e3e86a43a9 brightnessctl: disable unused dbus access 2024-06-01 12:09:51 +00:00
05986d363d brightnessctl: fix udev rules so i can run it again 2024-06-01 12:02:24 +00:00
539d9e45a2 networkmanager/modemmanager: ship separate packages for the daemon and CLI tools
they require fundamentally different sandboxing approaches. the daemon *can't* always use bwrap if it wants to run as non-root. meanwhile the CLI tools would mostly *prefer* to run under bwrap.

in the long term i'll maybe upstream the systemd sandboxing into nixpkgs, where there looks to be desire for it
2024-05-31 23:26:16 +00:00
a380bd04c4 trivial-builders: init deepLinkIntoOwnPackage 2024-05-31 23:26:16 +00:00
f296d8df93 make-sandboxed: fix multi-output packages and sandbox *all* their outputs
this mostly applies to the wrapperType = 'inplace' users
2024-05-31 23:26:16 +00:00
326bf045b0 networkmanager/wpa_supplicant: switch user back to "networkmanager"
root gives too much power, even with bwrap/namespaces
2024-05-31 23:26:16 +00:00
a1181a10ea networkmanager: install parallel dbus .conf files to allow the services to be run as *either* networkmanager or root user (hopefully!) 2024-05-31 23:26:16 +00:00
9bb6a903bb wpa_supplicant: get it to run under bwrap 2024-05-31 23:26:16 +00:00
214f963d89 networkmanager: run all services as root instead of networkmanager user
i believe this may allow using bwrap instead of landlock
2024-05-31 23:26:16 +00:00
c7eb4b66a5 polyunfill: remove unused su and sg security wrappers 2024-05-31 14:59:23 +00:00
452543e6f3 fix rescue host build 2024-05-31 10:37:03 +00:00
d692ac9851 overlays/cross: remove broken cdrtools fix (that project is INSANE) 2024-05-31 09:40:44 +00:00
5cba283859 overlays/cross: update upstreaming status
my part of the gnome2.GConf fix was actually upstreamed a year ago; the package fails for a different reason
2024-05-31 09:04:16 +00:00
7a701f92eb nixpkgs: bump
```
• Updated input 'nixpkgs-next-unpatched':
    'github:nixos/nixpkgs/d3d81af60c22e9e93a3930a9630b210362341ab9' (2024-05-31)
  → 'github:nixos/nixpkgs/8a0a33b56d6279fec4827da602882561ef00f2fb' (2024-05-31)
• Updated input 'nixpkgs-unpatched':
    'github:nixos/nixpkgs/4e60a4d94bdc1abafeefc1928aa3cda6ce6c4210' (2024-05-31)
  → 'github:nixos/nixpkgs/7ccd1516effbc5510391d3b498a7a3bef92a090b' (2024-05-31)
```
2024-05-31 08:44:53 +00:00
3c3a32e436 nixpatches: grab libphonenumber cross patch from PR 2024-05-31 08:43:27 +00:00
07aec3ca3c apps: explain why i ship both engrampa and xarchiver archive managers 2024-05-31 08:39:23 +00:00
58d5f11c7a overlays/cross: disable patches which im not actively using 2024-05-31 08:21:23 +00:00
ed2d4ef488 overlays/cross: update upstreaming status 2024-05-31 08:02:25 +00:00
e8f8866032 overlays/cross: remove old emulated package set and buildInQemu, etc 2024-05-31 06:59:32 +00:00
a2dfd8f08e libphonenumber: use a better patch for cross (CMAKE_CROSSCOMPILING_EMULATOR) 2024-05-31 06:27:10 +00:00
c7fd3d2217 nixpkgs: 2024-05-26 -> 2024-05-31, nixpkgs-wayland -> 2024-05-31
```
• Updated input 'nixpkgs-next-unpatched':
    'github:nixos/nixpkgs/2baa940f86e1fc54757fd7d1ed551c0a38904bf2' (2024-05-26)
  → 'github:nixos/nixpkgs/d3d81af60c22e9e93a3930a9630b210362341ab9' (2024-05-31)
• Updated input 'nixpkgs-unpatched':
    'github:nixos/nixpkgs/7780e5160e011b39019797a4c4b1a4babc80d1bf' (2024-05-26)
  → 'github:nixos/nixpkgs/4e60a4d94bdc1abafeefc1928aa3cda6ce6c4210' (2024-05-31)
• Updated input 'nixpkgs-wayland':
    'github:nix-community/nixpkgs-wayland/397c85d463aef789a8dd24c4db467e9ad787907b' (2024-05-26)
  → 'github:nix-community/nixpkgs-wayland/1db9b79a45c8e346e03480767e6d9749fabfaf10' (2024-05-31)
```
2024-05-31 06:09:03 +00:00
0fcc3f8d5d ModemManager: make the sandbox more strict 2024-05-30 21:32:35 +00:00
0bb887158b implement a dropbear SSH module 2024-05-30 20:58:01 +00:00
6570c5ed84 modemmanager: sandbox with bwrap instead of landlock 2024-05-30 18:47:09 +00:00
820fdecfd5 modemmanager: minimal (working) sandbox 2024-05-30 18:27:34 +00:00
8d43565f31 sane-theme: disable sandbox 2024-05-30 16:54:10 +00:00
18364761dd wireplumber: undo the enableSystemd=false patch 2024-05-30 16:50:53 +00:00
d3937487e6 moby: cleanup bonsai <-> sway circular dependency (slightly) 2024-05-30 12:43:09 +00:00
3fdeacc336 sane-input-handler: add a --help command 2024-05-30 12:30:41 +00:00
847414ac1f health-check: add a test that git is online 2024-05-30 12:18:57 +00:00
84f2006115 servo: fix gitea 2024-05-30 12:12:06 +00:00
7f5e12da8d dbus: dont consider the service "up" until the unix pipe actually appears 2024-05-30 11:04:02 +00:00
afa8a3c52e activationScripts.notifyActive: future-proof for if ever DBUS_SESSION_BUS_ADDRESS changes 2024-05-30 11:03:35 +00:00
bfbcb4789b activationScripts.notifyActive: fix forrenamed XDG_RUNTIME_DIR 2024-05-30 10:56:17 +00:00
2531cc1cf6 bonsai: place the socket in a subdirectory to improve sandboxing 2024-05-30 09:54:28 +00:00
e55b75c333 wireplumber: build without systemd 2024-05-30 09:46:29 +00:00
adb54657d4 sway: fix bonsai to be visible in the sandbox 2024-05-30 09:46:04 +00:00
6eefb9ce20 wireplumber: build against the same pipewire i deploy 2024-05-30 09:06:41 +00:00
2233622bb7 landlock-sandboxer: remove startup messages for 6.9 2024-05-30 08:55:13 +00:00
274a7821a7 wireplumber: remove no-longer-needed /run/systemd directory
not necessary when using seatd/when a member of the 'audio' group
2024-05-30 08:54:41 +00:00
4c84d1a727 doc: modules/users: show what XDG_SESSION_{ID,CLASS,TYPE} could look like if set 2024-05-30 08:44:26 +00:00
175acf6442 pipewire: build without systemd 2024-05-30 08:44:11 +00:00
0761b6135a users/colin: add myself to "audio" group so that wireplumber can access audio devices w/o systemd/logind 2024-05-30 08:44:11 +00:00
66c899d099 callaudiod: fix to not start before dbus/pipewire are up (avoids coredump on boot) 2024-05-30 06:07:08 +00:00
4aeb3360d3 cleanup: programs: dont assume sway is always the wayland/x11 provider 2024-05-30 06:00:32 +00:00
0c456d11d8 programs: ensure things which depend on sound or wayland are ordered after it 2024-05-30 04:55:05 +00:00
3b73773169 programs: ensure things which depend on dbus are ordered after it 2024-05-30 03:48:45 +00:00
9ba8ff738b refactor: sane.programs.$foo.service: specify type concretely 2024-05-30 03:39:32 +00:00
f1d397940f seatd: patch sandboxing for desko 2024-05-29 19:42:45 +00:00
fa94fa8e6c seatd: sandbox with bwrap
it always surprises my that you can sandbox something with cap_sys_admin like this...

i think this works *only* because the user is root
2024-05-29 19:09:57 +00:00
4b9c125c8c seatd: sandbox 2024-05-29 18:58:38 +00:00
0f7d25d8a5 doc: sway: say why i wrapperType = "inplace" 2024-05-29 18:58:05 +00:00
140641729e gvfs: disable (it was broken) 2024-05-29 18:39:31 +00:00
32124d76bf cups: disable (not currently used, and not sandboxed) 2024-05-29 18:33:17 +00:00
c5c174f988 sway: patch to use a narrower sandbox 2024-05-29 18:24:59 +00:00
29bc1608aa sway: remove sandbox input which are no longer necessary 2024-05-29 17:07:18 +00:00
635ca1e5d8 seatd: pull the service definition into my own repo
this will allow me to configure the package
2024-05-29 16:34:32 +00:00
2789868703 seatd: split out of sway conf 2024-05-29 16:22:52 +00:00
c40ec1990a sshd: disable systemd integration 2024-05-29 15:57:19 +00:00
d4dfcd6510 login: remove systemd pam integration (so it doesnt try, and fail, to start the user manager) 2024-05-29 15:42:39 +00:00
d865be952a refactor: sandboxing: replace manual --sanebox-keep-namespace pid config with isolatePids = false 2024-05-29 12:56:46 +00:00
7c8a18ecbd systemd: remove no-longer-used user@1000 override 2024-05-29 12:56:19 +00:00
35ff7de06e dbus: manage it ourselves instead of having systemd do it 2024-05-29 12:55:51 +00:00
00d06db66a make-sandboxed: handle more systemd service files 2024-05-29 12:54:44 +00:00
c570b7bf5d dbus: manage it ourselves instead of having systemd do it 2024-05-29 11:30:33 +00:00
770fc2e574 systemd: fix typod IgnoreOnIsolate option 2024-05-29 11:30:33 +00:00
0ed7eb24fb programs: assorted: remove legacy programs.feedback setting 2024-05-29 11:30:33 +00:00
ad8e75b6a3 programs: assorted: remove /var/lib/alsa persistence; doesnt seem to be needed 2024-05-29 11:30:33 +00:00
e8dbe0750d networkmanager: fix sandbox to actually work with systemd-resolved 2024-05-29 10:34:24 +00:00
1378988f21 desko: *really* disable wpa_supplicant 2024-05-29 10:34:03 +00:00
b88467771e doc: trust-dns: fix wan.txt example path 2024-05-29 09:33:59 +00:00
4309d887da wpa_supplicant: remove unused services 2024-05-29 09:33:25 +00:00
1ee21c4795 NetworkManager: run as user instead of root 2024-05-29 09:16:30 +00:00
fb7bcbb5f5 NetworkManager-wait-online: fix missing sanebox path 2024-05-29 01:37:15 +00:00
0013e8305e networkmanager: cleanup 2024-05-29 01:35:38 +00:00
7dedfcebb9 networkmanager: sandbox 2024-05-29 01:33:15 +00:00
753b97ffb4 todo.md: mark hosts/modules/gui cleanup as complete 2024-05-28 16:51:29 +00:00
247fc1f887 hosts/modules/gui: fold into hosts/common/programs 2024-05-28 16:51:02 +00:00
3c2ca46ef9 hosts/modules/gui/gtk: hoist to sane.programs.sane-theme 2024-05-28 16:44:27 +00:00
95dc395925 hosts/modules/gui/theme: lift my sway background up into its own package 2024-05-28 15:48:37 +00:00
cefd6c0534 documentation improvements 2024-05-28 13:36:01 +00:00
05efec8fd7 wg-home: decrease the refresh timeout 2024-05-28 13:36:01 +00:00
e8846b2d6b wpa_supplicant: sandbox 2024-05-28 13:36:01 +00:00
be38d56717 make-sandboxed: handle more systemd/dbus service file locations 2024-05-28 13:36:01 +00:00
7d242ab02c sane-battery-estimate: sandbox 2024-05-28 09:41:04 +00:00
47611eaa26 sane-weather: sandbox 2024-05-28 09:38:04 +00:00
9719f0f785 mpv: relax sandboxing for the sake of subtitle downloading 2024-05-28 09:37:57 +00:00
8042ea76e6 assorted programs: specify sandbox.autodetectCliPaths variant more precisely than just true 2024-05-28 07:14:27 +00:00
c59236509b sane-cast: sandbox 2024-05-28 07:07:11 +00:00
50e5206b0e todo.md: document that moby touchscreen stays on even when the screen is disabled 2024-05-28 05:27:37 +00:00
4ba0343315 networkmanager: hoist some lib.mkIfs up a few levels
would you believe one of these attributes was being set without a mkIf cfg.enabled guard :)
2024-05-28 05:27:23 +00:00
cbe6072c03 polyunfill: remove policykit suid wrappers 2024-05-28 05:24:37 +00:00
bea1fd95e5 polyunfill: disable dbus-daemon-launch-helper suid wrapper 2024-05-28 05:14:06 +00:00
ae544c0649 polyunfill: disable mount/umount suid wrappers 2024-05-28 05:02:26 +00:00
b571f70988 polyunfill: remove fusermount suid wrapper 2024-05-28 04:56:14 +00:00
e6498ad152 notejot: fix sandboxing 2024-05-28 03:59:31 +00:00
976b8ae45e rofi-snippets: make the filtering case insensitive, and improve ellipsis placement come 1.7.6 2024-05-28 03:38:36 +00:00
ab7c4d7410 rofi-snippets: remove the subshell and just use a pipe
i expect that this is faster, particularly because bash should stand up each section of the pipeline in parallel, right?
2024-05-28 03:23:04 +00:00
d2c3bec98e rofi-snippets: remove an extraneous layer of sandbox 2024-05-28 03:04:57 +00:00
3c5e5632ee wtype: sandbox 2024-05-28 03:04:26 +00:00
dcedb8d3f0 sanebox: handle --flag=path style of autodetected paths 2024-05-28 03:04:02 +00:00
8586db59f1 todo.md: sync 2024-05-28 02:14:10 +00:00
1f4d500b02 snippets: update 2024-05-28 02:11:49 +00:00
56b846023b update snippets 2024-05-28 01:27:59 +00:00
747d6c876d sane-vpn: add a "dns-fix" subcommand to open a shell using an external DNS resolver
this is hopefully temporary, until i can cleanup my trust-dns recursive resolver
2024-05-28 01:23:22 +00:00
f38d2d52d2 alsa-ucm-pinephone-pmos: prefer the earpiece over the "internal speaker" 2024-05-27 14:13:56 +00:00
04bbf54385 alsa-ucm-conf: switch to postmarketos version 2024-05-27 13:41:03 +00:00
f2271180dd alsa-ucm-conf: split the patched alsa confs out into their own package 2024-05-27 12:53:33 +00:00
60b1ab1429 conky: split sane-battery-estimate out into its own program 2024-05-27 11:33:40 +00:00
db3636641d sxmo-utils: disable update script 2024-05-27 07:51:56 +00:00
54a891504d delfin: 0.4.2 -> 0.4.4 2024-05-27 07:51:56 +00:00
8ea5061bef firefox-extensions: update to latest 2024-05-27 07:51:56 +00:00
b6d19a7a09 firefox-extensions.ctrl-shift-c-should-copy: update version field to use unstable idioms 2024-05-27 07:51:56 +00:00
439be20be7 lemmy-lemonade: 2024.03.20 -> 2024.04.22 2024-05-27 07:51:56 +00:00
a024f685c3 firefox: replace i-still-dont-care-about-cookies extension with a uBlock filter list
simpler that way; fewer extensions to trust
2024-05-27 07:43:55 +00:00
9c20cef6ea firefox: ublacklist: disable (i wasnt using any rules; it wasnt blocking anything from google search results) 2024-05-27 07:22:47 +00:00
abb65e55c6 uassets: fix updateScript 2024-05-27 07:16:50 +00:00
a2d385708f flake: echo the update command before running it 2024-05-27 07:16:42 +00:00
f6f1a6e136 firefox: uBlock Origin: ship filter lists statically 2024-05-27 06:54:52 +00:00
7941a8b1ed refactor: firefox: fix uBlock json indentation 2024-05-27 04:46:38 +00:00
bbcf8841ea todo.md: sync 2024-05-27 00:49:51 +00:00
063b0be5b6 hosts/modules/gui/greetd: remove 2024-05-27 00:44:01 +00:00
7e490f5c07 remove lingering references to sxmo 2024-05-27 00:38:30 +00:00
10a985e7f9 hosts/modules/gui/sxmo: remove 2024-05-27 00:27:53 +00:00
f3c3df2ca7 sxmo_suspend.sh: lift out of hosts/modules/gui/sxmo/hooks
i want to preserve this script for the future, while deleting the rest of my (unused) SXMO config
2024-05-27 00:23:50 +00:00
f477604063 hosts/modules/gui: remove gnome 2024-05-27 00:13:19 +00:00
d46fa8a242 swaync-fbcli: sandbox (experimental) 2024-05-27 00:11:20 +00:00
62b2eb874c swaync-service-dispatcher: sandbox 2024-05-27 00:07:30 +00:00
133c1b3699 swaync: remove unused systemd integrations
it's all s6 now
2024-05-27 00:06:03 +00:00
1b4300dbeb swaync: remove unused vpn button 2024-05-27 00:00:44 +00:00
a1c1a87dd8 nixpkgs: 2024-05-24 -> 2024-05-26; nixpkgs-wayland, sops-nix
```
• Updated input 'nixpkgs-next-unpatched':
    'github:nixos/nixpkgs/cc5c0d369b5e8f49705e2a2d7464e4b162804805' (2024-05-24)
  → 'github:nixos/nixpkgs/2baa940f86e1fc54757fd7d1ed551c0a38904bf2' (2024-05-26)
• Updated input 'nixpkgs-unpatched':
    'github:nixos/nixpkgs/2baa58d3488bd9cc4d53d6812509edc34a1c7e2a' (2024-05-24)
  → 'github:nixos/nixpkgs/7780e5160e011b39019797a4c4b1a4babc80d1bf' (2024-05-26)
• Updated input 'nixpkgs-wayland':
    'github:nix-community/nixpkgs-wayland/8746004cd97164c89f0997ea06642b819e5bc3fb' (2024-05-24)
  → 'github:nix-community/nixpkgs-wayland/397c85d463aef789a8dd24c4db467e9ad787907b' (2024-05-26)
• Updated input 'nixpkgs-wayland/lib-aggregate':
    'github:nix-community/lib-aggregate/5fa64b174daa22fe0d20ebbcc0ec2c7905b503f1' (2024-05-19)
  → 'github:nix-community/lib-aggregate/dbc9130fe1455e0f6ee4d8f5f799f9be551f866b' (2024-05-26)
• Updated input 'nixpkgs-wayland/lib-aggregate/nixpkgs-lib':
    'github:nix-community/nixpkgs.lib/0df131b5ee4d928a4b664b6d0cd99cf134d6ab6b' (2024-05-19)
  → 'github:nix-community/nixpkgs.lib/d0d27192931680482081aa1c38389da2af84a651' (2024-05-26)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/b549832718b8946e875c016a4785d204fcfc2e53' (2024-05-22)
  → 'github:Mic92/sops-nix/962797a8d7f15ed7033031731d0bb77244839960' (2024-05-26)
• Updated input 'sops-nix/nixpkgs-stable':
    'github:NixOS/nixpkgs/e7cc61784ddf51c81487637b3031a6dd2d6673a2' (2024-05-18)
  → 'github:NixOS/nixpkgs/59a450646ec8ee0397f5fa54a08573e8240eb91f' (2024-05-25)
```
2024-05-26 15:07:25 +00:00
92b9a56894 cleanup: remove unused secrets/common/wg/* 2024-05-26 14:37:33 +00:00
b159240b7f servo: import ovpn privkey 2024-05-26 14:37:33 +00:00
8a9f96eefc moby: import own OVPN privkey 2024-05-26 14:31:08 +00:00
af5aa15c23 cross: get passt to cross compile 2024-05-26 14:26:56 +00:00
a03099569c sanebox: fix bwrap+pasta DNS forwarding for hosts not using trust-dns 2024-05-26 14:26:56 +00:00
b1c7061b21 vpn: fix typos from previous 2 commits 2024-05-26 14:26:47 +00:00
c528bb3ec9 desko: add to OVPN 2024-05-26 14:07:32 +00:00
002639cc76 ovpn: use a single key per-device
this should fix the traffic collisions i'm seeing with the existing setup
2024-05-26 14:04:52 +00:00
45967fde7b brave: fix sandboxing under pasta/netns 2024-05-26 13:05:44 +00:00
ed97a81ef3 sane-vpn: use bwrap instead of just pasta so that the uids get mapped and programs can be happy 2024-05-26 13:04:13 +00:00
f158842c70 sanebox: fix uid mapping when bwrap uses the pasta backend 2024-05-26 13:03:50 +00:00
90d428be7f sane-vpn: allow sane-vpn do to work with no additional arguments 2024-05-26 11:33:12 +00:00
9d7b68eeb4 sane-tag-music: rewrite empty tracknumber tag to delete the tracknumber tag 2024-05-26 10:44:25 +00:00
8951df2e2c sane-scripts: set vim tags for python scripts 2024-05-26 10:42:12 +00:00
3a045f4d88 doc: polyunfill: point to https://github.com/NixOS/nixpkgs/pull/314791 2024-05-26 08:00:18 +00:00
57d6a9a4c3 polyunfill: simplify pam hacks 2024-05-26 07:04:12 +00:00
2ee39ca0cc poly_unfill: remove /run/wrappers/bin/unix_chkpwd
non-privileged users don't need to check passwords

well, maybe they do (for desktop unlockers), but i've already solved that :)
2024-05-26 06:37:59 +00:00
9d9211c5fa polyunfill: distribute /run/wrappers/bin/unix_chkpwd without suid bit 2024-05-26 01:18:30 +00:00
9ce7dcd57a /run/wrappers: remove unused newgidmap,newuidmap,newgrp binaries 2024-05-26 01:18:30 +00:00
af72f312d3 sandbox: remove /run/wrappers: SUID wrappers dont really accomplish much inside a namespace 2024-05-26 01:18:30 +00:00
efa1ee6c69 iproute2: disable sandbox and fix ip commands 2024-05-26 01:18:30 +00:00
6a15434cc6 net/vpn: remove the bridge devices from my VPN setup 2024-05-26 01:18:30 +00:00
59e4256dd8 sane-vpn: lint 2024-05-26 01:18:30 +00:00
6365bb7594 desko: disable wpa_supplicant/wireless networking again 2024-05-26 01:18:17 +00:00
8cb73687ce unl0kr: don't add extra deps to user's PATH 2024-05-26 01:17:42 +00:00
146 changed files with 2499 additions and 3762 deletions

View File

@@ -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:

29
TODO.md
View File

@@ -1,13 +1,13 @@
## BUGS
- moby: megapixels doesn't load in sandbox
- `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
- wg-ovpnd-* interfaces don't work, because i use the same keys across all hosts...
- and if i had them differ and simultaneously online, then i'd exceed the OVPN machine count.
- i should at least have them be up'd only on-demand.
- 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
@@ -16,7 +16,6 @@
- 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
- 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"`
@@ -28,7 +27,7 @@
- `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
@@ -53,6 +52,10 @@
## 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
- validate duplicity backups!
@@ -73,14 +76,15 @@
- limit access to `~/knowledge/secrets` through an agent that requires GUI approval, so a firefox exploit can't steal all my logins
- port sanebox to a compiled language (hare?)
- 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
- xdg-desktop-portal shouldn't kill children on exit
@@ -95,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
@@ -124,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)
@@ -131,8 +136,6 @@
- try Gradience tool specifically for theming adwaita? <https://linuxphoneapps.org/apps/com.github.gradienceteam.gradience/>
#### non-moby
- sane-tag-music: integrate `beets`/<https://beets.io/>
- this should be able to auto-tag a large part of my library
- RSS: integrate a paywall bypass
- e.g. self-hosted [ladder](https://github.com/everywall/ladder) (like 12ft.io)
- neovim: set up language server (lsp; rnix-lsp; nvim-lspconfig)
@@ -154,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!

42
flake.lock generated
View File

@@ -61,11 +61,11 @@
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1716120557,
"narHash": "sha256-rvNq9YolMY1DRMgwdAti8qwNDjkhTsotSWa15/Ch7+A=",
"lastModified": 1716725378,
"narHash": "sha256-bNTVDAVBLFSSTU+q54cJnntmFKBi+F/D8sSqlZwBGiM=",
"owner": "nix-community",
"repo": "lib-aggregate",
"rev": "5fa64b174daa22fe0d20ebbcc0ec2c7905b503f1",
"rev": "dbc9130fe1455e0f6ee4d8f5f799f9be551f866b",
"type": "github"
},
"original": {
@@ -152,11 +152,11 @@
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1716079763,
"narHash": "sha256-DGRfb7fO7c3XDS3twmuaV5NAGPPdU3W7Q35fjIZc8iY=",
"lastModified": 1716684580,
"narHash": "sha256-sIbMJWJr4hl2PWd9/iWlh89QfVzBn1NJ3u5RjeZADuM=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "0df131b5ee4d928a4b664b6d0cd99cf134d6ab6b",
"rev": "d0d27192931680482081aa1c38389da2af84a651",
"type": "github"
},
"original": {
@@ -167,11 +167,11 @@
},
"nixpkgs-next-unpatched": {
"locked": {
"lastModified": 1716573668,
"narHash": "sha256-K+8vYJtu7X+qQ1Q66kYTheq0IKKVyPMOMclY9oJYnS8=",
"lastModified": 1717243271,
"narHash": "sha256-M3VxP6DtREz5Lq6MKg1gQ2EeVdIbq6AEp/N1tDSrvoc=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "cc5c0d369b5e8f49705e2a2d7464e4b162804805",
"rev": "f7de25c01e4c073c06e0525226a0c2311d530cee",
"type": "github"
},
"original": {
@@ -183,11 +183,11 @@
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1716061101,
"narHash": "sha256-H0eCta7ahEgloGIwE/ihkyGstOGu+kQwAiHvwVoXaA0=",
"lastModified": 1716655032,
"narHash": "sha256-kQ25DAiCGigsNR/Quxm3v+JGXAEXZ8I7RAF4U94bGzE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e7cc61784ddf51c81487637b3031a6dd2d6673a2",
"rev": "59a450646ec8ee0397f5fa54a08573e8240eb91f",
"type": "github"
},
"original": {
@@ -199,11 +199,11 @@
},
"nixpkgs-unpatched": {
"locked": {
"lastModified": 1716592782,
"narHash": "sha256-aGafFFAkQwkiBXo+ocx4sCco+L233JqlUZhVfXceaQY=",
"lastModified": 1717242134,
"narHash": "sha256-2X835ZESUaQ/KZEuG9HkoEB7h0USG5uvkSUmLzFkxAE=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "2baa58d3488bd9cc4d53d6812509edc34a1c7e2a",
"rev": "61c1d282153dbfcb5fe413c228d172d0fe7c2a7e",
"type": "github"
},
"original": {
@@ -223,11 +223,11 @@
]
},
"locked": {
"lastModified": 1716589021,
"narHash": "sha256-m7+ogvgw6tCk5P1H9OqS2yTFlZOus9I+Genv3PUWkno=",
"lastModified": 1717175759,
"narHash": "sha256-KiM5ue/UNQt8ktoqCV4yFqhHxM31U94Mf/piKW9dZ4c=",
"owner": "nix-community",
"repo": "nixpkgs-wayland",
"rev": "8746004cd97164c89f0997ea06642b819e5bc3fb",
"rev": "93b225ddba91179248b378913a91defbc6aeb899",
"type": "github"
},
"original": {
@@ -254,11 +254,11 @@
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1716400300,
"narHash": "sha256-0lMkIk9h3AzOHs1dCL9RXvvN4PM8VBKb+cyGsqOKa4c=",
"lastModified": 1716692524,
"narHash": "sha256-sALodaA7Zkp/JD6ehgwc0UCBrSBfB4cX66uFGTsqeFU=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "b549832718b8946e875c016a4785d204fcfc2e53",
"rev": "962797a8d7f15ed7033031731d0bb77244839960",
"type": "github"
},
"original": {

View File

@@ -317,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

View File

@@ -1,4 +1,4 @@
{ config, pkgs, ... }:
{ config, lib, pkgs, ... }:
{
imports = [
./fs.nix
@@ -11,6 +11,8 @@
# 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;
@@ -20,11 +22,12 @@
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.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;

View File

@@ -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;

View File

@@ -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/>
@@ -24,6 +21,8 @@
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;
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
@@ -32,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;

View File

@@ -267,7 +267,5 @@ in
"lima.sched_timeout_ms=2000"
];
# services.xserver.displayManager.job.preStart = ensureHWReady;
# systemd.services.greetd.preStart = ensureHWReady;
systemd.services.unl0kr.preStart = ensureHWReady;
}

View File

@@ -28,6 +28,8 @@
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.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

View File

@@ -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;

View File

@@ -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 = {

View File

@@ -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

View File

@@ -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" = {

View File

@@ -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

View File

@@ -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";
}

View File

@@ -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

View File

@@ -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;
# })
];
}

View File

@@ -1,88 +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;
# see: <nixos/modules/tasks/swraid.nix>
# it was enabled by default before 23.11
boot.swraid.enable = lib.mkDefault 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 "";
# 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"
# 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
];
boot.initrd.includeDefaultModules = lib.mkDefault 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)";
# 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;
};
}

View File

@@ -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.

View File

@@ -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"
@@ -165,7 +167,6 @@ in
];
pcConsoleUtils = declPackageSet [
"errno" # 2024/05/18: doesn't cross compile (perl File-ShareDir / Module-Build-Tiny)
# "gh" # MS GitHub cli
"nix-index"
"nixpkgs-review"
@@ -210,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
@@ -237,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`
@@ -305,7 +467,7 @@ in
];
dtc.sandbox.method = "bwrap";
dtc.sandbox.autodetectCliPaths = true; # TODO:sandbox: untested
dtc.sandbox.autodetectCliPaths = "existingFile"; # TODO:sandbox: untested
duplicity = {};
@@ -341,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
@@ -356,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
@@ -369,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
@@ -391,9 +552,7 @@ in
});
forkstat.sandbox.method = "landlock"; #< doesn't seem to support bwrap
forkstat.sandbox.extraConfig = [
"--sanebox-keep-namespace" "pid"
];
forkstat.sandbox.isolatePids = false;
forkstat.sandbox.extraPaths = [
"/proc"
];
@@ -407,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
@@ -503,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
@@ -511,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.
@@ -537,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
@@ -572,16 +730,16 @@ in
iotop.sandbox.capabilities = [ "net_admin" ];
# provides `ip`, `routel`, `bridge`, others.
# landlock works fine for most of these, but `ip netns exec` uses namespaces internally,
# and that's incompatible with landlock
iproute2.sandbox.method = "bwrap";
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"
];
# 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";
@@ -693,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
@@ -757,9 +921,7 @@ in
# procps: free, pgrep, pidof, pkill, ps, pwait, top, uptime, couple others
procps.sandbox.method = "bwrap";
procps.sandbox.extraConfig = [
"--sanebox-keep-namespace" "pid"
];
procps.sandbox.isolatePids = false;
pstree.sandbox.method = "landlock";
pstree.sandbox.extraPaths = [
@@ -797,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" ];
@@ -827,6 +995,8 @@ 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
@@ -900,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;
@@ -967,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)
@@ -985,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
);
};
}

View File

@@ -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"

View 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";
};
}

View File

@@ -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

View File

@@ -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.
"--sanebox-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" ];
};

View File

@@ -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"
];
};
};
}

View File

@@ -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;

View 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"
'';
}

View File

@@ -13,6 +13,10 @@
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" ];

View File

@@ -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";

View File

@@ -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

View 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" ];
};
};
}

View File

@@ -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";
};

View File

@@ -9,10 +9,12 @@
./animatch.nix
./assorted.nix
./audacity.nix
./ausyscall.nix
./bemenu.nix
./blast-ugjka
./bonsai.nix
./brave.nix
./brightnessctl.nix
./bubblewrap.nix
./callaudiod.nix
./calls.nix
@@ -24,6 +26,7 @@
./cozy.nix
./cups.nix
./curlftpfs.nix
./dbus.nix
./dconf.nix
./deadd-notification-center
./dialect.nix
@@ -77,6 +80,7 @@
./megapixels.nix
./mepo.nix
./mimeo
./mmcli.nix
./modemmanager.nix
./mopidy.nix
./mpv
@@ -88,6 +92,7 @@
./nheko.nix
./nicotine-plus.nix
./nix-index.nix
./nmcli.nix
./notejot.nix
./ntfy-sh.nix
./objdump.nix
@@ -107,9 +112,12 @@
./sane-open.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

View File

@@ -1,7 +1,20 @@
{ pkgs, ... }:
{
sane.programs.errno = {
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.moreutils "bin/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";
};

View File

@@ -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";

View File

@@ -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.

View File

@@ -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

View File

@@ -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"

View File

@@ -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;
};
};

View File

@@ -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,

View File

@@ -52,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"
"--sanebox-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
};

View File

@@ -0,0 +1,12 @@
{ pkgs, ... }:
{
sane.programs.mmcli = {
packageUnwrapped = pkgs.modemmanager-split.mmcli.overrideAttrs (upstream: {
meta = upstream.meta // {
mainProgram = "mmcli";
};
});
# TODO: sandbox
};
}

View File

@@ -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 ];
}

View File

@@ -203,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

View File

@@ -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

View File

@@ -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 = {

View File

@@ -7,101 +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
];
systemd.services.NetworkManager-dispatcher = lib.mkIf cfg.enabled {
wantedBy = [ "NetworkManager.service" ];
# 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";
};
sandbox.whitelistDbus = [ "system" ];
};
}
environment.etc = lib.mkIf cfg.enabled {
"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
(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" ];
[logging]
audit=false
# level: TRACE, DEBUG, INFO, WARN, ERR, OFF
level=INFO
# domain=...
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"
];
};
[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 = 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-wait-online = {
path = [ "/run/current-system/sw" ]; #< so `nm-online` can find `sanebox`
# wantedBy = [ "network-online.target" ];
serviceConfig.User = "networkmanager";
serviceConfig.Group = "networkmanager";
};
boot.kernelModules = [ "ctr" ]; #< TODO: needed (what even is this)?
# TODO: polkit?
# TODO: NetworkManager-ensure-profiles?
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";
};
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?
})
];
}

View File

@@ -0,0 +1,7 @@
{ pkgs, ... }:
{
sane.programs.nmcli = {
packageUnwrapped = pkgs.networkmanager-split.nmcli;
# TODO: sandbox
};
}

View File

@@ -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 = [

View File

@@ -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 = [
"--sanebox-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

View File

@@ -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 = {

View File

@@ -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

View File

@@ -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 = [
"--sanebox-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;

View File

@@ -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 -

View File

@@ -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

View File

@@ -97,9 +97,7 @@ in
sandbox.whitelistAudio = true;
sandbox.whitelistDbus = [ "user" ]; #< to launch applications
sandbox.extraRuntimePaths = [ "sway" ];
sandbox.extraConfig = [
"--sanebox-keep-namespace" "pid"
];
sandbox.isolatePids = false; #< for toggling the keyboard
};
# sane.programs.actkbd = {
@@ -157,6 +155,7 @@ in
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=... :

View File

@@ -61,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"
}
@@ -242,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

View File

@@ -4,13 +4,11 @@
sandbox.method = "bwrap";
sandbox.autodetectCliPaths = "existing"; # for when opening a file
sandbox.whitelistDbus = [ "user" ];
sandbox.extraConfig = [
"--sanebox-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"

View File

@@ -229,7 +229,6 @@ 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})
@@ -248,13 +247,7 @@ in
# 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";

View File

@@ -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";
}

View 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" ];
};
};
})
]

View File

@@ -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

View 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
})
];
}

View File

@@ -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";
@@ -138,6 +148,8 @@ in
"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
@@ -171,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"
@@ -204,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";
@@ -223,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")"
@@ -237,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;

View File

@@ -38,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

View File

@@ -8,11 +8,11 @@
{ 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
@@ -46,15 +46,14 @@ in
# 🇲 𝐌 ₘ m̄ m⃞ m̋⃞ M⃞ 󰫺 󰬔
# - discord
#  󰙯 󰊴 󰺷 🎮
gps = serviceButton "s6" "eg25-control-gps" "";
cell-modem = serviceButton "s6" "eg25-control-powered" "󰺐";
vpn = serviceButton "systemd" "wg-quick-vpn-servo" "vpn::hn";
gps = serviceButton "eg25-control-gps" "";
cell-modem = serviceButton "eg25-control-powered" "󰺐";
gnome-calls = serviceButton "s6" "gnome-calls" "";
geary = serviceButton "s6" "geary" "";
abaddon = serviceButton "s6" "abaddon" " ";
dissent = serviceButton "s6" "dissent" " ";
signal-desktop = serviceButton "s6" "signal-desktop" "󰭻";
dino = serviceButton "s6" "dino" "󰟿";
fractal = serviceButton "s6" "fractal" "[m]";
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]";
}

View File

@@ -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.
@@ -102,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
"--sanebox-keep-namespace" "pid"
];
# glib/gio applications support many notification backends ("portal", "gtk", "freedesktop", ...).
# swaync implements only the `org.freedesktop.Notifications` dbus interface ("freedesktop"/fdo).
@@ -192,8 +179,6 @@ 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.dino.enabled [

View File

@@ -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

View File

@@ -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";

View File

@@ -16,7 +16,7 @@ in
};
sandbox.method = "bwrap";
sandbox.net = "clearnet";
sandbox.autodetectCliPaths = true;
sandbox.autodetectCliPaths = "existing";
sandbox.whitelistAudio = true;
sandbox.whitelistDbus = [ "user" ]; # mpris
sandbox.whitelistWayland = true;

View File

@@ -91,18 +91,14 @@ in
sandbox.whitelistWayland = true;
sandbox.extraRuntimePaths = [
"sway"
# "sxmo_status" #< only necessary if relying on sxmo's statusbar periodicals service
];
sandbox.extraPaths = [
# for wifi status on sxmo/phone
"/dev/rfkill"
# for wifi status on phone
# "/dev/rfkill"
# for the battery indicator
"/sys/class/power_supply"
"/sys/devices"
];
sandbox.extraHomePaths = [
".config/sxmo/hooks"
];
fs.".config/waybar/config".symlink.target =
(pkgs.formats.json {}).generate "waybar-config.json" [

View File

@@ -61,8 +61,6 @@ window#waybar {
#cpu,
#custom-media,
#custom-swaync,
#custom-sxmo,
#custom-sxmo-sane,
#disk,
#idle_inhibitor,
#memory,

View File

@@ -1,6 +1,11 @@
{ ... }:
{ config, pkgs, ... }:
{
sane.programs.wireplumber = {
packageUnwrapped = pkgs.wireplumber.override {
# use the same pipewire as configured to run against.
pipewire = config.sane.programs.pipewire.packageUnwrapped;
};
sandbox.method = "bwrap";
# sandbox.whitelistDbus = [
# "system" #< so it can request better scheduling from rtkit
@@ -14,16 +19,13 @@
"/dev/video0"
"/dev/video1"
"/dev/video2"
"/run/systemd"
# "/run/systemd"
"/run/udev"
"/sys/class/sound"
"/sys/class/video4linux"
"/sys/devices"
];
# sandbox.extraConfig = [
# # needed if i want rtkit to grant this higher scheduling priority
# "--sanebox-keep-namespace" "pid"
# ];
sandbox.isolatePids = false; #< needed if i want rtkit to grant this higher scheduling priority
suggestedPrograms = [ "alsa-ucm-conf" ];

View File

@@ -1,10 +1,77 @@
{ config, lib, ... }:
{ config, lib, pkgs, ... }:
let
cfg = config.sane.programs.wpa_supplicant;
in
{
sane.programs.wpa_supplicant = {};
services.udev.packages = lib.mkIf cfg.enabled [ cfg.package ];
# need to be on systemd.packages so we get its service file
systemd.packages = lib.mkIf cfg.enabled [ cfg.package ];
config = lib.mkMerge [
{
sane.programs.wpa_supplicant = {
packageUnwrapped = pkgs.wpa_supplicant.overrideAttrs (upstream: {
# postPatch = (upstream.postPatch or "") + ''
# substituteInPlace wpa_supplicant/dbus/dbus-wpa_supplicant.conf --replace-fail \
# 'user="root"' 'user="networkmanager"'
# '';
postInstall = (upstream.postInstall or "") + ''
substitute $out/share/dbus-1/system.d/dbus-wpa_supplicant.conf \
$out/share/dbus-1/system.d/networkmanager-wpa_supplicant.conf \
--replace-fail 'user="root"' 'group="networkmanager"'
'';
postFixup = (upstream.postFixup or "") + ''
# nixpkgs wpa_supplicant generates a dbus file which has a path like
# /nix/store/abc-wpa_supplicant/nix/store/abc-wpa_supplicant/sbin/...
# upstreaming status: <https://github.com/NixOS/nixpkgs/pull/315346>
substituteInPlace $out/share/dbus-1/system-services/* --replace-fail \
"$out$out" "$out"
# remove unused services to avoid unexpected interactions
rm $out/etc/systemd/system/{wpa_supplicant-nl80211@,wpa_supplicant-wired@,wpa_supplicant@}.service
'';
});
# 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.
# sandbox.method = "bwrap";
sandbox.method = "landlock";
sandbox.capabilities = [
# see also: <https://github.com/NixOS/nixpkgs/pull/305722>
"net_admin" "net_raw"
];
# sandbox.extraConfig = [ "--sanebox-keep-namespace" "all" ];
sandbox.net = "all";
sandbox.extraPaths = [
"/dev/net"
"/dev/rfkill"
"/proc/sys/net"
"/sys/class/net"
"/sys/devices"
];
sandbox.whitelistDbus = [ "system" ];
};
}
(lib.mkIf cfg.enabled {
services.udev.packages = [ cfg.package ];
systemd.packages = [ cfg.package ]; #< needs to be on systemd.packages so we get its service file
systemd.services.wpa_supplicant = {
path = [ "/run/current-system/sw" ]; #< so it can find `sanebox`
serviceConfig.User = "networkmanager";
serviceConfig.Group = "networkmanager";
serviceConfig.AmbientCapabilities = [
"CAP_NET_ADMIN"
"CAP_NET_RAW"
];
};
# systemd.services.wpa_supplicant = {
# aliases = [ "dbus-fi.w1.wpa_supplicant1.service" ];
# before = [ "network.target" ];
# wantedBy = [ "network.target" ];
# serviceConfig = {
# Type = "dbus";
# BusName = "fi.w1.wpa_supplicant1";
# ExecStart = "${cfg.package}/bin/wpa_supplicant -u";
# Restart = "always";
# };
# };
})
];
}

View File

@@ -89,7 +89,7 @@ in
};
# also available: ${cfg.package}/libexec/xdg-document-portal
# - <https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Documents.html>
# - shares files from its namespace with programs inside a namespace, via a fuse mount at /run/user/$uid/doc
# - shares files from its namespace with programs inside a namespace, via a fuse mount at $XDG_RUNTIME_DIR/doc
};
# after #603 is resolved, i can probably stop linking `{gtk,wlr}.portal` into ~

View File

@@ -25,10 +25,21 @@ in
enable = true;
settings.PermitRootLogin = "no";
settings.PasswordAuthentication = false;
settings.UsePAM = lib.mkDefault false; #< notably, disables systemd session tracking; incidentally disables pam_mount, etc.
};
sane.ports.ports."22" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
description = lib.mkDefault "colin-ssh";
};
# sane.services.dropbear = {
# enable = true;
# port = 1022;
# };
# sane.ports.ports."1022" = {
# protocol = [ "tcp" ];
# visibleTo.lan = true;
# description = lib.mkDefault "colin-dropbear-ssh";
# };
}

View File

@@ -1,4 +1,4 @@
{ pkgs, ... }:
{ ... }:
let
# N.B.: systemd doesn't like to honor its timeout settings.
# a timeout of 20s is actually closer to 70s,
@@ -12,11 +12,6 @@ in
DefaultTimeoutStopSec=${builtins.toString haltTimeout}
'';
systemd.user.extraConfig = ''
# DefaultTimeoutStopSec defaults to 90s, and frequently blocks overall system shutdown.
DefaultTimeoutStopSec=${builtins.toString haltTimeout}
'';
services.journald.extraConfig = ''
# docs: `man journald.conf`
# merged journald config is deployed to /etc/systemd/journald.conf
@@ -25,41 +20,6 @@ in
Compress=no
'';
# decreasing the timeout for the manager itself ("Stop job is running for User Manager for UID 1000").
# TimeoutStopSec gets stripped from .override file for `user@`, so can't do it that way:
# systemd.services."user@".serviceConfig.TimeoutStopSec = "20s";
# adding just TimeoutStopSec to `user@1000` causes it to lose all the other fields, including `ExecStart`:
# systemd.services."user@1000".serviceConfig.TimeoutStopSec = "20s";
# so, just recreate the whole damn service as it appears with `systemd cat 'user@1000'`
# and modify the parts i care about.
systemd.services."user@1000" = {
description = "User Manager for UID %i";
documentation = [ "man:user@service(5)" ];
after = [
"user-runtime-dir@%i.service"
"dbus.service"
"systemd-oomd.service"
];
requires = [ "user-runtime-dir@%i.service" ];
unitConfig.ignoreOnIsolate = true;
serviceConfig = {
User = "%i";
PAMName = "systemd-user";
Type = "notify-reload";
ExecStart = "${pkgs.systemd}/lib/systemd/systemd --user";
Slice = "user-%i.slice";
KillMode = "mixed";
Delegate = [ "pids" "memory" "cpu" ];
DelegateSubgroup = "init.scope";
TasksMax = "infinity";
TimeoutStopSec = "${builtins.toString haltTimeout}s"; #< default: 120s
KeyringMode = "inherit";
OOMScoreAdjust = 100;
MemoryPressureWatch = "skip";
};
};
# allow ordinary users to `reboot` or `shutdown`.
# source: <https://nixos.wiki/wiki/Polkit>
security.polkit.extraConfig = ''

View File

@@ -13,14 +13,16 @@
];
group = "users";
extraGroups = [
"audio" # for wireplumber, so i can access devices without logind
"clightning" # servo, for clightning-cli
"dialout" # required for modem access (moby)
"export" # to read filesystem exports (servo)
"feedbackd" # moby, so `fbcli` can control vibrator and LEDs
"input" # for /dev/input/<xyz>: sxmo
"input" # for /dev/input/<xyz>... TODO:is this still necessary?
"media" # servo
"networkmanager"
"nixbuild"
"seat" # for sway, if using seatd
"systemd-journal" # allows to view other user's journals (esp system users)
"transmission" # servo
"video" # mobile; for LEDs & maybe for camera?

View File

@@ -51,12 +51,6 @@ in
sane.fs."/etc/shadow".symlink.target = "/var/lib/etc_secrets/shadow";
# pam.d ordering (auth section only):
# /etc/pam.d/greetd:
# auth optional pam_unix.so likeauth nullok # unix-early (order 11600)
# auth optional /nix/store/051v0pwqfy1z7ld6087y99fdrv12113n-pam_mount-2.20/lib/security/pam_mount.so disable_interactive # mount (order 12000)
# auth optional /nix/store/82zqzh7i88pxybcf48zapnz4v0jf19nm-gnome-keyring-42.1/lib/security/pam_gnome_keyring.so # gnome_keyring (order 12200)
# auth sufficient pam_unix.so likeauth nullok try_first_pass # unix (order 12800)
# auth required pam_deny.so # deny (order 13600)
# /etc/pam.d/login:
# auth optional pam_unix.so likeauth nullok # unix-early (order 11600)
# auth optional /nix/store/051v0pwqfy1z7ld6087y99fdrv12113n-pam_mount-2.20/lib/security/pam_mount.so disable_interactive # mount (order 12000)
@@ -104,15 +98,6 @@ in
# - pam_cap bug, and fix: <https://bugzilla.kernel.org/show_bug.cgi?id=212945#c5>
# - may need to use keepcaps + defer: <https://bugzilla.kernel.org/show_bug.cgi?id=214377#c3>
# security.pam.services.greetd.rules = {
# # 2024/01/28: greetd seems to get its caps from systemd (pid1), no matter what i do.
# auth.pam_cap = {
# order = 12700;
# control = "optional";
# modulePath = "${libcapForPam.pam}/lib/security/pam_cap.so";
# args = [ "keepcaps" "defer" "debug" ]; #< doesn't take effect
# };
# };
security.pam.services.login.rules = {
# keepcaps + defer WORKS
auth.pam_cap = {

View File

@@ -3,7 +3,6 @@
{
imports = [
./derived-secrets
./gui
./hosts.nix
./nixcache.nix
./roles

View File

@@ -1,222 +0,0 @@
{ config, lib, pkgs, ... }:
let
declPackageSet = pkgs: {
packageUnwrapped = null;
suggestedPrograms = pkgs;
};
in
{
imports = [
./gnome.nix
./greetd.nix
./gtk.nix
./sxmo
./theme
];
sane.programs.gameApps = declPackageSet [
"animatch"
"gnome-2048"
"gnome.hitori" # like sudoku
];
sane.programs.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"
];
sane.programs.guiApps = declPackageSet [
# package sets
"gameApps"
"guiBaseApps"
];
sane.programs.guiBaseApps = declPackageSet [
# "abaddon" # discord client
"alacritty" # terminal emulator
"calls" # gnome calls (dialer/handler)
"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
];
sane.programs.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"
];
sane.programs.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.
"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"
]
);
# TODO: find a better place for these
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 = ''
# notify all logged-in users that the system has been activated/upgraded.
if [ -d /run/user ]; then
for uid in $(ls /run/user); do
PATH="$PATH:${pkgs.sudo}/bin" \
sudo -u "#$uid" env DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
PATH="$PATH:${pkgs.libnotify}/bin" \
notify-send 'nixos activated' "version: $(cat "$systemConfig/nixos-version")"
done
fi
'';
};
}

View File

@@ -1,87 +0,0 @@
{ lib, config, pkgs, ... }:
let
cfg = config.sane.gui.gnome;
in
{
options = with lib; {
sane.gui.gnome.enable = mkOption {
default = false;
type = types.bool;
};
};
config = lib.mkIf cfg.enable {
sane.programs.guiApps.enableFor.user.colin = true;
# start gnome/gdm on boot
services.xserver.enable = true;
services.xserver.desktopManager.gnome.enable = true;
services.xserver.displayManager.gdm.enable = true;
# gnome does networking stuff with networkmanager
networking.networkmanager.enable = true;
networking.wireless.enable = lib.mkForce false;
# services.xserver.desktopManager.gnome.enable enables some default apps we don't really care about.
# see <nixos/modules/services/x11/desktop-managers/gnome.nix>
environment.gnome.excludePackages = with pkgs; [
# gnome.gnome-menus # unused outside gnome classic, but probably harmless
gnome.gnome-control-center #< if you want a faster deploy
gnome-tour
];
# disable these for a faster build cycle
services.dleyna-renderer.enable = false;
services.dleyna-server.enable = false;
services.gnome.gnome-browser-connector.enable = false;
services.gnome.gnome-initial-setup.enable = false;
services.gnome.gnome-remote-desktop.enable = false;
services.gnome.gnome-user-share.enable = false;
services.gnome.rygel.enable = false;
services.gnome.evolution-data-server.enable = lib.mkForce false;
services.gnome.gnome-online-accounts.enable = lib.mkForce false;
services.gnome.gnome-online-miners.enable = lib.mkForce false;
};
# user extras:
# obtain these by running `dconf dump /` after manually customizing gnome
# TODO: fix "is not of type `GVariant value'"
# dconf.settings = lib.mkIf (gui == "gnome") {
# gnome = {
# # control alt-tab behavior
# "org/gnome/desktop/wm/keybindings" = {
# switch-applications = [ "<Super>Tab" ];
# switch-applications-backward=[];
# switch-windows=["<Alt>Tab"];
# switch-windows-backward=["<Super><Alt>Tab"];
# };
# # idle power savings
# "org/gnome/settings-deamon/plugins/power" = {
# idle-brigthness = 50;
# sleep-inactive-ac-type = "nothing";
# sleep-inactive-battery-timeout = 5400; # seconds
# };
# "org/gnome/shell" = {
# favorite-apps = [
# "org.gnome.Nautilus.desktop"
# "firefox.desktop"
# # "org.gnome.Terminal.desktop"
# ];
# };
# "org/gnome/desktop/session" = {
# # how long until considering a session idle (triggers e.g. screen blanking)
# idle-delay = 900;
# };
# "org/gnome/desktop/interface" = {
# text-scaling-factor = 1.25;
# };
# "org/gnome/desktop/media-handling" = {
# # don't auto-mount inserted media
# automount = false;
# automount-open = false;
# };
# };
# };
}

View File

@@ -1,128 +0,0 @@
# greetd source/docs:
# - <https://git.sr.ht/~kennylevinsen/greetd>
{ config, lib, pkgs, ... }:
let
systemd-cat = "${pkgs.systemd}/bin/systemd-cat";
runWithLogger = identifier: cmd: pkgs.writeShellScriptBin identifier ''
echo "launching ${identifier}..." | ${systemd-cat} --identifier=${identifier}
${cmd} 2>&1 | ${systemd-cat} --identifier=${identifier}
'';
cfg = config.sane.gui.greetd;
in
{
options = with lib; {
sane.gui.greetd.enable = mkOption {
default = false;
type = types.bool;
};
sane.gui.greetd.session.command = mkOption {
type = types.str;
description = ''
name to use for the default session in syslog.
'';
};
sane.gui.greetd.session.name = mkOption {
default = "greetd-session";
type = types.str;
description = "name of session to use in logger";
};
sane.gui.greetd.session.user = mkOption {
default = null;
type = types.nullOr types.str;
};
# helpers for common things to layer on top of greetd
sane.gui.greetd.sway.enable = mkOption {
default = false;
type = types.bool;
description = ''
use sway as a wayland compositor in which to host a graphical greeter like gtkgreet, phog, etc.
'';
};
sane.gui.greetd.sway.greeterCmd = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
command for sway to `exec` that provides the actual graphical greeter.
'';
};
sane.gui.greetd.sway.gtkgreet.enable = mkOption {
default = false;
type = types.bool;
description = ''
have sway launch gtkgreet instead of directly presenting a desktop.
'';
};
sane.gui.greetd.sway.gtkgreet.session.command = mkOption {
type = types.str;
description = ''
command for gtkgreet to execute on successful authentication.
'';
};
sane.gui.greetd.sway.gtkgreet.session.name = mkOption {
type = types.str;
description = ''
name to use for the default session in syslog and in the gtkgreet menu.
note that this `sessionName` will become a binary on the user's PATH.
'';
};
sane.gui.greetd.sway.gtkgreet.session.user = mkOption {
type = types.str;
default = "colin";
description = ''
name of user which one expects to login as.
'';
};
};
config = lib.mkIf cfg.enable (lib.mkMerge [
(lib.mkIf cfg.sway.enable {
sane.gui.greetd.session = if cfg.sway.greeterCmd != null then {
name = "sway-as-greeter";
command = let
swayAsGreeterConfig = pkgs.writeText "sway-as-greeter-config" ''
exec ${cfg.sway.greeterCmd}
'';
in "${pkgs.sway}/bin/sway --debug --config ${swayAsGreeterConfig}";
} else {
name = "sway";
user = lib.mkDefault "colin";
command = "${pkgs.sway}/bin/sway --debug";
};
})
(lib.mkIf cfg.sway.gtkgreet.enable (
let
inherit (cfg.sway.gtkgreet) session;
sessionProvider = runWithLogger session.name session.command;
in {
# gtkgreet shows the --command argument in the UI
# - so we want it to look nice (not a /nix/store/... path)
# - to do that we put it in the user's PATH.
sane.gui.greetd.sway.greeterCmd = "${pkgs.greetd.gtkgreet}/bin/gtkgreet --layer-shell --command ${session.name}";
users.users.${session.user}.packages = [ sessionProvider ];
}
))
{
services.greetd = {
enable = true;
# i could have gtkgreet launch the session directly: but stdout/stderr gets dropped
# settings.default_session.command = cfg.session.command;
# wrapper to launch with stdout/stderr redirected to system journal.
settings.default_session.command = let
launchWithLogger = runWithLogger cfg.session.name cfg.session.command;
in "${launchWithLogger}/bin/${cfg.session.name}";
};
# persisting fontconfig & mesa_shader_cache improves start time by ~5x
users.users.greeter.home = "/var/lib/greeter";
sane.persist.sys.byStore.plaintext = [
{ user = "greeter"; group = "greeter"; path = "/var/lib/greeter/.cache/fontconfig"; }
{ user = "greeter"; group = "greeter"; path = "/var/lib/greeter/.cache/mesa_shader_cache"; }
];
}
]);
}

View File

@@ -1,626 +0,0 @@
# this work derives from noneucat's sxmo service/packages, found via NUR
# - <repo:nix-community/nur-combined:repos/noneucat/modules/pinephone/sxmo.nix>
# other nix works:
# - <https://github.com/wentam/sxmo-nix>
# - implements sxmo atop tinydm (also packaged by wentam)
# - wentam cleans up sxmo-utils to be sealed. also patches to use systemd poweroff, etc
# - packages a handful of anjan and proycon utilities
# - packages <https://gitlab.com/kop316/mmsd/>
# - packages <https://gitlab.com/kop316/vvmd/>
# - <https://github.com/chuangzhu/nixpkgs-sxmo>
# - implements sxmo as a direct systemd service -- apparently no DM
# - packages sxmo-utils
# - injects PATH into each script
# other OS works:
# - <https://git.sr.ht/~aren/sxmo-utils> (arch)
# - perhaps sxmo-utils is best packaged via the `resholve` shell solver?
#
# sxmo upstream links:
# - docs (rendered): <https://man.sr.ht/~anjan/sxmo-docs-next/>
# - issue tracker: <https://todo.sr.ht/~mil/sxmo-tickets>
# - mail list (patches): <https://lists.sr.ht/~mil/sxmo-devel>
#
# sxmo technical overview:
# - inputs
# - bonsaid: handles vol/power buttons
# - it receives those buttons from dwm (if x11) harcoded in config.h or sway (if wayland)
# - lisgd: handles gestures
# - startup
# - daemon based (lisgsd, idle_locker, statusbar_periodics)
# - auto-started at login
# - managable by `sxmo_jobs.sh`
# - list available daemons: `sxmo_jobs.sh list`
# - query if a daemon is active: `sxmo_jobs.sh running <my-daemon>`
# - start daemon: `sxmo_jobs.sh start <my-daemon>`
# - managable by `superctl`
# - `superctl status`
# - user hooks:
# - live in ~/.config/sxmo/hooks/
# - logs:
# - live in ~/.local/state/sxmo.log
# - ~/.local/state/superd.log
# - ~/.local/state/superd/logs/<daemon>.log
# - `journalctl --user --boot` (lightdm redirects the sxmo session stdout => systemd)
#
# - default components:
# - DE: sway (if wayland), dwm (if X)
# - menus: bemenu (if wayland), dmenu (if X)
# - gestures: lisgd
# - on-screen keyboard: wvkbd (if wayland), svkbd (if X)
{ config, lib, pkgs, ... }:
let
cfg = config.sane.gui.sxmo;
package = cfg.package;
knownKeyboards = {
# map keyboard package name -> name of binary to invoke
wvkbd = "wvkbd-mobintl";
svkbd = "svkbd-mobile-intl";
};
knownTerminals = {
vte = "vte-2.91";
};
systemd-cat = "${pkgs.systemd}/bin/systemd-cat";
runWithLogger = identifier: cmd: pkgs.writeShellScript identifier ''
echo "launching ${identifier}..." | ${systemd-cat} --identifier=${identifier}
${cmd} 2>&1 | ${systemd-cat} --identifier=${identifier}
'';
hookPkgs = {
block_suspend = pkgs.static-nix-shell.mkBash {
pname = "sxmo_hook_block_suspend.sh";
pkgs = [ "procps" ];
srcRoot = ./hooks;
};
inputhandler = pkgs.static-nix-shell.mkBash {
pname = "sxmo_hook_inputhandler.sh";
pkgs = [ "coreutils" "playerctl" "pulseaudio" ];
srcRoot = ./hooks;
};
postwake = pkgs.static-nix-shell.mkBash {
pname = "sxmo_hook_postwake.sh";
pkgs = [ "coreutils" ];
srcRoot = ./hooks;
};
rotate = pkgs.static-nix-shell.mkBash {
pname = "sxmo_hook_rotate.sh";
pkgs = {
sway = config.sane.programs.sway.package.sway-unwrapped;
};
srcRoot = ./hooks;
};
start = pkgs.static-nix-shell.mkBash {
pname = "sxmo_hook_start.sh";
pkgs = [ "systemd" "xdg-user-dirs" ];
srcRoot = ./hooks;
};
suspend = pkgs.static-nix-shell.mkPython3Bin {
pname = "sxmo_suspend.sh";
pkgs = [ "rtl8723cs-wowlan" "util-linux" ];
srcRoot = ./hooks;
extraMakeWrapperArgs = [ "--add-flags" "--verbose" ];
};
};
in
{
options = with lib; {
sane.gui.sxmo.enable = mkOption {
default = false;
type = types.bool;
};
sane.gui.sxmo.package = mkOption {
type = types.package;
default = pkgs.sxmo-utils.override {
preferSystemd = true;
sway = config.sane.programs.sway.package.sway-unwrapped;
};
description = ''
sxmo base scripts and hooks collection.
consider overriding the outputs under /share/sxmo/default_hooks
to insert your own user scripts.
'';
};
sane.gui.sxmo.hooks = mkOption {
type = types.attrsOf types.path;
default = {
# default upstream hooks
# additional hooks are in subdirectories like three_button_touchscreen/
# - sxmo_hook_inputhandler.sh
# - sxmo_hook_lock.sh
# - sxmo_hook_postwake.sh
# - sxmo_hook_screenoff.sh
# - sxmo_hook_unlock.sh
# by including hooks here, updating the sxmo package also updates the hooks
# without requiring any reboot
"sxmo_hook_apps.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_apps.sh";
# "sxmo_hook_block_suspend.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_block_suspend.sh";
"sxmo_hook_call_audio.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_call_audio.sh";
"sxmo_hook_contextmenu_fallback.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_contextmenu_fallback.sh";
"sxmo_hook_contextmenu.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_contextmenu.sh";
"sxmo_hook_desktop_widget.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_desktop_widget.sh";
"sxmo_hook_discard.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_discard.sh";
"sxmo_hook_hangup.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_hangup.sh";
"sxmo_hook_icons.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_icons.sh";
"sxmo_hook_lisgdstart.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_lisgdstart.sh";
"sxmo_hook_logout.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_logout.sh";
"sxmo_hook_missed_call.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_missed_call.sh";
"sxmo_hook_mnc.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_mnc.sh";
"sxmo_hook_modem.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_modem.sh";
"sxmo_hook_mute_ring.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_mute_ring.sh";
"sxmo_hook_network_down.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_network_down.sh";
"sxmo_hook_network_pre_down.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_network_pre_down.sh";
"sxmo_hook_network_pre_up.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_network_pre_up.sh";
"sxmo_hook_network_up.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_network_up.sh";
"sxmo_hook_notification.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_notification.sh";
"sxmo_hook_notifications.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_notifications.sh";
"sxmo_hook_pickup.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_pickup.sh";
"sxmo_hook_restart_modem_daemons.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_restart_modem_daemons.sh";
"sxmo_hook_ring.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_ring.sh";
"sxmo_hook_rotate.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_rotate.sh";
"sxmo_hook_screenoff.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_screenoff.sh";
"sxmo_hook_scripts.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_scripts.sh";
"sxmo_hook_sendsms.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_sendsms.sh";
"sxmo_hook_smslog.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_smslog.sh";
"sxmo_hook_sms.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_sms.sh";
"sxmo_hook_start.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_start.sh";
"sxmo_hook_statusbar.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_statusbar.sh";
"sxmo_hook_stop.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_stop.sh";
"sxmo_hook_tailtextlog.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_tailtextlog.sh";
} // {
# default hooks for this nix module, not upstreamable
"sxmo_hook_block_suspend.sh" = "${hookPkgs.block_suspend}/bin/sxmo_hook_block_suspend.sh";
"sxmo_hook_inputhandler.sh" = "${hookPkgs.inputhandler}/bin/sxmo_hook_inputhandler.sh";
"sxmo_hook_postwake.sh" = "${hookPkgs.postwake}/bin/sxmo_hook_postwake.sh";
"sxmo_hook_rotate.sh" = "${hookPkgs.rotate}/bin/sxmo_hook_rotate.sh";
"sxmo_hook_start.sh" = "${hookPkgs.start}/bin/sxmo_hook_start.sh";
"sxmo_suspend.sh" = "${hookPkgs.suspend}/bin/sxmo_suspend.sh";
};
description = ''
extra hooks to add with higher priority than the builtins
'';
};
sane.gui.sxmo.terminal = mkOption {
# type = types.nullOr (types.enum [ "foot" "st" "vte" ]);
type = types.nullOr types.str;
default = "foot";
description = ''
name of terminal to use for sxmo_terminal.sh.
foot, st, and vte have special integrations in sxmo, but any will work.
'';
};
sane.gui.sxmo.keyboard = mkOption {
# type = types.nullOr (types.enum ["wvkbd"])
type = types.nullOr types.str;
default = "wvkbd";
description = ''
name of on-screen-keyboard to use for sxmo_keyboard.sh.
this sets the KEYBOARD environment variable.
see also: KEYBOARD_ARGS.
'';
};
sane.gui.sxmo.settings = mkOption {
description = ''
environment variables used to configure sxmo.
e.g. SXMO_UNLOCK_IDLE_TIME or SXMO_VOLUME_BUTTON.
'';
type = types.submodule {
freeformType = types.attrsOf types.str;
options =
let
mkSettingsOpt = default: description: mkOption {
inherit default description;
type = types.nullOr types.str;
};
in {
SXMO_BAR_SHOW_BAT_PER = mkSettingsOpt "1" "show battery percentage in statusbar";
SXMO_DISABLE_CONFIGVERSION_CHECK = mkSettingsOpt "1" "allow omitting the configversion line from user-provided sxmo dotfiles";
SXMO_UNLOCK_IDLE_TIME = mkSettingsOpt "300" "how many seconds of inactivity before locking the screen"; # lock -> screenoff happens 8s later, not configurable
# SXMO_WM = mkSettingsOpt "sway" "sway or dwm. ordinarily initialized by sxmo_{x,w}init.sh";
SXMO_NO_AUDIO = mkSettingsOpt "" "don't start pipewire/pulseaudio in sxmo_hook_start.sh, don't show audio in statusbar, disable audio menu";
SXMO_STATES = mkSettingsOpt "unlock screenoff" "list of states the device should support (unlock, lock, screenoff)";
SXMO_SWAY_SCALE = mkSettingsOpt "1" "sway output scale";
SXMO_WOB_DISABLE = mkSettingsOpt "" "disable the on-screen volume display";
};
};
default = {};
};
sane.gui.sxmo.noidle = mkOption {
type = types.bool;
default = false;
description = "inhibit lock-on-idle and screenoff-on-idle";
};
sane.gui.sxmo.nogesture = mkOption {
type = types.bool;
default = false;
description = "don't start lisgd gesture daemon by default";
};
};
config = lib.mkMerge [
{
sane.programs.sxmoApps = {
packageUnwrapped = null;
suggestedPrograms = [
"guiApps"
"bemenu" # specifically to import its theming
"bonsai"
"sfeed" # want this here so that the user's ~/.sfeed/sfeedrc gets created
# "superd" # make superctl (used by sxmo) be on PATH
# "sway-autoscaler"
"waybar-sxmo-status"
];
persist.byStore.cryptClearOnBoot = [
# builds to be 10's of MB per day
# ".local/state/superd/logs"
".local/share/sxmo/modem" # SMS
".local/share/sxmo/notifications" # so i can see new SMS messages. not sure actually if this needs persisting or if it'll re-hydrate from modem.
];
};
sane.programs.waybar-sxmo-status = {
packageUnwrapped = pkgs.static-nix-shell.mkBash {
pname = "waybar-sxmo-status";
srcRoot = ./.;
pkgs = {
sxmo-utils = package;
"sxmo-utils.runtimeDeps" = package.runtimeDeps;
};
};
};
}
{
# TODO: lift to option declaration
# N.B.: TERMCMD was renamed SXMO_TERMINAL on 2023/08/29
sane.gui.sxmo.settings.SXMO_TERMINAL = lib.mkIf (cfg.terminal != null)
(lib.mkDefault (knownTerminals."${cfg.terminal}" or cfg.terminal));
sane.gui.sxmo.settings.KEYBOARD = lib.mkIf (cfg.keyboard != null)
(lib.mkDefault (knownKeyboards."${cfg.keyboard}" or cfg.keyboard));
}
(lib.mkIf cfg.enable (lib.mkMerge [
{
sane.programs.sway.enableFor.user.colin = true;
sane.programs.waybar.config = {
top = import ./waybar-top.nix;
fontSize = 14;
};
sane.programs.sway.config = {
# N.B. missing from upstream sxmo config here is:
# - `bindsym $mod+g exec sxmo_hook_locker.sh`
# - `bindsym $mod+t exec sxmo_appmenu.sh power`
# - `bindsym $mod+i exec sxmo_wmmenu.sh windowswitcher`
# - `bindsym $mod+p exec sxmo_appmenu.sh`
# - `bindsym $mod+Shift+p exec sxmo_appmenu.sh sys`
# - `input * xkb_options compose:ralt`
# these could be added, but i don't see much benefit.
font = "pango:monospace 10";
mod = "Mod1"; # prefer Alt
workspace_layout = "tabbed";
# screenshot_cmd = "sxmo_screenshot.sh";
extra_lines =
let
sxmo_init = pkgs.writeShellScript "sxmo_init.sh" ''
# perform the same behavior as sxmo_{x,w}init.sh -- but without actually launching wayland/X11
# this amounts to:
# - setting env vars (e.g. getting the hooks onto PATH)
# - placing default configs in ~ for sxmo-launched services (sxmo_migrate.sh)
# - binding vol/power buttons (sxmo_swayinitconf.sh)
# - launching sxmo_hook_start.sh
#
# the commands here are similar to upstream sxmo_winit.sh, but not identical and the ordering may be different
# profile may contain SXMO_DEVICE_NAME which is used by _sxmo_load_environment so load it early
source "$XDG_CONFIG_HOME/sxmo/profile"
# sourcing upstream sxmo_init.sh triggers _sxmo_load_environment
# which ensures SXMO_* environment variables are set
source ${package}/etc/profile.d/sxmo_init.sh
# _sxmo_prepare_dirs ensures ~/.cache/sxmo & other XDG dirs exist with correct perms & owner
_sxmo_prepare_dirs
# migrate tells sxmo to provide the following default files:
# - ~/.config/sxmo/profile
# - ~/.config/fontconfig/conf.d/50-sxmo.conf
# - ~/.config/sxmo/sway
# - ~/.config/foot/foot.ini
# - ~/.config/mako/config
# - ~/.config/sxmo/bonsai_tree.json
# - ~/.config/wob/wob.ini
# - ~/.config/sxmo/conky.conf
sxmo_migrate.sh sync
# various things may have happened above that require me to re-load the profile here:
# - _sxmo_load_environment sources a deviceprofile.sh file, which may override my profile settings.
# very obvious if you set a non-default SXMO_SWAY_SCALE.
# - sxmo_migrate.sh may have provided a default profile, if i failed to
source "$XDG_CONFIG_HOME/sxmo/profile"
# place my non-specialized hooks at higher precedence than the default device-hooks
# alternative would be to move my hooks to ~/.config/sxmo/hooks/<device-name>.
export PATH="$XDG_CONFIG_HOME/sxmo/hooks:$PATH"
# kill anything leftover from the previous sxmo run. this way we can (try to) be reentrant
echo "sxmo_init: killing stale daemons (if active)"
sxmo_jobs.sh stop all
pkill bemenu
pkill wvkbd
pkill superd
# configure vol/power-button input mapping (upstream SXMO has this in sway config)
echo "sxmo_init: configuring sway bindings/displays with:"
echo "SXMO_POWER_BUTTON: $SXMO_POWER_BUTTON"
echo "SXMO_VOLUME_BUTTON: $SXMO_VOLUME_BUTTON"
echo "SXMO_SWAY_SCALE: $SXMO_SWAY_SCALE"
sxmo_swayinitconf.sh
echo "sxmo_init: invoking sxmo_hook_start.sh with:"
echo "PATH: $PATH"
sxmo_hook_start.sh
'';
in ''
# TODO: some of this is probably unnecessary
mode "menu" {
# just a placeholder for "menu" mode
bindsym --input-device=1:1:1c21800.lradc XF86AudioMute exec nothing
}
bindsym button2 kill
bindswitch lid:on exec sxmo_wm.sh dpms on
bindswitch lid:off exec sxmo_wm.sh dpms off
exec 'printf %s "$SWAYSOCK" > "$XDG_RUNTIME_DIR"/sxmo.swaysock'
# XXX(2023/12/04): this shouldn't be necessary, but without this Komikku fails to launch because XDG_SESSION_TYPE is unset
exec dbus-update-activation-environment --systemd XDG_SESSION_TYPE
exec_always ${sxmo_init}
'';
};
sane.programs.sxmoApps.enableFor.user.colin = true;
sane.programs.sway-autoscaler.config.defaultScale = builtins.fromJSON cfg.settings.SXMO_SWAY_SCALE;
# sxmo internally uses doas instead of sudo
security.doas.enable = true;
security.doas.wheelNeedsPassword = false;
# lightdm-mobile-greeter: "The name org.a11y.Bus was not provided by any .service files"
services.gnome.at-spi2-core.enable = true;
environment.systemPackages = [
package
] ++ lib.optionals (cfg.terminal != null) [ pkgs."${cfg.terminal}" ]
++ lib.optionals (cfg.keyboard != null) [ pkgs."${cfg.keyboard}" ];
environment.sessionVariables = {
XDG_DATA_DIRS = [
# TODO: only need the share/sxmo directly linked
"${package}/share"
];
} // (lib.filterAttrs (k: v:
k == "SXMO_DISABLE_CONFIGVERSION_CHECK" # read before `profile` is sourced
|| k == "SXMO_TERMINAL" # for apps launched via `swaymsg exec -- sxmo_terminal.sh ...`
)
cfg.settings
);
sane.programs.bonsai.config.transitions = let
doExec = inputName: transitions: {
type = "exec";
command = [
"setsid"
"-f"
"sxmo_hook_inputhandler.sh"
inputName
];
inherit transitions;
};
onDelay = ms: transitions: {
type = "delay";
delay_duration = ms * 1000000;
inherit transitions;
};
onEvent = eventName: transitions: {
type = "event";
event_name = eventName;
inherit transitions;
};
friendlyToBonsai = { trigger ? null, terminal ? false, timeout ? {}, power_pressed ? {}, power_released ? {}, voldown_pressed ? {}, voldown_released ? {}, volup_pressed ? {}, volup_released ? {} }@args:
if trigger != null then [
(doExec trigger (friendlyToBonsai (builtins.removeAttrs args ["trigger"])))
] else let
events = [ ]
++ (lib.optional (timeout != {}) (onDelay (timeout.ms or 400) (friendlyToBonsai (builtins.removeAttrs timeout ["ms"]))))
++ (lib.optional (power_pressed != {}) (onEvent "power_pressed" (friendlyToBonsai power_pressed)))
++ (lib.optional (power_released != {}) (onEvent "power_released" (friendlyToBonsai power_released)))
++ (lib.optional (voldown_pressed != {}) (onEvent "voldown_pressed" (friendlyToBonsai voldown_pressed)))
++ (lib.optional (voldown_released != {}) (onEvent "voldown_released" (friendlyToBonsai voldown_released)))
++ (lib.optional (volup_pressed != {}) (onEvent "volup_pressed" (friendlyToBonsai volup_pressed)))
++ (lib.optional (volup_released != {}) (onEvent "volup_released" (friendlyToBonsai volup_released)))
;
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; }));
};
};
in friendlyToBonsai {
# map sequences of "events" to an argument to pass to sxmo_hook_inputhandler.sh
# map: power (short), power (short) x2, power (long)
power_pressed.timeout.ms = 900; # press w/o release. this is a long timeout because it's tied to the "kill window" action.
power_pressed.timeout.trigger = "powerhold";
power_pressed.power_released.timeout.trigger = "powerbutton_one";
power_pressed.power_released.timeout.ms = 300;
power_pressed.power_released.power_pressed.trigger = "powerbutton_two";
# map: volume taps and holds
volup_pressed = (recurseHold "volup" {}) // {
# this either becomes volup_hold_* (via recurseHold, above) or:
# - a short volup_tap_1 followed by:
# - a *finalized* volup_1 (i.e. end of action)
# - more taps/holds, in which case we prefix it with `modal_<action>`
# to denote that we very explicitly entered this state.
#
# it's clunky: i do it this way so that voldown can map to keyboard/terminal in unlock mode
# but trigger media controls in screenoff
# in a way which *still* allows media controls if explicitly entered into via a tap on volup first
volup_released = (volumeActions { prefix = "modal_"; }) // {
trigger = "volup_tap_1";
timeout.ms = 300;
timeout.trigger = "volup_1";
};
};
voldown_pressed = (volumeActions {}).voldown_pressed // {
trigger = "voldown_start";
};
};
# sxmo puts in /share/sxmo:
# - profile.d/sxmo_init.sh
# - appcfg/
# - default_hooks/
# - and more
# environment.pathsToLink = [ "/share/sxmo" ];
# if superd fails to start a service within 100ms, it'll try to start again
# the fallout of this is that during intense lag (e.g. OOM or swapping) it can
# start the service many times.
# see <repo:craftyguy/superd:internal/cmd/cmd.go>
# startTimerDuration = 100 * time.Millisecond
# TODO: better fix may be to patch `sxmo_hook_lisgdstart.sh` and force it to behave as a singleton
# systemd.services."dedupe-sxmo-lisgd" = {
# description = "kill duplicate lisgd processes started by superd";
# serviceConfig = {
# Type = "oneshot";
# };
# script = ''
# if [ "$(${pkgs.procps}/bin/pgrep -c lisgd)" -gt 1 ]; then
# echo 'killing duplicated lisgd daemons'
# ${pkgs.psmisc}/bin/killall lisgd # let superd restart it
# fi
# '';
# wantedBy = [ "multi-user.target" ];
# };
# systemd.timers."dedupe-sxmo-lisgd" = {
# wantedBy = [ "dedupe-sxmo-lisgd.service" ];
# timerConfig = {
# OnUnitActiveSec = "2min";
# };
# };
sane.user.fs = lib.mkMerge [
{
# link the superd services into a place where systemd can find them.
# the unit files should be compatible, except maybe for PATH handling
# ".config/systemd/user/autocutsel-primary.service".symlink.target = "${package}/share/superd/services/autocutsel-primary.service";
# ".config/systemd/user/autocutsel.service".symlink.target = "${package}/share/superd/services/autocutsel.service";
# ".config/systemd/user/bonsaid.service".symlink.target = "${package}/share/superd/services/bonsaid.service";
# # ".config/systemd/user/dunst.service".symlink.target = "${package}/share/superd/services/dunst.service";
# # ".config/systemd/user/mako.service".symlink.target = "${package}/share/superd/services/mako.service";
# ".config/systemd/user/mmsd-tng.service".symlink.target = "${package}/share/superd/services/mmsd-tng.service";
# ".config/systemd/user/sxmo_autosuspend.service".symlink.target = "${package}/share/superd/services/sxmo_autosuspend.service";
# ".config/systemd/user/sxmo_battery_monitor.service".symlink.target = "${package}/share/superd/services/sxmo_battery_monitor.service";
# ".config/systemd/user/sxmo_conky.service".symlink.target = "${package}/share/superd/services/sxmo_conky.service";
# ".config/systemd/user/sxmo_desktop_widget.service".symlink.target = "${package}/share/superd/services/sxmo_desktop_widget.service";
# ".config/systemd/user/sxmo_hook_lisgd.service".symlink.target = "${package}/share/superd/services/sxmo_hook_lisgd.service";
# ".config/systemd/user/sxmo_menumode_toggler.service".symlink.target = "${package}/share/superd/services/sxmo_menumode_toggler.service";
# ".config/systemd/user/sxmo_modemmonitor.service".symlink.target = "${package}/share/superd/services/sxmo_modemmonitor.service";
# ".config/systemd/user/sxmo_networkmonitor.service".symlink.target = "${package}/share/superd/services/sxmo_networkmonitor.service";
# ".config/systemd/user/sxmo_notificationmonitor.service".symlink.target = "${package}/share/superd/services/sxmo_notificationmonitor.service";
# ".config/systemd/user/sxmo_soundmonitor.service".symlink.target = "${package}/share/superd/services/sxmo_soundmonitor.service";
# ".config/systemd/user/sxmo_wob.service".symlink.target = "${package}/share/superd/services/sxmo_wob.service";
# ".config/systemd/user/sxmo-x11-status.service".symlink.target = "${package}/share/superd/services/sxmo-x11-status.service";
# ".config/systemd/user/unclutter.service".symlink.target = "${package}/share/superd/services/unclutter.service";
# ".config/systemd/user/unclutter-xfixes.service".symlink.target = "${package}/share/superd/services/unclutter-xfixes.service";
# ".config/systemd/user/vvmd.service".symlink.target = "${package}/share/superd/services/vvmd.service";
# service code further below tells systemd to put ~/.config/sxmo/hooks on PATH, but it puts hooks/bin on PATH instead, so symlink that
".config/sxmo/hooks/bin".symlink.target = ".";
".cache/sxmo/sxmo.noidle" = lib.mkIf cfg.noidle {
symlink.text = "";
};
".cache/sxmo/sxmo.nogesture" = lib.mkIf cfg.nogesture {
symlink.text = "";
};
".config/sxmo/profile".symlink.text = let
mkKeyValue = key: value: ''export ${key}="${value}"'';
in
lib.generators.toKeyValue { inherit mkKeyValue; } cfg.settings;
}
(lib.mapAttrs' (name: value: {
# sxmo's `_sxmo_load_environments` adds to PATH:
# - ~/.config/sxmo/hooks/$SXMO_DEVICE_NAME
# - ~/.config/sxmo/hooks
name = ".config/sxmo/hooks/${name}";
value.symlink.target = value;
}) cfg.hooks)
];
sane.user.services = let
sxmoPath = [ package ] ++ package.runtimeDeps;
sxmoEnvSetup = ''
# mimic my sxmo_init.sh a bit. refer to the actual sxmo_init.sh above for details.
# the specific ordering, and the duplicated profile sourcing, matters.
export HOME="''${HOME:-/home/colin}"
export XDG_CONFIG_HOME="''${XDG_CONFIG_HOME:-$HOME/.config}"
source "$XDG_CONFIG_HOME/sxmo/profile"
source ${package}/etc/profile.d/sxmo_init.sh
source "$XDG_CONFIG_HOME/sxmo/profile"
export PATH="$XDG_CONFIG_HOME/sxmo/hooks:$PATH:${lib.makeBinPath sxmoPath}"
'';
sxmoService = name: {
description = "sxmo ${name}";
script = ''
${sxmoEnvSetup}
exec sxmo_${name}.sh
'';
serviceConfig.Type = "simple";
serviceConfig.Restart = "always";
serviceConfig.RestartSec = "20s";
};
in {
# these are defined here, and started mostly in sxmo_hook_start.sh.
# the ones commented our here are the ones i explicitly no longer use.
# uncommenting them here *won't* cause them to be auto-started.
sxmo_autosuspend = sxmoService "autosuspend";
# sxmo_battery_monitor = sxmoService "battery_monitor";
sxmo_desktop_widget = sxmoService "hook_desktop_widget";
sxmo_hook_lisgd = sxmoService "hook_lisgdstart";
sxmo_menumode_toggler = sxmoService "menumode_toggler";
sxmo_modemmonitor = sxmoService "modemmonitor";
# sxmo_networkmonitor = sxmoService "networkmonitor";
sxmo_notificationmonitor = sxmoService "notificationmonitor";
# sxmo_soundmonitor = sxmoService "soundmonitor";
# sxmo_wob = sxmoService "wob";
sxmo-x11-status = sxmoService "status_xsetroot";
bonsaid.script = lib.mkBefore sxmoEnvSetup;
};
}
]))
];
}

View File

@@ -1,57 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p procps
# Basic exponential backoff, this should save some resources if we're blocked by
# the same thing for a while
delay() {
sleep "$delay_time"
delay_time="$((delay_time*2))"
if [ "$delay_time" -gt 45 ]; then
delay_time=45
fi
}
wait_item() {
delay_time=1
while $1 > /dev/null 2>&1; do
echo "Blocking suspend for $1"
waited=1
delay
done
}
##################################### below is original, not shared with upstream sxmo_hook_block_suspend.sh
casting_go2tv() {
pgrep -f go2tv
}
# forward to the next block_suspend.sh script (if any).
# have to handle the case where this script is on PATH, and also when it was called without being on PATH.
# the implementation here causes us to call ourselves exactly once, at most (or twice, if there are duplicate PATH entries)
SXMO_HOOK_BLOCK_SUSPEND_DEPTH=$((${SXMO_HOOK_BLOCK_SUSPEND_DEPTH:-0} + 1))
echo "recurse counter: $SXMO_HOOK_BLOCK_SUSPEND_DEPTH"
block_suspend_next=true
FWD_COUNT=0
IFS=:
for p in $PATH ; do
echo "testing: $p/sxmo_hook_block_suspend.sh"
if $(test -x "$p/sxmo_hook_block_suspend.sh"); then
FWD_COUNT=$(($FWD_COUNT + 1))
fi
if [ "$FWD_COUNT" -eq "$SXMO_HOOK_BLOCK_SUSPEND_DEPTH" ]; then
block_suspend_next="$p/sxmo_hook_block_suspend.sh"
break
fi
done
while [ "$waited" != "0" ]; do
waited=0
echo "forwarding to: $block_suspend_next"
SXMO_HOOK_BLOCK_SUSPEND_DEPTH="$SXMO_HOOK_BLOCK_SUSPEND_DEPTH" "$block_suspend_next"
# wait for my own items last. else, we could wait for go2tv, then wait for internals, and in the meantime go2tv was re-spawned.
wait_item casting_go2tv
done

View File

@@ -1,144 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p coreutils -p playerctl -p pulseaudio
# input map considerations
# - using compound actions causes delays.
# e.g. if volup->volup is a distinct action from volup, then single-volup action is forced to wait the maximum button delay.
# - actions which are to be responsive should therefore have a dedicated key.
# - a dedicated "kill" combo is important for unresponsive fullscreen apps, because appmenu doesn't show in those
# - although better may be to force appmenu to show over FS apps
# - bonsai mappings are static, so buttons can't benefit from non-compounding unless they're mapped accordingly for all lock states
# - this limitation could be removed, but with work
#
# example of a design which considers these things:
# - when unlocked:
# - volup toggle -> app menu
# - voldown press -> keyboard
# - voldown hold -> terminal
# - power x2 -> screenoff
# - hold power -> kill app
# - when locked:
# - volup tap -> volume up
# - volup hold -> media seek forward
# - voldown tap -> volume down
# - voldown hold -> media seek backward
# - power x1 -> screen on
# - power x2 -> play/pause media
# some trickiness allows for media controls in unlocked mode:
# - volup tap -> enter media mode
# - i.e. in this state, vol tap/hold is mapped to volume/seek
# - if, after entering media mode, no more taps occur, then we trigger the default app-menu action
# limitations/downsides:
# - power mappings means phone is artificially slow to unlock.
# - media controls when unlocked have quirks:
# - mashing voldown to decrease the volume will leave you with a toggled keyboard.
# - seeking backward isn't possible except by first tapping volup.
# increments to use for volume adjustment
VOL_INCR=5
# replicating the naming from upstream sxmo_hook_inputhandler.sh...
ACTION="$1"
STATE=$(cat "$SXMO_STATE")
noop() {
true
}
handle_with() {
echo "sxmo_hook_inputhandler.sh: STATE=$STATE ACTION=$ACTION: handle_with: $@"
"$@"
exit 0
}
# state is one of:
# - "unlock" => normal operation; display on and touchscreen on
# - "screenoff" => display off and touchscreen off
# - "lock" => display on but touchscreen disabled
# - "proximity{lock,unlock}" => intended for when in a phone call
if [ "$STATE" = "unlock" ]; then
case "$ACTION" in
# powerbutton_one: intentional default to no-op
# powerbutton_two: intentional default to screenoff
"powerhold")
# power thrice: kill active window
handle_with sxmo_killwindow.sh
;;
"volup_tap_1")
# swallow: this could be the start to a media control (multi taps / holds),
# or it could be just a single tap -> release, handled next/below
handle_with noop
;;
"volup_1")
# volume up once: app-specific menu w/ fallback to SXMO system menu
handle_with sxmo_appmenu.sh
;;
"voldown_start")
# volume down once: toggle keyboard
handle_with sxmo_keyboard.sh toggle
;;
"voldown_hold_2")
# hold voldown to launch terminal
# note we already triggered the keyboard; that's fine: usually keyboard + terminal go together :)
# voldown_hold_1 frequently triggers during short taps meant only to reveal the keyboard,
# so prefer a longer hold duration
handle_with sxmo_terminal.sh
;;
"voldown_tap_1")
# swallow, to prevent keyboard from also triggering media controls
handle_with noop
;;
voldown_hold_*)
# swallow, to prevent terminal from also triggering media controls
handle_with noop
;;
esac
fi
if [ "$STATE" = "screenoff" ]; then
case "$ACTION" in
"powerbutton_two")
# power twice => toggle media player
handle_with playerctl play-pause
;;
"powerhold")
# power toggle during deep sleep often gets misread as power hold, so treat same
handle_with sxmo_state.sh set unlock
;;
esac
fi
# default actions
case "$ACTION" in
"powerbutton_one")
# power once => unlock
handle_with sxmo_state.sh set unlock
;;
"powerbutton_two")
# power twice => screenoff
handle_with sxmo_state.sh set screenoff
;;
# powerbutton_three: intentional no-op because overloading the kill-window handler is risky
volup_tap*|modal_volup_tap*)
handle_with pactl set-sink-volume @DEFAULT_SINK@ +"$VOL_INCR%"
;;
voldown_tap*|modal_voldown_tap*)
handle_with pactl set-sink-volume @DEFAULT_SINK@ -"$VOL_INCR%"
;;
volup_hold*|modal_volup_hold*)
handle_with playerctl position 30+
;;
voldown_hold*|modal_voldown_hold*)
handle_with playerctl position 10-
;;
esac
handle_with noop

View File

@@ -1,51 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p coreutils
# the default sxmo_postwake handler checks if the modem is offline
# and if so installs a wakelock to block suspend for 30s.
# that's a questionable place to install that logic, and i want to keep stuff
# out of the wake-from-sleep critical path, so i'm overriding this hook to disable that.
declare -A newmap
wowlan_reason[0x0]="not wowlan"
# mappings are found in megi's linux: drivers/staging/rtl8723cs/include/hal_com.h
wowlan_reason[0x1]="RX_PAIRWISEKEY"
wowlan_reason[0x2]="RX_GTK"
wowlan_reason[0x3]="RX_FOURWAY_HANDSHAKE"
wowlan_reason[0x4]="RX_DISASSOC"
wowlan_reason[0x8]="RX_DEAUTH"
wowlan_reason[0x9]="RX_ARP_REQUEST"
wowlan_reason[0x10]="FW_DECISION_DISCONNECT"
wowlan_reason[0x21]="RX_MAGIC_PKT"
wowlan_reason[0x22]="RX_UNICAST_PKT"
wowlan_reason[0x23]="RX_PATTERN_PKT"
wowlan_reason[0x24]="RTD3_SSID_MATCH"
wowlan_reason[0x30]="RX_REALWOW_V2_WAKEUP_PKT"
wowlan_reason[0x31]="RX_REALWOW_V2_ACK_LOST"
wowlan_reason[0x40]="ENABLE_FAIL_DMA_IDLE"
wowlan_reason[0x41]="ENABLE_FAIL_DMA_PAUSE"
wowlan_reason[0x42]="RTIME_FAIL_DMA_IDLE"
wowlan_reason[0x43]="RTIME_FAIL_DMA_PAUSE"
wowlan_reason[0x55]="RX_PNO"
#ifdef CONFIG_WOW_KEEP_ALIVE_PATTERN
wowlan_reason[0x60]="WOW_KEEPALIVE_ACK_TIMEOUT"
wowlan_reason[0x61]="WOW_KEEPALIVE_WAKE"
#endif/*CONFIG_WOW_KEEP_ALIVE_PATTERN*/
wowlan_reason[0x66]="AP_OFFLOAD_WAKEUP"
wowlan_reason[0xfd]="CLK_32K_UNLOCK"
wowlan_reason[0xfe]="CLK_32K_LOCK"
wowlan_text="$(cat /proc/net/rtl8723cs/wlan0/wowlan_last_wake_reason)"
wowlan_bits="${wowlan_text/last wake reason: /}"
wowlan_reason="${wowlan_reason[$wowlan_bits]}"
echo "exited suspend: $wowlan_text ($wowlan_reason)"
if [ "$wowlan_bits" != "0x0" ]; then
# give time for userspace to respond to the wake event.
# IM clients might have to re-establish TCP connections, perform sync, etc
# until finally receiving the event which the system woke for,
# TODO: if we suspended only very briefly, likely all the networking is in sync
# and we don't have to wait this long.
# there's no easy way *here* to know how long we slept for, though.
sxmo_wakelock.sh lock postwake_work 25s
fi

View File

@@ -1,16 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p sway
# called whenever sxmo_rotate.sh is invoked.
# i.e. whenever the screen is rotated manually, or automatically if autorotate is enabled.
# $1 = the new orientation
# possible values are "normal", "invert", "left" and "right"
# exit fullscreen, if any app is in FS.
# this benefits UX because:
# - most of my FS use is in landscape mode
# - when i toggle apps or desktops i always do so in portrait mode
# - therefore when i rotate landscape -> portrait mode, i almost never want fullscreen anymore.
if [ "$1" = "normal" ] || [ "$1" = "invert" ]; then
swaymsg fullscreen disable
fi

View File

@@ -1,95 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p systemd -p xdg-user-dirs
# this is based on upstream sxmo-utils sxmo_hook_start.sh
# but modified for nixos integration and specialize a bit to my needs
. sxmo_common.sh
# Create xdg user directories, such as ~/Pictures
xdg-user-dirs-update
sxmo_jobs.sh start daemon_manager
# Periodically update some status bar components
# don't: statusbar is managed by waybar
# sxmo_hook_statusbar.sh all
# sxmo_jobs.sh start statusbar_periodics sxmo_run_aligned.sh 60 \
# sxmo_hook_statusbar.sh periodics
# TODO: start these externally, via `wantedBy` in nix
# don't: i don't use mako
# superctl start mako
# systemctl --user start sxmo_wob
systemctl --user start sxmo_menumode_toggler
systemctl --user start bonsaid
# don't: sway background is managed externally
# swaymsg output '*' bg "$SXMO_BG_IMG" fill
# To setup initial lock state
sxmo_state.sh set unlock
# Turn on auto-suspend
if [ -w "/sys/power/wakeup_count" ] && [ -f "/sys/power/wake_lock" ]; then
systemctl --user start sxmo_autosuspend
fi
# Turn on lisgd
if [ ! -e "$XDG_CACHE_HOME"/sxmo/sxmo.nogesture ]; then
systemctl --user start sxmo_hook_lisgd
fi
if [ "$(command -v ModemManager)" ]; then
# Turn on the dbus-monitors for modem-related tasks
systemctl --user start sxmo_modemmonitor
# place a wakelock for 120s to allow the modem to fully warm up (eg25 +
# elogind/systemd would do this for us, but we don't use those.)
sxmo_wakelock.sh lock sxmo_modem_warming_up 120s
fi
# don't: conky is managed externally
# superctl start sxmo_conky
# Monitor the battery
# don't: this is *exclusively* for sxmo_hook_statusbar.sh, which i don't use.
# systemctl --user start sxmo_battery_monitor
# It watch network changes and update the status bar icon by example
# don't: this is for sxmo_hook_statusbar.sh, which i don't use.
# this means we never call sxmo_hook_network_{up,down,...}, but the defaults are no-op anyway
# systemctl --user start sxmo_networkmonitor
# The daemon that display notifications popup messages
# more importantly: it lights the led green when a notification arrives
systemctl --user start sxmo_notificationmonitor
# monitor for headphone for statusbar
# this also invokes `wob` whenever the volume is changed
# don't: my volume monitoring is handled by sway
# systemctl --user start sxmo_soundmonitor
# rotate UI based on physical display angle by default
if [ -n "$SXMO_AUTOROTATE" ]; then
# TODO: this could use ~/.cache/sxmo/sxmo.autorotate like for lisgd above
sxmo_jobs.sh start autorotate sxmo_autorotate.sh
fi
# Play a funky startup tune if you want (disabled by default)
#mpv --quiet --no-video ~/welcome.ogg &
# mmsd and vvmd
if [ -f "${SXMO_MMS_BASE_DIR:-"$HOME"/.mms/modemmanager}/mms" ]; then
systemctl --user start mmsd-tng
fi
if [ -f "${SXMO_VVM_BASE_DIR:-"$HOME"/.vvm/modemmanager}/vvm" ]; then
systemctl --user start vvmd
fi
# add some warnings if things are not setup correctly
if ! command -v "sxmo_deviceprofile_$SXMO_DEVICE_NAME.sh"; then
sxmo_notify_user.sh --urgency=critical \
"No deviceprofile found $SXMO_DEVICE_NAME. See: https://sxmo.org/deviceprofile"
fi
sxmo_migrate.sh state || sxmo_notify_user.sh --urgency=critical \
"Config needs migration" "$? file(s) in your sxmo configuration are out of date and disabled - using defaults until you migrate (run sxmo_migrate.sh)"

View File

@@ -1,122 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p sxmo-utils -p sxmo-utils.runtimeDeps
#
# usage:
# waybar-sxmo-status widget1 [ widget2 [...]]
#
# where each widget is one of:
# - modem-state
# - modem-tech
# - modem-signal
# - wifi-status
# - volume
# sxmo_hook_statusbar.sh assumes:
# - mmcli, jq on PATH
# - sxmo_hook_icons.sh and sxmo_common.sh are sourcable
# - from sxmo_common, it only uses sxmobar (and aliases jq=gojq)
# setup environment so that the hooks will be on PATH:
# - sxmo_hook_statusbar.sh
# - sxmo_hook_icons.sh
export HOME="${HOME:-/home/colin}"
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
export PATH="$XDG_CONFIG_HOME/sxmo/hooks:$PATH"
# ensure that sxmo_audio.sh tells us the volume instead of early-returning
export SXMO_NO_AUDIO=
# clunky interaction between us and sxmo_hook_statusbar.sh:
# - we export `sxmobar` to it, but within that function cannot modify the environment
# of *this* script, because it gets run in a different process.
# - so, `sxmobar` prints info to stdout, and then this script re-interprets that info.
# - practically, `sxmobar` prints shell commands, and then this script `eval`s them, to achieve that IPC.
sxmobar() {
action="$1"
shift
if [ "$action" = "-a" ]; then
while [ -n "$*" ]; do
arg="$1"
case "$arg" in
"-f"|"-b"|"-t"|"-e")
# foreground/background/text/emphasis: ignore it
shift
shift
;;
*)
# begin arguments
break
;;
esac
done
echo "setitem $@"
fi
}
export -f sxmobar
setitem() {
id="$1"
priority="$2"
value="$3"
case "$id" in
modem-state)
modem_state="$value"
;;
modem-tech)
modem_tech="$value"
;;
modem-signal)
modem_signal="$value"
;;
wifi-status)
wifi_status="$value"
;;
volume)
volume="$value"
;;
esac
}
while [ -n "$*" ]; do
variable="$1"
shift
case "$variable" in
"--verbose")
set -x
;;
"modem-state")
if [ -z "$modem_state" ]; then
eval "$(sxmo_hook_statusbar.sh modem)"
fi
echo -n "$modem_state"
;;
"modem-tech")
if [ -z "$modem_tech" ]; then
eval "$(sxmo_hook_statusbar.sh modem)"
fi
echo -n "$modem_tech"
;;
"modem-signal")
if [ -z "$modem_signal" ]; then
eval "$(sxmo_hook_statusbar.sh modem)"
fi
echo -n "$modem_signal"
;;
"wifi-status")
if [ -z "$wifi_status" ]; then
eval "$(sxmo_hook_statusbar.sh network wifi wlan0)"
fi
echo -n "$wifi_status"
;;
"volume")
if [ -z "$volume" ]; then
eval "$(sxmo_hook_statusbar.sh volume)"
fi
echo -n "$volume"
;;
*)
echo -n "UNK: $variable"
;;
esac
done

View File

@@ -1,85 +0,0 @@
# docs: https://github.com/Alexays/Waybar/wiki/Configuration
# format specifiers: https://fmt.dev/latest/syntax.html#syntax
# this is merged with the sway/waybar-top.nix defaults
{
height = 26;
modules-left = [ "sway/workspaces" ];
modules-center = [ ];
modules-right = [
"custom/swaync"
"clock"
"battery"
"custom/sxmo-sane"
# "custom/sxmo"
# "custom/sxmo/modem-state"
# "custom/sxmo/modem-tech"
# "custom/sxmo/modem-signal"
# "custom/sxmo/wifi"
];
"sway/workspaces" = {
all-outputs = true;
# force the bar to always show even empty workspaces
persistent-workspaces = {
"1" = [];
"2" = [];
"3" = [];
"4" = [];
"5" = [];
};
};
"custom/sxmo-sane" = {
# this calls all the SXMO indicators, inline.
# so it works even without the "statusbar periodics" sxmo service running.
interval = 2;
format = "{}";
exec = "waybar-sxmo-status modem-state modem-tech modem-signal wifi-status volume";
};
"custom/sxmo" = {
# this gives wifi state, battery, mic/speaker, lockstate, time all as one widget.
# a good starting point, but may want to split these apart later to make things configurable.
# the values for this bar are computed in sxmo:configs/default_hooks/sxmo_hook_statusbar.sh
exec = "sxmo_status.sh";
interval = 1;
format = "{}";
};
# not ported: battery, ethernet
"custom/sxmo/modem-state" = {
exec = "cat /run/user/1000/sxmo_status/default/10-modem-state";
interval = 2;
format = "{}";
};
"custom/sxmo/modem-tech" = {
exec = "cat /run/user/1000/sxmo_status/default/11-modem-tech";
interval = 2;
format = "{}";
};
"custom/sxmo/modem-signal" = {
exec = "cat /run/user/1000/sxmo_status/default/12-modem-signal";
interval = 2;
format = "{}";
};
"custom/sxmo/wifi" = {
exec = "cat /run/user/1000/sxmo_status/default/30-wifi-status";
interval = 2;
format = "{}";
};
"custom/sxmo/volume" = {
exec = "cat /run/user/1000/sxmo_status/default/50-volume";
interval = 2;
format = "{}";
};
"custom/sxmo/state" = {
exec = "cat /run/user/1000/sxmo_status/default/90-state";
interval = 2;
format = "{}";
};
"custom/sxmo/time" = {
exec = "cat /run/user/1000/sxmo_status/default/99-time";
interval = 2;
format = "{}";
};
}

View File

@@ -1,28 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.sane.gui.theme.background;
in
{
options = with lib; {
sane.gui.theme.background = {
svg = mkOption {
type = types.path;
default = ./nixos-bg-02.svg;
};
png = mkOption {
type = types.path;
default = pkgs.runCommand
"nixos-bg.png"
{ nativeBuildInputs = [ pkgs.inkscape ]; }
''
inkscape ${cfg.svg} -o $out
'';
};
};
};
config = {
sane.programs.sway.config.background = lib.mkDefault cfg.png;
sane.gui.sxmo.settings.SXMO_BG_IMG = lib.mkDefault (builtins.toString cfg.png);
};
}

View File

@@ -17,6 +17,9 @@ let
persistentKeepalive = 25;
# allows wireguard to notice DNS/hostname changes, with this much effective TTL.
dynamicEndpointRefreshSeconds = 600;
# the refresh fails (because e.g. DNS fails to resolve), try it again this soon instead.
# defaults to the same as dynamicEndpointRefreshSeconds, but i think setting it that high stalls my nix switches!
dynamicEndpointRefreshRestartSeconds = 10;
});
# make separate peers to route each given host
mkClientPeers = hosts: builtins.map (p: mkPeer {

View File

@@ -0,0 +1,9 @@
{
"description": "The podcast by the Linux Mint community for all users of Linux.",
"is_podcast": true,
"site_name": "mintCast",
"site_url": "https://mintcast.org",
"title": "mintCast",
"url": "https://mintcast.org/feed/podcast/",
"velocity": 0.121
}

View File

@@ -39,7 +39,8 @@ let
else
let
makeSandboxArgs = pkgs.callPackage ./make-sandbox-args.nix { };
makeSandboxed = pkgs.callPackage ./make-sandboxed.nix { sanebox = config.sane.programs.sanebox.package; };
# makeSandboxed = pkgs.callPackage ./make-sandboxed.nix { sanebox = config.sane.programs.sanebox.package; };
makeSandboxed = pkgs.callPackage ./make-sandboxed.nix { };
vpn = lib.findSingle (v: v.default) null null (builtins.attrValues config.sane.vpn);
@@ -51,7 +52,7 @@ let
"/etc" #< especially for /etc/profiles/per-user/$USER/bin
"/run/current-system" #< for basics like `ls`, and all this program's `suggestedPrograms` (/run/current-system/sw/bin)
"/run/wrappers" #< SUID wrappers. TODO: remove!
# "/run/wrappers" #< SUID wrappers. they don't mean much inside a namespace.
# /run/opengl-driver is a symlink into /nix/store; needed by e.g. mpv
"/run/opengl-driver"
"/run/opengl-driver-32" #< XXX: doesn't exist on aarch64?
@@ -216,13 +217,31 @@ let
'';
};
services = mkOption {
type = types.attrsOf types.anything; # options.sane.users.value.type;
type = options.sane.user._options.services.type;
default = {};
description = ''
user services to define if this package is enabled.
acts as noop for root-enabled packages.
see `sane.users.<user>.services` for options;
'';
# TODO: this `apply` should by moved to where we pass the `services` down to `sane.users`
apply = lib.mapAttrs (svcName: svcCfg:
svcCfg // lib.optionalAttrs (builtins.tryEval svcCfg.description).success {
# ensure service dependencies based on what a service's program whitelists.
# only do this for the services which are *defined* by this program though (i.e. `scvCfg ? description`)
# so as to avoid idioms like when sway adds `graphical-session.partOf = default`
depends = svcCfg.depends
++ lib.optionals (svcName != "dbus" && builtins.elem "user" config.sandbox.whitelistDbus) [
"dbus"
] ++ lib.optionals ((!builtins.elem "wayland" svcCfg.partOf) && config.sandbox.whitelistWayland) [
"wayland"
] ++ lib.optionals ((!builtins.elem "x11" svcCfg.partOf) && config.sandbox.whitelistX) [
"x11"
] ++ lib.optionals ((!builtins.elem "sound" svcCfg.partOf) && config.sandbox.whitelistAudio) [
"sound"
];
}
);
};
buildCost = mkOption {
type = types.enum [ 0 1 2 3 ];
@@ -309,6 +328,13 @@ let
e.g. sandbox.capabilities = [ "net_admin" "net_raw" ];
'';
};
sandbox.isolatePids = mkOption {
type = types.bool;
default = true;
description = ''
whether to place the process in a new PID namespace, if the sandboxer supports that.
'';
};
sandbox.whitelistAudio = mkOption {
type = types.bool;
default = false;
@@ -457,7 +483,7 @@ let
sandbox.extraRuntimePaths =
lib.optionals config.sandbox.whitelistAudio [ "pipewire" "pulse" ] # this includes pipewire/pipewire-0-manager: is that ok?
++ lib.optionals (builtins.elem "user" config.sandbox.whitelistDbus) [ "bus" ]
++ lib.optionals config.sandbox.whitelistWayland [ "wayland" ] # app can still communicate with wayland server w/o this, if it has net access
++ lib.optionals config.sandbox.whitelistWayland [ "wl" ] # app can still communicate with wayland server w/o this, if it has net access
++ lib.optionals config.sandbox.whitelistS6 [ "s6" ] # TODO: this allows re-writing the services themselves: don't allow that!
;
sandbox.extraHomePaths = let
@@ -475,8 +501,10 @@ let
++ lib.optionals (mainProgram != null) (whitelistDir ".config/${mainProgram}")
++ lib.optionals (mainProgram != null) (whitelistDir ".local/share/${mainProgram}")
;
sandbox.extraConfig = lib.mkIf config.sandbox.usePortal [
sandbox.extraConfig = lib.optionals config.sandbox.usePortal [
"--sanebox-portal"
] ++ lib.optionals (!config.sandbox.isolatePids) [
"--sanebox-keep-namespace" "pid"
];
};
});

View File

@@ -1,5 +1,8 @@
{ lib
, stdenv
, buildPackages
, file
, gnugrep
, runCommandLocal
, runtimeShell
, sanebox
@@ -95,20 +98,27 @@ let
done
}
if [ -e "$out/bin" ]; then
crawlAndWrap "$out/bin"
fi
if [ -e "$out/libexec" ]; then
crawlAndWrap "$out/libexec"
fi
for output in $outputs; do
local outdir=''${!output}
echo "scanning output '$output' at $outdir for binaries to sandbox"
if [ -e "$outdir/bin" ]; then
crawlAndWrap "$outdir/bin"
fi
if [ -e "$outdir/libexec" ]; then
crawlAndWrap "$outdir/libexec"
fi
done
'';
});
# there are certain `meta` fields we care to preserve from the original package (priority),
# and others we *can't* preserve (outputsToInstall).
extractMeta = pkg: if (pkg ? meta) && (pkg.meta ? priority) then {
inherit (pkg.meta) priority;
} else {};
extractMeta = pkg: let
meta = pkg.meta or {};
in
(lib.optionalAttrs (meta ? priority) { inherit (meta) priority; })
// (lib.optionalAttrs (meta ? mainProgram) { inherit (meta) mainProgram; })
;
# helper used for `wrapperType == "wrappedDerivation"` which simply symlinks all a package's binaries into a new derivation
symlinkBinaries = pkgName: package: (runCommandLocal "${pkgName}-bin-only" {} ''
@@ -117,6 +127,10 @@ let
mkdir -p "$out/bin"
${buildPackages.xorg.lndir}/bin/lndir "${package}/bin" "$out/bin"
fi
if [ "$(readlink ${package}/sbin)" == "bin" ]; then
# weird packages like wpa_supplicant depend on a sbin/ -> bin symlink in their service files
ln -s bin "$out/sbin"
fi
if [ -e "${package}/libexec" ]; then
mkdir -p "$out/libexec"
${buildPackages.xorg.lndir}/bin/lndir "${package}/libexec" "$out/libexec"
@@ -128,7 +142,7 @@ let
meta = extractMeta package;
});
# helper used for `wrapperType == "wrappedDerivation"` which ensures that and copied/symlinked share/ files (like .desktop) files
# helper used for `wrapperType == "wrappedDerivation"` which ensures that any copied/symlinked share/ files (like .desktop) files
# don't point to the unwrapped binaries.
# other important files it preserves:
# - share/applications
@@ -136,6 +150,7 @@ let
# - share/icons
# - share/man
# - share/mime
# - {etc,lib,share}/systemd
fixHardcodedRefs = unsandboxed: sandboxedBin: unsandboxedNonBin: unsandboxedNonBin.overrideAttrs (prevAttrs: {
postInstall = (prevAttrs.postInstall or "") + ''
trySubstitute() {
@@ -155,17 +170,17 @@ let
# fixup a few files i understand well enough
for d in \
$out/etc/xdg/autostart/*.desktop \
$out/lib/systemd/user/*.service \
$out/share/applications/*.desktop \
$out/share/dbus-1/services/*.service \
$out/share/systemd/user/*.service \
$out/share/dbus-1/{services,system-services}/*.service \
$out/{etc,lib,share}/systemd/{system,user}/*.service \
; do
# dbus and desktop files
trySubstitute "$d" "Exec=%s/bin/"
trySubstitute "$d" "Exec=%s/libexec/"
# systemd service files
trySubstitute "$d" "ExecStart=%s/bin/"
trySubstitute "$d" "ExecStart=%s/libexec/"
# Exec: dbus and desktop files
# ExecStart,ExecReload: systemd service files
for key in Exec ExecStart ExecReload; do
for binLoc in bin libexec sbin; do
trySubstitute "$d" "$key=%s/$binLoc/"
done
done
done
'';
passthru = (prevAttrs.passthru or {}) // {
@@ -220,43 +235,59 @@ let
priority = ((prevAttrs.meta or {}).priority or 0) - 1;
};
passthru = (prevAttrs.passthru or {}) // extraPassthru // {
checkSandboxed = runCommandLocal "${pkgName}-check-sandboxed" {} ''
checkSandboxed = runCommandLocal "${pkgName}-check-sandboxed" {
nativeBuildInputs = [ file gnugrep sanebox ];
buildInputs = builtins.map (out: finalAttrs.finalPackage."${out}") (finalAttrs.outputs or [ "out" ]);
} ''
set -e
# invoke each binary in a way only the sandbox wrapper will recognize,
# ensuring that every binary has in fact been wrapped.
_numExec=0
_checkExecutable() {
echo "checking if $1 is sandboxed"
PATH="${finalAttrs.finalPackage}/bin:${sanebox}/bin:$PATH" \
SANEBOX_DISABLE=1 \
"$1" --sanebox-replace-cli echo "printing for test" \
local dir="$1"
local binname="$2"
echo "checking if $dir/$binname is sandboxed"
# XXX: call by full path because some binaries (e.g. util-linux) would otherwise
# be shadowed by things the nix builder implicitly puts on PATH.
# additionally, call via qemu and manually specify the interpreter *if the file has one*.
# if the file doesn't have an interpreter, assume it's directly invokable by qemu (hence, the intentional lack of quotes around `interpreter`)
set -x
local realbin="$(realpath $dir/$binname)"
local interpreter=$(file "$realbin" | grep --only-matching "a /nix/.* script" | cut -d" " -f2 || echo "")
${stdenv.hostPlatform.emulator buildPackages} $interpreter "$dir/$binname" --sanebox-replace-cli echo "printing for test" \
| grep "printing for test"
_numExec=$(( $_numExec + 1 ))
}
_checkDir() {
for b in $(ls "$1"); do
if [ -d "$1/$b" ]; then
local dir="$1"
for b in $(ls "$dir"); do
if [ -d "$dir/$b" ]; then
if [ "$b" != .sandboxed ]; then
_checkDir "$1/$b"
_checkDir "$dir/$b"
fi
elif [ -x "$1/$b" ]; then
_checkExecutable "$1/$b"
elif [ -x "$dir/$b" ]; then
_checkExecutable "$dir" "$b"
else
test -n "$CHECK_DIR_NON_BIN"
fi
done
}
# *everything* in the bin dir should be a wrapped executable
if [ -e "${finalAttrs.finalPackage}/bin" ]; then
_checkDir "${finalAttrs.finalPackage}/bin"
fi
for outDir in $buildInputs; do
echo "starting crawl from package output: $outDir"
# *everything* in the bin dir should be a wrapped executable
if [ -e "$outDir/bin" ]; then
echo "checking toplevel dir at $outDir/bin"
_checkDir "$outDir/bin"
fi
# the libexec dir is 90% wrapped executables, but sometimes also .so/.la objects.
# note that this directory isn't flat
if [ -e "${finalAttrs.finalPackage}/libexec" ]; then
CHECK_DIR_NON_BIN=1 _checkDir "${finalAttrs.finalPackage}/libexec"
fi
# the libexec dir is 90% wrapped executables, but sometimes also .so/.la objects.
# note that this directory isn't flat
if [ -e "$outDir/libexec" ]; then
echo "checking toplevel dir at $outDir/libexec"
CHECK_DIR_NON_BIN=1 _checkDir "$outDir/libexec"
fi
done
echo "successfully tested $_numExec binaries"
test "$_numExec" -ne 0

View File

@@ -1,6 +1,7 @@
{ ... }:
{
imports = [
./dropbear.nix
./clightning.nix
./dyn-dns.nix
./eg25-manager.nix

View File

@@ -0,0 +1,37 @@
{ config, lib, pkgs, ... }:
let
cfg = config.sane.services.dropbear;
in
{
options = {
sane.services.dropbear = with lib; {
enable = mkOption {
default = false;
type = types.bool;
};
package = mkOption {
type = types.package;
default = pkgs.dropbear;
defaultText = literalExpression "pkgs.dropbear";
};
port = mkOption {
type = types.port;
default = 22;
};
};
};
config = lib.mkIf cfg.enable {
systemd.services.dropbear = {
description = "Dropbear SSH Server";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.Type = "simple";
# N.B.: dropbear ssh key format is incompatible with OpenSSH's.
# also, needs to be manually generated on first run (`dropbearkey -t rsa -f /etc/ssh/host_keys/dropbear_rsa_host_key -s 4096`)
serviceConfig.ExecStart = "${cfg.package}/bin/dropbear -F -p ${builtins.toString cfg.port} -r /etc/ssh/host_keys/dropbear_rsa_host_key -r /etc/ssh/host_keys/dropbear_ed25519_host_key";
};
};
}

View File

@@ -1,5 +1,4 @@
# eg25-manager: <https://gitlab.com/mobian1/eg25-manager>
# - used by sxmo, in <configs/default_hooks/sxmo_hook_restart_modem_daemons.sh>
# - requires modemmanager (ModemManager.service)
{ config, lib, pkgs, ... }:
let

View File

@@ -35,7 +35,7 @@ let
'';
example = {
"%CNAMESELF%" = "lappy";
"%AWAN%" = ''"$(cat /var/www/wan.txt)"'';
"%AWAN%" = ''"$(cat /var/uninsane/wan.txt)"'';
};
};
includes = mkOption {
@@ -117,9 +117,9 @@ let
'') dns.zones
);
serviceConfig = config.systemd.services.trust-dns.serviceConfig // {
serviceConfig = (config.systemd.services.hickory-dns or config.systemd.services.trust-dns).serviceConfig // {
ExecStart = lib.escapeShellArgs ([
"${config.services.trust-dns.package}/bin/${config.services.trust-dns.package.meta.mainProgram}"
"${lib.getExe config.services.trust-dns.package}"
"--port" (builtins.toString port)
"--zonedir" "/var/lib/trust-dns/${flavor}"
"--config" "${configPath}"
@@ -131,7 +131,10 @@ let
# servo/dyn-dns needs /var/lib/uninsane/wan.txt.
# this might not exist on other systems,
# so just bind the deepest path which is guaranteed to exist.
ReadOnlyPaths = [ "/var/lib" ];
ReadOnlyPaths = [ "/var/lib" ]; #< TODO: scope this down!
} // lib.optionalAttrs cfg.asSystemResolver {
# allow the group to write trust-dns state (needed by NetworkManager hook)
StateDirectoryMode = "775";
};
};
in
@@ -181,9 +184,10 @@ in
rev = "67649863faf2e08f63963a96a491a4025aaf8ed6";
hash = "sha256-vmVY8C0cCCFxy/4+g1vKZsAD5lMaufIExnFaSVVAhGM=";
};
cargoHash = "sha256-FEjNxv1iu27SXQhz1+Aehs4es8VxT1BPz5uZq8TcG/k=";
cargoHash = "sha256-NoWrQgTPOp99pEs73VQrfeU3m8fny2s20Mf9qxwiPtQ=";
});
};
services.trust-dns.settings.directory = "/var/lib/trust-dns";
users.groups.trust-dns = {};
users.users.trust-dns = {
@@ -193,6 +197,18 @@ in
systemd.services = lib.mkMerge [
{
hickory-dns.enable = false;
hickory-dns.serviceConfig = {
DynamicUser = lib.mkForce false;
User = "trust-dns";
Group = "trust-dns";
wantedBy = lib.mkForce [];
# there can be a lot of restarts as interfaces toggle,
# particularly around the DHCP/NetworkManager stuff.
StartLimitBurst = 60;
StateDirectory = lib.mkForce "trust-dns";
};
trust-dns.enable = false;
trust-dns.serviceConfig = {
DynamicUser = lib.mkForce false;
@@ -202,6 +218,7 @@ in
# there can be a lot of restarts as interfaces toggle,
# particularly around the DHCP/NetworkManager stuff.
StartLimitBurst = 60;
StateDirectory = lib.mkForce "trust-dns";
};
# trust-dns.unitConfig.StartLimitIntervalSec = 60;
}
@@ -214,10 +231,23 @@ in
)
];
# run a hook whenever networking details change, so the DNS zone can be updated to reflect this
environment.etc."NetworkManager/dispatcher.d/60-trust-dns-nmhook" = lib.mkIf cfg.asSystemResolver {
source = "${trust-dns-nmhook}/bin/trust-dns-nmhook";
};
# allow NetworkManager (via trust-dns-nmhook) to restart trust-dns when necessary
# - source: <https://stackoverflow.com/questions/61480914/using-policykit-to-allow-non-root-users-to-start-and-stop-a-service>
security.polkit.extraConfig = lib.mkIf cfg.asSystemResolver ''
polkit.addRule(function(action, subject) {
if (subject.isInGroup("trust-dns") &&
action.id == "org.freedesktop.systemd1.manage-units" &&
action.lookup("unit") == "trust-dns-localhost.service") {
return polkit.Result.YES;
}
});
'';
sane.services.trust-dns.instances.localhost = lib.mkIf cfg.asSystemResolver {
listenAddrsIpv4 = [ "127.0.0.1" ];
listenAddrsIpv6 = [ "::1" ];

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