1
0
forked from colin/nix-files

Compare commits

...

249 Commits

Author SHA1 Message Date
47f474fecd moby: fix the magnetometer (compass)
it's not immediately viewable by geoclue, but it's viewable (and
working) from the CLI:
```
SANEBOX_DISABLE=1 watch cat /sys/devices/platform/soc/1c2b000.i2c/i2c-1/1-001c/iio:device2/in_magn_x_raw
```

the longer-term fix requires u-boot integration, but this hack is
actually entirely contained to linux. u-boot gives linux a
mostly-unmodified dtb from the linux package, and i just modify the
linux dtb to use the specific magnetometer my hardware has.
2024-07-02 20:29:49 +00:00
828ef00b61 servo: transmission: torrent-done: print call args at start to aid debugging 2024-07-02 16:07:46 +00:00
5d14a39d52 qmk: ergodox: make braces easier to type and clean up layers 2024-07-02 14:09:42 +00:00
58f89aadf3 scripts: add a way to flash my ergodox-ez firmware 2024-07-02 12:18:58 +00:00
d9a03ee64a signal-desktop-from-src: 7.11.1 -> 7.14.0 2024-07-02 09:53:55 +00:00
697543a675 u-boot-pinephone: use "extraPatches" instead of "patches", to future-proof 2024-07-01 17:44:53 +00:00
ff235f5806 dino: run mainline again, as Dino has released 0.4.4 (which doesnt contain eeevery commit i was running before, but most 2024-07-01 17:25:40 +00:00
39fe0ce43a syshud: 2024-06-20 -> 2024-06-29 2024-07-01 16:57:03 +00:00
98fde86ff6 uassets: 2024-06-26 -> 2024-07-01 2024-07-01 16:57:03 +00:00
5c6a5b01c4 sops-nix: 2024-06-24 -> 2024-07-01 2024-07-01 16:57:03 +00:00
bb4f963c9c nixpkgs-wayland: 2024-06-26 -> 2024-07-01 2024-07-01 16:57:03 +00:00
9eb0b3fc86 nixpkgs: 2024-06-30 -> 2024-07-01 2024-07-01 16:57:03 +00:00
5b7f15b278 moby: upgrade Tow-Boot -> u-boot
i'm trying to get the compass to work, but looks as though it didnt try to probe the 1.2b AF8133J
2024-07-01 16:56:46 +00:00
5176d6a3bc moby: enable iio sensor access (rotation, light; compass is not yet working) 2024-07-01 11:57:06 +00:00
84ba7e3d68 mepo: fix sandboxed geoclue interactions 2024-07-01 08:19:21 +00:00
6d16d83aab geoclue-ols: fix that lru_cache was applied to an async function, even though futures can only be run once 2024-07-01 08:18:22 +00:00
e9c51eddb3 feeds: subscribe to Matt Stoller 2024-07-01 07:33:41 +00:00
75473c7123 nixpkgs: 2024-06-26 -> 2024-06-30 2024-07-01 06:15:42 +00:00
10f7714cfd firefox-extensions.ether-metamask: 11.16.14 -> 11.16.15 2024-07-01 06:13:25 +00:00
fe78f8bc45 geoclue-ols: 2024-06-21 -> 2024-06-30 (cache cellid lookup results) 2024-06-30 18:43:07 +00:00
6bbe3a8e23 qmk/ergodox/udev: cleanup 2024-06-30 16:52:36 +00:00
98c4a5ec87 qmkPackages.all: document how to flash 2024-06-30 16:18:43 +00:00
bf3a894d38 sane-scripts.wipe: fix missing procps dep 2024-06-30 16:13:56 +00:00
c973f2e03b qmkPackages.ergodox_ez_glow_sane: tune keymap 2024-06-30 16:13:05 +00:00
9f76469b5c qmkPackages: add my own layout (copied from base ergodox_ez keymap) 2024-06-30 14:06:45 +00:00
52231f2adc qmk-firmware: init at 0.25.9 2024-06-30 13:24:27 +00:00
8c5d9d79d7 todo.md: sync 2024-06-30 07:39:21 +00:00
961c38e79b scripts/check-uninsane: fix doofnet ftp test to actually route over doofnet 2024-06-30 06:35:04 +00:00
fc5068f4d4 pc: add tools to make using the ZSA Ergodox easier 2024-06-28 10:25:02 +00:00
e641f5c93a mpv: associate with m.youtube.com mobile URLs as well 2024-06-28 04:39:39 +00:00
870e766966 nixpkgs: remove listparser patch (PR closed; not upstreaming it) 2024-06-28 04:39:39 +00:00
a75a341b56 sane-wipe: fix so pkill is available 2024-06-28 04:39:39 +00:00
8b7ed2cdd4 avahi: fix NSS integrations
now moby can access its own gps-share instance at moby.local, from geoclue.service. lappy can access that too.
2024-06-27 23:57:36 +00:00
b3a685aa31 python3Packages -> python3.pkgs, to fix cross-compilation errors (especially around geoclue-ols) 2024-06-27 15:46:04 +00:00
9b8c461ce9 dont treat python packages specially: lift all python packages out of python-packages/ subdir; remove pyPkgs arg from static-nix-shell.mkPython3 2024-06-27 11:28:17 +00:00
27de05a751 python-packages: fix cross compilation errors introduced during the move away from buildPythonPackage 2024-06-27 09:02:30 +00:00
f54f1c57bc avahi: integrate with nss
now i can resolve .local hosts, via glibc, e.g. 'getent hosts <host>.local'
2024-06-27 06:18:48 +00:00
98d6439f2a modules/warnings: add a way to bypass module-level assertions as well 2024-06-27 06:17:53 +00:00
fbcf2aed41 python packages: port away from buildPythonPackage -> stdenv.mkDerivation
in a future refactoring, maybe i can remove them from the special 'pkgs/python-packages' directory altogether
2024-06-26 23:37:27 +00:00
fb7701027e nixpkgs: 2024-06-24 -> 2024-06-26 2024-06-26 21:02:07 +00:00
0bc228c07b nixpkgs-wayland: 2024-06-23 -> 2024-06-26 2024-06-26 21:01:49 +00:00
943ebba7fb sops-nix: 2024-06-23 -> 2024-06-24 2024-06-26 21:01:30 +00:00
e41bf78db6 uassets: 0-unstable-2024-06-23 -> 0-unstable-2024-06-26 2024-06-26 21:01:12 +00:00
8588230f80 firefox-extensions.ublock: 1.58.1b10 -> 1.58.1b11 2024-06-26 21:00:53 +00:00
8ef1af7e22 firefox-extensions.ether-metamask: 11.16.13 -> 11.16.14 2024-06-26 21:00:27 +00:00
989344f87e geoclue: integrate with gps-share, via avahi
N.B.: this doesn't actually work on moby -- yet. need to fix avahi DNS lookups
2024-06-26 11:22:04 +00:00
90f8d1e042 gps-share: specify /dev path to GPS device 2024-06-26 11:22:04 +00:00
d8ca5f91c3 sane-sysload: add an option to query battery *percent* charged 2024-06-26 10:56:08 +00:00
167bb4d8de servo: transmission: torrent-done: fix typo 2024-06-26 09:21:51 +00:00
6b117fa9bf servo: transmission: torrent-done: implement a TR_NO_HARDLINK option 2024-06-26 09:05:51 +00:00
4b9dcd50fb WIP: ship gps-share on moby 2024-06-26 09:05:27 +00:00
84e6d536d6 gps-share: init at 0.3.1 2024-06-26 08:43:37 +00:00
4c74e53052 servo: transmission: torrent-done: log destructive ops when TR_DEBUG=1 2024-06-26 08:27:16 +00:00
5def8f30ad servo: transmission: torrent-done: fix typos and add a TR_DEBUG option 2024-06-26 08:20:03 +00:00
45dd144b24 servo: transmission: torrent-done: fix dry-run; ensure all destructive ops are actually marked as destructive 2024-06-26 08:09:57 +00:00
66d4b380da servo: transmission: torrent-done: remove more noisy files 2024-06-26 08:01:58 +00:00
8e7da2c956 servo: transmission: split torrent-done script into own file 2024-06-26 07:59:20 +00:00
0f11b9a7b7 mpv: associate with YouTube Shorts videos 2024-06-25 21:17:27 +00:00
d9437bf4aa listparser: switch from buildPythonPackage -> stdenv.mkDerivation 2024-06-24 21:12:38 +00:00
5d1c52d0bc feeds: add buttondown.email 2024-06-24 17:05:10 +00:00
a0dfdb5125 init-feed: lift out of pkgs/ and into scripts/ where its easier to invoke 2024-06-24 17:04:23 +00:00
cbc2ba02a4 python3Packages.listparser: grab from nixpkgs patch instead 2024-06-24 15:07:19 +00:00
ef0adb5689 nixpkgs-wayland: 2024-06-21 -> 2024-06-23 2024-06-24 14:21:48 +00:00
b1bd4399f1 nixpkgs: 2024-06-21 -> 2024-06-24 2024-06-24 14:21:19 +00:00
2b252e3ede sops-nix: 2024-06-16 -> 2024-06-23 2024-06-24 14:20:58 +00:00
9aaf89408a uassets: 2024-06-21 -> 2024-06-23 2024-06-24 14:20:37 +00:00
283ca45c5d sponsorblock: 5.6.1 -> 5.6 ; ublacklist: 8.8.1 -> 8.8.2 2024-06-24 14:19:14 +00:00
7955d90f8d python3Packages.listparser: 0.18 -> 0.20 2024-06-24 12:48:43 +00:00
a06481fbef python3Packages.listparser: fetch from GitHub instead of PyPi" 2024-06-24 12:40:09 +00:00
5db4d73ad6 gpodder: lift listparser out of gnome-feeds
it's being removed in https://github.com/NixOS/nixpkgs/pull/320801 i.e. when i next update nixpkgs
2024-06-24 12:35:52 +00:00
304c8f8e3e docs: eg25-control: elaborate on Almanac v.s. Ephemeris 2024-06-24 00:25:54 +00:00
5a09a2665b secrets: net: add new home wifi creds 2024-06-23 18:16:10 +00:00
209545fc41 refactor: split satellite program into own file
mainly so i have a place to document its GUI :)
2024-06-23 12:44:50 +00:00
1e12566207 moby: disable gpsd
1. i wasn't actually relying on it for anything. 2. it's 100k LoC which runs as root (?), in a totally un-secured systemd service.

i may be enabling something similar like this in the future, to prevent geoclue from deciding to disable the GPS. i'll probably be going with the simpler gps-share or gnss-share for that
2024-06-23 03:53:24 +00:00
9a53cbc833 docs: geoclue: link to forums, git, API docs 2024-06-23 03:53:07 +00:00
439bb5263f switchboard: sandbox 2024-06-22 03:43:23 +00:00
845dba3ca5 modules/vpn: fix deprecation warnings 2024-06-22 03:35:41 +00:00
5e7fe850ec blast-ugjka: 0.6.2 -> 0.7.0 2024-06-22 01:25:26 +00:00
832338488d firefox-extensions.ether-metamask: 11.16.12 -> 11.16.13 2024-06-22 01:24:58 +00:00
86ee95f607 uassets: intra-day bump 2024-06-22 01:24:46 +00:00
5f5e55c98b nixpkgs-wayland: 2024-06-20 -> 2024-06-21 2024-06-22 01:24:26 +00:00
7d59782005 nixpkgs: intra-day bump 2024-06-22 01:24:09 +00:00
62b541012b blast-ugjka: add an updateScript 2024-06-21 19:14:47 +00:00
514197a17f docs: mmcli: include notes for how to enable the gps 2024-06-21 19:11:07 +00:00
143bdf672b ship satellite program
really this only belongs on devices which have a gps unit (i.e. moby).
maybe i'll tune that in the future.
2024-06-21 19:09:43 +00:00
a6c48eda71 geoclue2: remove extraneous appConfig where-am-i whitelisting
it's included by the default nixos service (which whitelists 'geoclue-demo-agent'
2024-06-21 17:49:15 +00:00
a603c3e6bc ols: synthesize cell tower data when no exact match is found 2024-06-21 16:24:13 +00:00
1f48f41927 ols: ship static cell tower position database from opencellid.org 2024-06-21 13:48:28 +00:00
c0d9f05575 python3Packages.ols: point to my own repo, 2023-06-15 -> 2024-06-21 2024-06-21 13:42:02 +00:00
7f46b034f9 opencellid: init at 0-unstable-2024-06-20 2024-06-21 12:55:38 +00:00
ba66378bc0 docs: ols: point to wigle docs and api limits 2024-06-21 11:54:38 +00:00
dcc8168aa0 nixpkgs: update sysvol patch 2024-06-07 -> 2024-06-20 2024-06-21 11:54:07 +00:00
f7d3c26d12 servo: irc: add wigle.net 2024-06-21 11:48:47 +00:00
3d871e8d7c scripts/check-nur: fix (linux-exynos5-mainline was invalid in default eval) 2024-06-21 07:43:33 +00:00
78f4cd9be2 sysvol: 2024-06-13 -> 2024-06-20 2024-06-21 07:25:15 +00:00
f83bac3c2b firefox-extensions -> latest 2024-06-21 07:25:15 +00:00
58de5d661f uassets: 2024-06-15 -> 2024-06-21 2024-06-21 07:25:15 +00:00
599832d59c 2024-06-11 -> 2024-06-16 2024-06-21 07:25:15 +00:00
625cb0992b nixpkgs-wayland: 2024-06-14 -> 2024-06-20 2024-06-21 07:25:15 +00:00
a02f221628 nixpkgs: 2024-06-19 -> 2024-06-21 2024-06-21 07:25:15 +00:00
ad8bcfc09e scripts/deploy: build all hosts before building all variants 2024-06-21 07:25:15 +00:00
815ce6287f scripts/update: fix that the script wasnt building the update scripts before trying to invoke them 2024-06-21 07:25:15 +00:00
0d1d56870f default.nix: copy everything to the nix store before evaluating any of my config 2024-06-21 07:25:15 +00:00
2445b882c2 scripts/update: more debug logging 2024-06-20 22:54:16 +00:00
12465e111e nixpkgs: update xsimd patch 2024-06-20 21:54:06 +00:00
65a0914828 fastcluster/ols: fix cross compilation to moby 2024-06-20 13:33:18 +00:00
dab60e79c1 moby: remove gps.nix 2024-06-20 12:01:10 +00:00
fe57f186cd gpsd: deploy via sane.programs interface 2024-06-20 11:57:09 +00:00
78d66a8b09 ols: pipe stderr > stdout 2024-06-20 11:52:35 +00:00
b2955c9c9d geoclue2: use nixpkgs' service 2024-06-20 11:52:13 +00:00
b0e184b0f0 geoclue: integrate ols/wigle as backend
the wigle API limits are *strict*. probably too strict to actually be useful
2024-06-20 11:35:26 +00:00
3cd97b522c ols: enable
still some more work to do to really integrate this with geoclue
2024-06-20 11:05:15 +00:00
c91681c77c python3Packages.ols: init at at 0.1.0-unstable-2023-06-15 2024-06-20 11:05:15 +00:00
d0d623da15 programs: ship geoclue2 as an actual program
moby probably needs its gps.nix file removed. also this is incomplete due to Mozilla terminating their location services API
2024-06-20 08:40:36 +00:00
0db86d8c86 moby: sway: use Alt as the modifier key 2024-06-20 05:55:12 +00:00
b74dfe7578 crappy: sway: use Alt as the mod key 2024-06-20 05:55:12 +00:00
d1843b6b3d refactor: sway-config -> config, to match its installed name 2024-06-20 05:55:12 +00:00
b482a1dfd6 swaync: disable debug, to un-break DND mode
i'm sick of G_MESSAGES_DEBUG breaking stuff. i must be parsing cli output that gets broken by that, somewhere
2024-06-20 05:24:53 +00:00
5ba74a4055 doc: swaync: fix typo in notify-send example 2024-06-20 05:17:51 +00:00
b3b77e3e62 nwg-panel: stylize with the goal that it uses a bit less space on moby 2024-06-20 02:39:45 +00:00
63bc58a56f playerctl: patch missing refcount tracking to avoid a crash in nwg-panel 2024-06-20 00:46:31 +00:00
efcf8639dc gdb: ship a python-capable gdbinit 2024-06-19 23:03:17 +00:00
90b86dc7fc servo: re-enable transmission and jackett 2024-06-19 21:29:32 +00:00
8bf8d31c5f nwg-panel: record the URL to the upstream PR 2024-06-19 21:28:18 +00:00
2e44abc55d scripts/deploy: fix off-by-one in runOnTarget 2024-06-19 21:05:37 +00:00
9e92069ba3 nwg-panel: migrate the mediaPrevNext patch to something suitable for upstream 2024-06-19 21:04:15 +00:00
2a592a4a15 nwg-panel: disable the music-note icon in playerctl 2024-06-19 20:35:50 +00:00
8ca357ea7f scripts/deploy: add a --reboot option 2024-06-19 20:31:43 +00:00
4f4c05a922 nwg-panel: fix playerctl patch for newest nwg-panel, and also hide the label
hopefully the label is the part which includes the music note icon
2024-06-19 19:40:23 +00:00
7c4be0f4e9 hosts: fix that -min and -light variants were actually identical to the full versions 2024-06-19 11:25:30 +00:00
afea7fe5e7 scripts/deploy: implement a dry-run mode 2024-06-19 11:24:33 +00:00
294f0061bd sxmo-utils: add a deprecation warning 2024-06-19 11:20:49 +00:00
4efe159933 nixpkgs: 2024-06-15 -> 2024-06-19 2024-06-19 10:35:58 +00:00
b7f99c022b nwg-panel: enable sysload by default 2024-06-19 02:04:33 +00:00
b3c5e53156 sane-sysload: implement CPU measurement 2024-06-19 01:58:21 +00:00
91c2b04ab4 sane-sysload: make the format CLI args friendlier 2024-06-19 01:20:36 +00:00
27efb10a27 refactor: rename sane-sysinfo -> sane-sysload 2024-06-19 01:04:06 +00:00
e4e32f46fe nwg-panel: integrate optional sysload executor (WIP; disabled by default) 2024-06-19 01:01:03 +00:00
64b169069a nwg-panel: fix issue that playerctl was being pushed off the bar 2024-06-19 00:47:43 +00:00
c2c15e1ac3 networkmanager_dmenu: sandbox 2024-06-19 00:44:35 +00:00
0b3156c4c7 nmcli: sandbox 2024-06-19 00:44:24 +00:00
1c8551c842 rofi: add a shortcut for configuring WiFi 2024-06-18 23:44:21 +00:00
2755d98b99 sane-open: make sure networkmanager_dmenu shows the keyboard when activated 2024-06-18 23:44:21 +00:00
543108a5dd networkmanager_dmenu: ship 2024-06-18 23:44:21 +00:00
b32d02dc3f programs: add pidof from procps
used by things like networkmanager-dmenu, which i plan to add soon
2024-06-18 23:44:20 +00:00
0bd92ef77e swaync: make the backlight/mpris items configurable 2024-06-18 21:41:15 +00:00
a7df4cc125 lint: swaync: sort config properties 2024-06-18 21:34:04 +00:00
09a615ee62 netns: factor the netns setup/teardown into distinct services, rather than trying to piggyback network-local-commands
idk what network-local-commands is about, nor network-pre.target.
network-pre.target doesn't seem to actually be wanted by anything (?)
2024-06-18 10:36:08 +00:00
8523b406ad todo.md: note that swaync brightness slider does not work 2024-06-18 09:48:35 +00:00
6021da072c replace builtins.toJSON with writers.writeJSON where possible
it gives pretty-printed JSON that's easier to work with
2024-06-18 09:33:17 +00:00
a49abbd123 hosts: add pubkeys for $host-hn 2024-06-18 09:33:17 +00:00
f9091c0b0c netns: ensure that network.target depends on network-pre.target (why doesnt it by default?)
this should fix that servo tries to start wg-ovpns before the netns is configured
2024-06-18 09:07:40 +00:00
bbf8fd5b20 servo: disable almost all WAN stuff (leave only wireguard, as a fallback) 2024-06-18 09:04:13 +00:00
be84747ffc check-uninsane: test FTP over doof (and simplify) 2024-06-18 08:09:06 +00:00
478b443430 doc: sftpgo: note that "/README.md" doesnt work 2024-06-18 07:56:26 +00:00
ded5f6560d check-uninsane: fix ftp test to work when invoked from the wan 2024-06-18 07:55:11 +00:00
c1b3629dcf swaync: fix segfault under load 2024-06-18 07:52:02 +00:00
5879499924 swaync-service-dispatcher: simplify quoting 2024-06-18 06:40:44 +00:00
5a63f294c0 servo: sftpgo: allow fully-anonymous www read access to /pub
this will help me write automated tests for its availability
2024-06-18 05:44:20 +00:00
891a29feeb nwg-panel: fix commands (like lock, shutdown) to not run through swaymsg 2024-06-18 02:51:58 +00:00
0863505877 wifi: add new network 2024-06-18 02:34:27 +00:00
0c922bd63a nwg-panel: fix reboot/shutdown commands to not assume systemd 2024-06-18 02:32:04 +00:00
e04ec4c706 nwg-panel: fix the "lock" button to use the correct screen locker 2024-06-18 02:31:46 +00:00
b0f9733ac8 sway: fix that Super+L didnt have sandbox access to start the screen locker 2024-06-18 02:26:57 +00:00
e2babfc076 nwg-panel: fix clock to always be centered, even if that means overlapped rendering 2024-06-18 01:08:02 +00:00
ef29b569e5 nwg-panel: fix clock size to actually be larger on lappy/desko 2024-06-18 01:07:43 +00:00
6f0a455d0b scripts/check-uninsane: implement --verbose flag 2024-06-17 23:36:52 +00:00
7d6a420c52 sane-vpn: allow sane-vpn do -- [COMMAND] 2024-06-17 23:26:28 +00:00
259143b87e scripts/check-uninsane: fix so ssh servo systemctl --failed actually works on servo, even when ssh key is locked 2024-06-17 23:24:34 +00:00
fce426c318 servo: trust-dns: expose the hn DNS server on port 53
nothing i had was *expecting* it to be on port 1053, and it was just never working (?)
2024-06-17 23:16:00 +00:00
9b794777b5 servo: trust-dns: have the ovpns DNS provider return doof-based addresses instead of WAN-based addresses 2024-06-17 23:14:21 +00:00
3ada668366 servo: expose all wan services also to the doof tunnel 2024-06-17 23:08:08 +00:00
39a39e763d trust-dns: hack to substitute ANATIVE before anything else 2024-06-17 22:44:43 +00:00
50353280d3 servo: port ANATIVE over the doof interface to return the doof IP address 2024-06-17 22:37:50 +00:00
72b8211029 servo: switch ns2.uninsane.org from ovpns -> doof 2024-06-17 22:19:36 +00:00
dbf719b59b scripts/check-uninsane: fix the git.uninsane.org check to work even w/o access to SSH keys 2024-06-17 22:16:23 +00:00
57d7d3821f scripts/check-uninsane: dont rely on ovpns.uninsane.org bootstrap DNS: directly test the known IPv4 address 2024-06-17 22:12:34 +00:00
e86e9fc079 scripts/check-uninsane: add a check for DNS via doofnet 2024-06-17 22:11:02 +00:00
d708b78ebe scripts/check-uninsane: fix ftp check, to not error if README.md exists in the current directory 2024-06-17 22:10:47 +00:00
075418eda1 git: add alias git com to commit 2024-06-17 22:01:58 +00:00
9fc5b83b61 refactor: servo: hardcode OVPN-related IP addresses in far fewer places 2024-06-17 22:00:39 +00:00
4b99607f7b scripts/check-uninsane: annotate the OVPNS/DOOF checks 2024-06-17 09:25:10 +00:00
0d99293b2f servo: split the doof/ovpns netns config into its own module
a big thing this gets me is that the attributes (like IP addresses) are now accessible via 'config' an i won't have to hardcode them so much
2024-06-17 09:25:10 +00:00
b3890b82dc servo: http/https: expose to doof 2024-06-17 07:55:53 +00:00
3fc96a3e32 check-uninsane: also test http://uninsane.org, over OVPN connection 2024-06-17 07:50:15 +00:00
1af7b613bd servo: doof: respond to DNS queries 2024-06-17 07:39:52 +00:00
4c8695aae8 servo: fix missing route table for doof 2024-06-17 07:31:28 +00:00
d45e3fda5e servo: trust-dns: enable on doof-net 2024-06-17 07:20:23 +00:00
456e0de872 servo: doof net: add the capability to forward ports 2024-06-17 07:20:23 +00:00
7825ddc123 servo: split out a "bridgedWireguardNamespace" helper for configuring ovpns VPN
i can re-use this to forward traffic over doof
2024-06-17 07:20:23 +00:00
dd47a5083c servo: only forward ports to OVPN which are actually marked for visiblity 2024-06-17 06:29:09 +00:00
14d5d9eb5a servo: net: remove dead Hurricane Electric code 2024-06-17 06:04:29 +00:00
1f6f2399d6 nwg-panel: fix swaync icon 2024-06-16 06:35:32 +00:00
b0ee12ba7b modules/users: export HOME in environment.d because some services (nwg-panel) need it 2024-06-16 06:01:20 +00:00
a6d268ca72 nwg-panel: disable the brightness indicator 2024-06-16 05:42:58 +00:00
1ecc033ff5 nwg-panel: re-add missing style.css 2024-06-16 05:27:32 +00:00
c87dab93b3 scripts/deploy: allow specifying multiple hosts or multiple variants 2024-06-16 05:15:12 +00:00
53139a7cdf nwg-panel: address some TODOs 2024-06-16 04:59:23 +00:00
f37014a856 nwg-panel: minor tweaks & simplifications 2024-06-15 22:52:52 +00:00
0237d3a144 nwg-panel: fix broken JSON generation
heh, whoops
2024-06-15 22:24:41 +00:00
656ad76f25 nwg-panel/config: sort keys 2024-06-15 22:04:08 +00:00
b7c71dc67b nwg-panel: add a few comments/TODOs to the config 2024-06-15 21:56:41 +00:00
aaa40eae04 nwg-panel: port config to Nix
this makes it easier to plumb config into it, and also to comment it
2024-06-15 21:52:38 +00:00
d8ed82cfdf cross: remove upstreamed libvpx patch 2024-06-15 11:37:20 +00:00
0e73f95ab1 nixpkgs: 2024-06-14 -> 2024-06-15 2024-06-15 11:16:40 +00:00
b1ba0cad03 nixpkgs-wayland: minor bump 2024-06-15 11:16:32 +00:00
4bcbfbc8aa uassets: 2024-06-14 -> 2024-06-15 2024-06-15 11:16:16 +00:00
0f6c9f3cde sane-sysinfo: add a way to render memory use 2024-06-15 11:12:45 +00:00
f4d806c0c2 sane-sysinfo: handle the case of no battery 2024-06-15 10:35:32 +00:00
6963998519 refactor: sane-sysinfo: more cleanups 2024-06-15 10:34:39 +00:00
a63f6281c5 refactor: sane-sysinfo: clean up a bit more 2024-06-15 10:26:22 +00:00
df0a8cf900 refactor: sane-sysinfo: split out a BatteryInfo class 2024-06-15 09:46:58 +00:00
a4f5343fb5 sane-sysinfo: port to Python
it's a pretty literal port; probably has some bugs
2024-06-15 08:59:50 +00:00
c50a4d1d71 static-nix-shell: fix mkBash scripts to actually be invokable from the CLI
they need the `bash` package! how did this work before?
2024-06-15 07:42:04 +00:00
aadbeab3ac doc: nwg-panel: point out that it really is ok to build w/o wlr-randr 2024-06-15 06:53:38 +00:00
aafcf7b478 lift sane-battery-estimate out of conky, rename to sane-sysinfo 2024-06-15 06:52:54 +00:00
a78b840215 nwg-panel: enable per-app volume controls 2024-06-15 03:59:36 +00:00
3c2347faba nwg-panel: fixup the formatting
especially, make it fit on moby
2024-06-15 03:49:01 +00:00
ebff35a378 add missing sane-nix-files
hmm. not great that i could deploy even without this being checked into git....
2024-06-15 03:37:19 +00:00
1515f01384 zsh: add alias: :fg -> fg 2024-06-15 03:26:36 +00:00
60a5c61500 default.nix: pass through host config and fs 2024-06-15 03:18:16 +00:00
417b85450c tod.md: notes about nwg-panel cleanup 2024-06-15 00:54:01 +00:00
2e0a3dc8ef nwg-panel: fix cross-compiled result to not ship build-time dependencies 2024-06-15 00:52:31 +00:00
3165c95d0f sysvol: 2024-06-09 -> 2024-06-13 2024-06-15 00:28:03 +00:00
6dd4d9da3e uassets: 2024-06-12 -> 2024-06-14 2024-06-15 00:19:40 +00:00
5a086b359d nixpkgs-wayland: 2024-06-12 -> 2024-06-14 2024-06-15 00:19:25 +00:00
a204f0a987 nixpkgs: 2024-06-12 -> 2024-06-14 2024-06-15 00:18:41 +00:00
317251338c todo.md: note that s6 is not re-entrant 2024-06-14 20:26:30 +00:00
01cfed2438 scripts/deploy: swap the iteration order: build all hosts at -min variant, then -light, etc; then also do the -next variants 2024-06-14 20:24:50 +00:00
ba0524d193 scripts/update: dont update feeds by default 2024-06-14 18:29:06 +00:00
26a4f20f6c scripts/deploy: factor out a deployHelper to make variant=all usable *without* host=all 2024-06-14 18:28:52 +00:00
46f5a7e37d nwg-panel: patch it to cross compile (by purging bluetooth/randr) 2024-06-14 09:34:17 +00:00
88a487f565 /etc/nixos: link in such a way that i dont pick up a whole bunch of garbage
it seemed to also be causing some non-determinism when deploying to crappy

ideally i would seal the whole nix build, by only evaluating all this config *after* building 'sane-nix-files'
2024-06-14 09:18:15 +00:00
d037afd75c sane-nix-files: define this repo as a package
setup as a dirty git repo, intentionally
2024-06-14 09:18:15 +00:00
654858f8ff nwg-panel: theme the calendar 2024-06-14 09:17:46 +00:00
5abcc7d399 nwg-panel: fix @workspaceNumbers typo 2024-06-14 08:50:28 +00:00
65823507ad nwg-panel: make workspace numbers/hiding configurable 2024-06-14 08:47:24 +00:00
63a88da3b4 moby: switch from waybar -> nwg-panel 2024-06-14 08:47:24 +00:00
734da36639 nwg-panel: make configurable through nix 2024-06-14 08:47:24 +00:00
49ccf95fb3 nwg-panel: style.css: fix line endings?
idk, i just copied + pasted the contents back, and now the file is 200B smaller and i dont see ^M in git
2024-06-14 08:47:24 +00:00
e70d0f3c8e nwg-panel: style.css: fix indentation 2024-06-14 08:47:24 +00:00
c00cccd429 nwg-panel: disable the green border hover for *all* items 2024-06-14 08:47:24 +00:00
02fdc91237 sway: switch from waybar -> nwg-panel (except for moby) 2024-06-14 08:47:24 +00:00
14616f9b61 nwg-panel: stylize 2024-06-14 08:47:24 +00:00
f9d856b3bb waybar: fix typo 2024-06-14 08:47:24 +00:00
d52db06ffe nwg-panel: implement, but dont ship by default 2024-06-14 08:47:24 +00:00
Shelvacu
dc2c31f220 gitea: keep login session alive for 30 days 2024-06-14 03:34:42 +00:00
52322e3207 switchboard: fix cross compilation 2024-06-14 03:29:02 +00:00
26f1f2b581 remove unused flake.lock file 2024-06-14 03:08:07 +00:00
227 changed files with 4062 additions and 1203 deletions

22
TODO.md
View File

@ -6,6 +6,7 @@
- `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
- nor `m.wikipedia.org` (`dyna.wikipedia.org`)
- and *sometimes* apple.com fails
- sandbox: link cache means that if i update ~/.config/... files inline, sandboxed programs still see the old version
- mpv: audiocast has mpv sending its output to the builtin speakers unless manually changed
@ -15,7 +16,7 @@
- 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
- sysvol (volume overlay): when casting with `blast`, sysvol doesn't react to volume changes
- syshud (volume overlay): when casting with `blast`, syshud doesn't react to volume changes
- moby: kaslr is effectively disabled
- `dmesg | grep "KASLR disabled due to lack of seed"`
- fix by adding `kaslrseed` to uboot script before `booti`
@ -24,6 +25,13 @@
- moby: bpf is effectively disabled?
- `dmesg | grep 'systemd[1]: bpf-lsm: Failed to load BPF object: No such process'`
- `dmesg | grep 'hid_bpf: error while preloading HID BPF dispatcher: -22'`
- `s6` is not re-entrant
- so if the desktop crashes, the login process from `unl0kr` fails to re-launch the GUI
- swaync brightness slider does not work
- it reads brightness from /sys/class/backlight/....
- but to *set* the brightness it assumes systemd logind is running
<repo:ErikReider/SwayNotificationCenter:src/controlCenter/widgets/backlight/backlightUtil.vala>
no reason i can't just write to that file, or exec brightnessctl (if i learn vala)
## REFACTORING:
- add import checks to my Python nix-shell scripts
@ -84,12 +92,12 @@
### user experience
- rofi: sort items case-insensitively
- xdg-desktop-portal shouldn't kill children on exit
- *maybe* a job for `setsid -f`?
- replace starship prompt with something more efficient
- watch `forkstat`: it does way too much
- cleanup waybar so that it's not invoking playerctl every 2 seconds
- cleanup waybar/nwg-panel so that it's not invoking playerctl every 2 seconds
- nwg-panel: doesn't know that virtual-desktop 10/TV exists
- install apps:
- compass viewer (moby)
- display QR codes for WiFi endpoints: <https://linuxphoneapps.org/apps/noappid.wisperwind.wifi2qr/>
- shopping list (not in nixpkgs): <https://linuxphoneapps.org/apps/ro.hume.cosmin.shoppinglist/>
- offline Wikipedia (or, add to `wike`)
@ -119,13 +127,10 @@
- don't show MPRIS if no players detected
- this is a problem of playerctld, i guess
- add option to change audio output
- fix colors (red alert) to match overall theme
- moby: tune GPS
- run only geoclue, and not gpsd, to save power?
- tune QGPS setting in eg25-control, for less jitter?
- 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?
- manually do smoothing, as some layer between mepo and geoclue?
- 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
@ -152,6 +157,7 @@
- email: fix so that local mail doesn't go to junk
- git sendmail flow adds the DKIM signatures, but gets delivered locally w/o having the sig checked, so goes into Junk
- could change junk filter from "no DKIM success" to explicit "DKIM failed"
- add an auto-reply address (e.g. `reply-test@uninsane.org`) which reflects all incoming mail; use this (or a friend running this) for liveness checks
### perf
- debug nixos-rebuild times

View File

@ -1,62 +1,5 @@
# limited, non-flake interface to this repo.
# this file exposes the same view into `pkgs` which the flake would see when evaluated.
#
# the primary purpose of this file is so i can run `updateScript`s which expect
# the root to be `default.nix`
{ }:
{ ... }@args:
let
mkPkgs = args: (import ./pkgs/additional/nixpkgs args).extend
(import ./overlays/all.nix);
inherit (mkPkgs {}) lib;
evalHost = { name, system, branch ? "master", variant ? null }:
let
pkgs = mkPkgs { inherit system; variant = branch; };
in pkgs.nixos (
[
(lib.optionalAttrs (variant == "light") {
sane.maxBuildCost = 2;
})
(lib.optionalAttrs (variant == "min") {
sane.maxBuildCost = 0;
})
(import ./hosts/instantiate.nix { hostName = name; })
(import ./modules)
pkgs.sops-nix.nixosModules.sops
]
);
mkFlavoredHost = args: let
host = evalHost args;
# expose the toplevel nixos system as the toplevel attribute itself,
# with nested aliases for other common build targets
in host.config.system.build.toplevel.overrideAttrs (base: {
passthru = (base.passthru or {}) // {
img = host.config.system.build.img;
pkgs = host.config.system.build.pkgs;
programs = lib.mapAttrs (_: p: p.package) host.config.sane.programs;
toplevel = host.config.system.build.toplevel; #< self
};
});
mkHost = args: {
"${args.name}" = mkFlavoredHost args;
"${args.name}-next" = mkFlavoredHost args // { branch = "staging-next"; };
"${args.name}-staging" = mkFlavoredHost args // { branch = "staging"; };
"${args.name}-light" = mkFlavoredHost args // { variant = "light"; };
"${args.name}-light-next" = mkFlavoredHost args // { variant = "light"; branch = "staging-next"; };
"${args.name}-light-staging" = mkFlavoredHost args // { variant = "light"; branch = "staging"; };
"${args.name}-min" = mkFlavoredHost args // { variant = "min"; };
"${args.name}-min-next" = mkFlavoredHost args // { variant = "min"; branch = "staging-next"; };
"${args.name}-min-staging" = mkFlavoredHost args // { variant = "min"; branch = "staging-staging"; };
};
hosts = lib.foldl' (acc: host: acc // (mkHost host)) {} [
{ name = "crappy"; system = "armv7l-linux"; }
{ name = "desko"; system = "x86_64-linux"; }
{ name = "lappy"; system = "x86_64-linux"; }
{ name = "moby"; system = "aarch64-linux"; }
{ name = "rescue"; system = "x86_64-linux"; }
{ name = "servo"; system = "x86_64-linux"; }
];
in (mkPkgs {}) // {
inherit hosts;
}
sane-nix-files = import ./pkgs/additional/sane-nix-files { };
in
import "${sane-nix-files}/impure.nix" args

View File

@ -1,7 +0,0 @@
{
"nodes": {
"root": {}
},
"root": "root",
"version": 7
}

View File

@ -25,6 +25,7 @@
sane.programs.dino.config.autostart = false;
sane.programs.dissent.config.autostart = false;
sane.programs.fractal.config.autostart = false;
sane.programs.sway.config.mod = "Mod1"; #< alt key instead of Super
# sane.programs.guiApps.enableFor.user.colin = false;

View File

@ -35,6 +35,11 @@
sane.programs."gnome.geary".config.autostart = true;
sane.programs.signal-desktop.config.autostart = true;
sane.programs.nwg-panel.config = {
battery = false;
brightness = false;
};
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
# needed to use libimobiledevice/ifuse, for iphone sync

View File

@ -10,7 +10,6 @@
{
imports = [
./fs.nix
./gps.nix
];
sane.hal.pine64.enable = true;
@ -29,6 +28,7 @@
sops.secrets.colin-passwd.neededForUsers = true;
sane.programs.sway.enableFor.user.colin = true;
sane.programs.sway.config.mod = "Mod1"; #< alt key instead of Super
sane.programs.blueberry.enableFor.user.colin = false; # bluetooth manager: doesn't cross compile!
sane.programs.fcitx5.enableFor.user.colin = false; # does not cross compile
sane.programs.mercurial.enableFor.user.colin = false; # does not cross compile

View File

@ -1,68 +0,0 @@
# pinephone GPS happens in EG25 modem
# serial control interface to modem is /dev/ttyUSB2
# after enabling GPS, readout is /dev/ttyUSB1
#
# minimal process to enable modem and GPS:
# - `echo 1 > /sys/class/modem-power/modem-power/device/powered`
# - `screen /dev/ttyUSB2 115200`
# - `AT+QGPSCFG="nmeasrc",1`
# - `AT+QGPS=1`
# this process is automated by my `eg25-control` program and services (`eg25-control-powered`, `eg25-control-gps`)
# - see the `modules/` directory further up this repository.
#
# now, something like `gpsd` can directly read from /dev/ttyUSB1,
# or geoclue can query the GPS directly through modem-manager
#
# initial GPS fix can take 15+ minutes.
# meanwhile, services like eg25-manager or eg25-control-freshen-agps can speed this up by uploading assisted GPS data to the modem.
#
# support/help:
# - geoclue, gnome-maps
# - irc: #gnome-maps on irc.gimp.org
# - Matrix: #gnome-maps:gnome.org (unclear if bridged to IRC)
#
# programs to pair this with:
# - `satellite-gtk`: <https://codeberg.org/tpikonen/satellite>
# - shows/tracks which satellites the GPS is connected to; useful to understand fix characteristics
# - `gnome-maps`: uses geoclue, has route planning
# - `mepo`: uses gpsd, minimalist, flaky, and buttons are kinda hard to activate on mobile
# - puremaps?
# - osmin?
#
# known/outstanding bugs:
# - `systemctl start eg25-control-gps` can the hang the whole system (2023/10/06)
# - i think it's actually `eg25-control-powered` which does this (started by the gps)
# - best guess is modem draws so much power at launch that other parts of the system see undervoltage
# - workaround is to hard power-cycle the system. the modem may not bring up after reboot: leave unpowered for 60s and boot again.
#
# future work:
# - integrate with [wigle](https://www.wigle.net/) for offline equivalent to Mozilla Location Services
{ config, lib, ... }:
{
# test gpsd with `gpspipe -w -n 10 2> /dev/null | grep -m 1 TPV | jq '.lat, .lon' | tr '\n' ' '`
# ^ should return <lat> <long>
services.gpsd.enable = true;
services.gpsd.devices = [ "/dev/ttyUSB1" ];
# test geoclue2 by building `geoclue2-with-demo-agent`
# and running "${geoclue2-with-demo-agent}/libexec/geoclue-2.0/demos/where-am-i"
# note that geoclue is dbus-activated, and auto-stops after 60s with no caller
services.geoclue2.enable = true;
services.geoclue2.appConfig.where-am-i = {
# this is the default "agent", shipped by geoclue package: allow it to use location
isAllowed = true;
isSystem = false;
# XXX: setting users != [] might be causing `where-am-i` to time out
users = [
# restrict to only one set of users. empty array (default) means "allow any user to access geolocation".
(builtins.toString config.users.users.colin.uid)
];
};
systemd.services.geoclue.after = lib.mkForce []; #< defaults to network-online, but not all my sources require network
users.users.geoclue.extraGroups = [
"dialout" # TODO: figure out if dialout is required. that's for /dev/ttyUSB1, but geoclue probably doesn't read that?
];
sane.programs.where-am-i.enableFor.user.colin = true;
}

View File

@ -3,9 +3,19 @@
let
portOpts = with lib; types.submodule {
options = {
visibleTo.ovpn = mkOption {
visibleTo.ovpns = mkOption {
type = types.bool;
default = false;
description = ''
whether to forward inbound traffic on the OVPN vpn port to the corresponding localhost port.
'';
};
visibleTo.doof = mkOption {
type = types.bool;
default = false;
description = ''
whether to forward inbound traffic on the doofnet vpn port to the corresponding localhost port.
'';
};
};
};
@ -13,7 +23,7 @@ in
{
options = with lib; {
sane.ports.ports = mkOption {
# add the `visibleTo.ovpn` option
# add the `visibleTo.{doof,ovpns}` options
type = types.attrsOf portOpts;
};
};
@ -40,18 +50,16 @@ in
# tun-sea config
sane.dns.zones."uninsane.org".inet.A."doof.tunnel" = "205.201.63.12";
sane.dns.zones."uninsane.org".inet.AAAA."doof.tunnel" = "2602:fce8:106::51";
networking.wireguard.interfaces.wg-doof = let
ip = "${pkgs.iproute2}/bin/ip";
in {
# sane.dns.zones."uninsane.org".inet.AAAA."doof.tunnel" = "2602:fce8:106::51"; #< TODO: enable IPv6
networking.wireguard.interfaces.wg-doof = {
privateKeyFile = config.sops.secrets.wg_doof_privkey.path;
# wg is active only in this namespace.
# run e.g. ip netns exec doof <some command like ping/curl/etc, it'll go through wg>
# sudo ip netns exec doof ping www.google.com
interfaceNamespace = "doof";
ips = [
"205.201.63.12/32"
"2602:fce8:106::51/128"
"205.201.63.12"
# "2602:fce8:106::51/128" #< TODO: enable IPv6
];
peers = [
{
@ -63,45 +71,24 @@ in
persistentKeepalive = 25; #< keep the NAT alive
}
];
preSetup = ''
${ip} netns add doof || (test -e /run/netns/doof && echo "doof already exists")
'';
postShutdown = ''
${ip} netns delete doof || echo "couldn't delete doof"
'';
};
sane.netns.doof.hostVethIpv4 = "10.0.2.5";
sane.netns.doof.netnsVethIpv4 = "10.0.2.6";
sane.netns.doof.netnsPubIpv4 = "205.201.63.12";
sane.netns.doof.routeTable = 12;
# OVPN CONFIG (https://www.ovpn.com):
# DOCS: https://nixos.wiki/wiki/WireGuard
# if you `systemctl restart wireguard-wg-ovpns`, make sure to also restart any other services in `NetworkNamespacePath = .../ovpns`.
# TODO: why not create the namespace as a seperate operation (nix config for that?)
networking.wireguard.enable = true;
networking.wireguard.interfaces.wg-ovpns = let
ip = "${pkgs.iproute2}/bin/ip";
in-ns = "${ip} netns exec ovpns";
iptables = "${pkgs.iptables}/bin/iptables";
veth-host-ip = "10.0.1.5";
veth-local-ip = "10.0.1.6";
vpn-ip = "185.157.162.178";
# DNS = 46.227.67.134, 192.165.9.158, 2a07:a880:4601:10f0:cd45::1, 2001:67c:750:1:cafe:cd45::1
vpn-dns = "46.227.67.134";
bridgePort = port: proto: ''
${in-ns} ${iptables} -A PREROUTING -t nat -p ${proto} --dport ${port} -m iprange --dst-range ${vpn-ip} \
-j DNAT --to-destination ${veth-host-ip}
'';
bridgeStatements = lib.foldlAttrs
(acc: port: portCfg: acc ++ (builtins.map (bridgePort port) portCfg.protocol))
[]
config.sane.ports.ports;
in {
networking.wireguard.interfaces.wg-ovpns = {
privateKeyFile = config.sops.secrets.wg_ovpns_privkey.path;
# wg is active only in this namespace.
# run e.g. ip netns exec ovpns <some command like ping/curl/etc, it'll go through wg>
# sudo ip netns exec ovpns ping www.google.com
interfaceNamespace = "ovpns";
ips = [
"185.157.162.178/32"
];
ips = [ "185.157.162.178" ];
peers = [
{
publicKey = "SkkEZDCBde22KTs/Hc7FWvDBfdOCQA4YtBEuC3n5KGs=";
@ -119,99 +106,11 @@ in
# dynamicEndpointRefreshRestartSeconds = 5;
}
];
preSetup = ''
${ip} netns add ovpns || (test -e /run/netns/ovpns && echo "ovpns already exists")
'';
postShutdown = ''
${in-ns} ip link del ovpns-veth-b || echo "couldn't delete ovpns-veth-b"
${ip} link del ovpns-veth-a || echo "couldn't delete ovpns-veth-a"
${ip} netns delete ovpns || echo "couldn't delete ovpns"
# restore rules/routes
${ip} rule del from ${veth-host-ip} lookup ovpns pref 50 || echo "couldn't delete init -> ovpns rule"
${ip} route del default via ${veth-local-ip} dev ovpns-veth-a proto kernel src ${veth-host-ip} metric 1002 table ovpns || echo "couldn't delete init -> ovpns route"
${ip} rule add from all lookup local pref 0
${ip} rule del from all lookup local pref 100
'';
postSetup = ''
# DOCS:
# - some of this approach is described here: <https://josephmuia.ca/2018-05-16-net-namespaces-veth-nat/>
# - iptables primer: <https://danielmiessler.com/study/iptables/>
# create veth pair
${ip} link add ovpns-veth-a type veth peer name ovpns-veth-b
${ip} addr add ${veth-host-ip}/24 dev ovpns-veth-a
${ip} link set ovpns-veth-a up
# mv veth-b into the ovpns namespace
${ip} link set ovpns-veth-b netns ovpns
${in-ns} ip addr add ${veth-local-ip}/24 dev ovpns-veth-b
${in-ns} ip link set ovpns-veth-b up
# make it so traffic originating from the host side of the veth
# is sent over the veth no matter its destination.
${ip} rule add from ${veth-host-ip} lookup ovpns pref 50
# for traffic originating at the host veth to the WAN, use the veth as our gateway
# not sure if the metric 1002 matters.
${ip} route add default via ${veth-local-ip} dev ovpns-veth-a proto kernel src ${veth-host-ip} metric 1002 table ovpns
# give the default route lower priority
${ip} rule add from all lookup local pref 100
${ip} rule del from all lookup local pref 0
# in order to access DNS in this netns, we need to route it to the VPN's nameservers
# - alternatively, we could fix DNS servers like 1.1.1.1.
${in-ns} ${iptables} -A OUTPUT -t nat -p udp --dport 53 -m iprange --dst-range 127.0.0.53 \
-j DNAT --to-destination ${vpn-dns}:53
'' + (lib.concatStringsSep "\n" bridgeStatements);
};
# create a new routing table that we can use to proxy traffic out of the root namespace
# through the ovpns namespace, and to the WAN via VPN.
networking.iproute2.rttablesExtraConfig = ''
5 ovpns
'';
networking.iproute2.enable = true;
# HURRICANE ELECTRIC CONFIG:
# networking.sits = {
# hurricane = {
# remote = "216.218.226.238";
# local = "192.168.0.5";
# # local = "10.0.0.5";
# # remote = "10.0.0.1";
# # local = "10.0.0.22";
# dev = "eth0";
# ttl = 255;
# };
# };
# networking.interfaces."hurricane".ipv6 = {
# addresses = [
# # mx.uninsane.org (publically routed /64)
# {
# address = "2001:470:b:465::1";
# prefixLength = 128;
# }
# # client addr
# # {
# # address = "2001:470:a:466::2";
# # prefixLength = 64;
# # }
# ];
# routes = [
# {
# address = "::";
# prefixLength = 0;
# # via = "2001:470:a:466::1";
# }
# ];
# };
# # after configuration, we want the hurricane device to look like this:
# # hurricane: flags=209<UP,POINTOPOINT,RUNNING,NOARP> mtu 1480
# # inet6 2001:470:a:450::2 prefixlen 64 scopeid 0x0<global>
# # inet6 fe80::c0a8:16 prefixlen 64 scopeid 0x20<link>
# # sit txqueuelen 1000 (IPv6-in-IPv4)
# # test with:
# # curl --interface hurricane http://[2607:f8b0:400a:80b::2004]
# # ping 2607:f8b0:400a:80b::2004
sane.netns.ovpns.hostVethIpv4 = "10.0.1.5";
sane.netns.ovpns.netnsVethIpv4 = "10.0.1.6";
sane.netns.ovpns.netnsPubIpv4 = "185.157.162.178";
sane.netns.ovpns.routeTable = 11;
sane.netns.ovpns.dns = "46.227.67.134"; #< DNS requests inside the namespace are forwarded here
};
}

View File

@ -36,7 +36,8 @@
# - rb = received bytes
# - sp = sent packets
# - sb = sent bytes
{ lib, ... }:
{ config, lib, ... }:
let
# TURN port range (inclusive).
# default coturn behavior is to use the upper quarter of all ports. i.e. 49152 - 65535.
@ -55,7 +56,7 @@ in
# protocol = [ "tcp" "udp" ];
# # visibleTo.lan = true;
# # visibleTo.wan = true;
# visibleTo.ovpn = true; # forward traffic from the VPN to the root NS
# visibleTo.ovpns = true; # forward traffic from the VPN to the root NS
# description = "colin-stun-turn";
# };
# "5349" = {
@ -63,7 +64,7 @@ in
# protocol = [ "tcp" ];
# # visibleTo.lan = true;
# # visibleTo.wan = true;
# visibleTo.ovpn = true;
# visibleTo.ovpns = true;
# description = "colin-stun-turn-over-tls";
# };
# }
@ -76,7 +77,7 @@ in
# protocol = [ "tcp" "udp" ];
# # visibleTo.lan = true;
# # visibleTo.wan = true;
# visibleTo.ovpn = true;
# visibleTo.ovpns = true;
# description = "colin-turn-${builtins.toString count}-of-${builtins.toString numPorts}";
# };
# })
@ -130,11 +131,11 @@ in
"verbose"
# "Verbose" #< even MORE verbosity than "verbose" (it's TOO MUCH verbosity really)
"no-multicast-peers" # disables sending to IPv4 broadcast addresses (e.g. 224.0.0.0/3)
# "listening-ip=10.0.1.5" "external-ip=185.157.162.178" #< 2024/04/25: works, if running in root namespace
"listening-ip=185.157.162.178" "external-ip=185.157.162.178"
# "listening-ip=${config.sane.netns.ovpns.hostVethIpv4}" "external-ip=${config.sane.netns.ovpns.netnsPubIpv4}" #< 2024/04/25: works, if running in root namespace
"listening-ip=${config.sane.netns.ovpns.netnsPubIpv4}" "external-ip=${config.sane.netns.ovpns.netnsPubIpv4}"
# old attempts:
# "external-ip=185.157.162.178/10.0.1.5"
# "external-ip=${config.sane.netns.ovpns.netnsPubIpv4}/${config.sane.netns.ovpns.hostVethIpv4}"
# "listening-ip=10.78.79.51" # can be specified multiple times; omit for *
# "external-ip=97.113.128.229/10.78.79.51"
# "external-ip=97.113.128.229"

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.pyln-client ])"
#!nix-shell -i python3 -p pyln-client -p python3
"""
clightning-sane: helper to perform common Lightning node admin operations:

View File

@ -26,7 +26,7 @@
./postgres.nix
./prosody
./slskd.nix
./transmission.nix
./transmission
./trust-dns.nix
./wikipedia.nix
];

View File

@ -51,54 +51,54 @@ lib.mkIf false
{
"3478" = {
protocol = [ "tcp" "udp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-stun-turn";
};
"5222" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-client-to-server";
};
"5223" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpps-client-to-server"; # XMPP over TLS
};
"5269" = {
protocol = [ "tcp" ];
visibleTo.wan = true;
visibleTo.doof = true;
description = "colin-xmpp-server-to-server";
};
"5270" = {
protocol = [ "tcp" ];
visibleTo.wan = true;
visibleTo.doof = true;
description = "colin-xmpps-server-to-server"; # XMPP over TLS
};
"5280" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-bosh";
};
"5281" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-bosh-https";
};
"5349" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-stun-turn-over-tls";
};
"5443" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-web-services"; # file uploads, websockets, admin
};
}
@ -109,8 +109,8 @@ lib.mkIf false
numPorts = turnPortHigh - turnPortLow + 1;
in {
protocol = [ "tcp" "udp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-turn-${builtins.toString count}-of-${builtins.toString numPorts}";
};
})

View File

@ -8,14 +8,14 @@
{
sane.ports.ports."143" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-imap-imap.uninsane.org";
};
sane.ports.ports."993" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-imaps-imap.uninsane.org";
};

View File

@ -1,6 +1,6 @@
# postfix config options: <https://www.postfix.org/postconf.5.html>
{ lib, pkgs, ... }:
{ config, lib, pkgs, ... }:
let
submissionOptions = {
@ -56,8 +56,7 @@ in
sane.dns.zones."uninsane.org".inet = {
MX."@" = "10 mx.uninsane.org.";
# XXX: RFC's specify that the MX record CANNOT BE A CNAME
A."mx" = "185.157.162.178";
A."mx" = "%AOVPNS%"; #< XXX: RFC's specify that the MX record CANNOT BE A CNAME. TODO: use "%AOVPNS%?
# Sender Policy Framework:
# +mx => mail passes if it originated from the MX

View File

@ -12,6 +12,10 @@
device = "/var/media";
options = [ "rbind" ];
};
fileSystems."/var/export/pub" = {
device = "/var/www/sites/uninsane.org/share";
options = [ "rbind" ];
};
# fileSystems."/var/export/playground" = {
# device = config.fileSystems."/mnt/persist/ext".device;
# fsType = "btrfs";
@ -37,7 +41,8 @@
wantedBy = [ "nfs.service" "sftpgo.service" ];
file.text = ''
- media/ read-only: Videos, Music, Books, etc
- playground/ read-write: use it to share files with other users of this server
- playground/ read-write: use it to share files with other users of this server, inaccessible from the www
- pub/ read-only: content made to be shared with the www
'';
};

View File

@ -9,10 +9,10 @@
{ config, lib, pkgs, sane-lib, ... }:
let
external_auth_hook = pkgs.static-nix-shell.mkPython3Bin {
external_auth_hook = pkgs.static-nix-shell.mkPython3 {
pname = "external_auth_hook";
srcRoot = ./.;
pyPkgs = [ "passlib" ];
pkgs = [ "python3.pkgs.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
@ -27,13 +27,12 @@ in
"21" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
# visibleTo.wan = true;
description = "colin-FTP server";
};
"990" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-FTPS server";
};
} // (sane-lib.mapToAttrs
@ -41,8 +40,8 @@ in
name = builtins.toString port;
value = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-FTP server data port range";
};
})
@ -101,6 +100,13 @@ in
debug = true;
tls_mode = 2; # 2 = "implicit FTPS": client negotiates TLS before any FTP command.
}
{
# binding this means any doof client can connect (TLS only)
address = config.sane.netns.doof.hostVethIpv4;
port = 990;
debug = true;
tls_mode = 2; # 2 = "implicit FTPS": client negotiates TLS before any FTP command.
}
];
# active mode is susceptible to "bounce attacks", without much benefit over passive mode
@ -117,7 +123,7 @@ in
banner = ''
Welcome, friends, to Colin's FTP server! Also available via NFS on the same host, but LAN-only.
Read-only access (LAN-restricted):
Read-only access (LAN clients see everything; WAN clients can only see /pub):
Username: "anonymous"
Password: "anonymous"

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ps.passlib ])"
#!nix-shell -i python3 -p python3 -p python3.pkgs.passlib
# vim: set filetype=python :
#
# available environment variables:
@ -45,6 +45,8 @@ from hmac import compare_digest
authFail = dict(username="")
PERM_DENY = []
PERM_LIST = [ "list" ]
PERM_RO = [ "list", "download" ]
PERM_RW = [
# read-only:
@ -127,12 +129,14 @@ def getAuthResponse(ip: str, username: str, password: str) -> dict:
return mkAuthOk(username, permissions = {
"/": PERM_RW,
"/playground": PERM_RW,
"/pub": PERM_RO,
})
if isWireguard(ip):
# allow any user from wireguard
return mkAuthOk(username, permissions = {
"/": PERM_RW,
"/playground": PERM_RW,
"/pub": PERM_RO,
})
if isLan(ip):
if username == "anonymous":
@ -140,7 +144,19 @@ def getAuthResponse(ip: str, username: str, password: str) -> dict:
return mkAuthOk("anonymous", permissions = {
"/": PERM_RO,
"/playground": PERM_RW,
"/pub": PERM_RO,
})
if username == "anonymous":
# anonymous users from the www can have even more limited access.
# mostly because i need an easy way to test WAN connectivity :-)
return mkAuthOk("anonymous", permissions = {
# "/": PERM_DENY,
"/": PERM_LIST, #< REQUIRED, even for lftp to list a subdir
"/media": PERM_DENY,
"/playground": PERM_DENY,
"/pub": PERM_RO,
# "/README.md": PERM_RO, #< does not work
})
return authFail

View File

@ -50,7 +50,11 @@
ENABLE_CAPTCHA = true;
NOREPLY_ADDRESS = "noreply.anonymous.git@uninsane.org";
};
session.COOKIE_SECURE = true;
session = {
COOKIE_SECURE = true;
# keep me logged in for 30 days
SESSION_LIFE_TIME = 60 * 60 * 24 * 30;
};
repository = {
DEFAULT_BRANCH = "master";
ENABLE_PUSH_CREATE_USER = true;
@ -129,7 +133,7 @@
sane.ports.ports."22" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
visibleTo.doof = true;
description = "colin-git@git.uninsane.org";
};
}

View File

@ -1,6 +1,5 @@
{ lib, pkgs, ... }:
{ config, lib, pkgs, ... }:
lib.mkIf false #< TODO: re-enable once confident of sandboxing
{
sane.persist.sys.byStore.plaintext = [
# TODO: mode? we only need this to save Indexer creds ==> migrate to config?
@ -13,7 +12,7 @@ lib.mkIf false #< TODO: re-enable once confident of sandboxing
systemd.services.jackett.serviceConfig = {
# run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns";
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect 185.157.162.178" ]; # abort if public IP is not as expected
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect ${config.sane.netns.ovpns.netnsPubIpv4}" ]; # abort if public IP is not as expected
# patch jackett to listen on the public interfaces
# ExecStart = lib.mkForce "${pkgs.jackett}/bin/Jackett --NoUpdates --DataFolder /var/lib/jackett/.config/Jackett --ListenPublic";
@ -25,8 +24,7 @@ lib.mkIf false #< TODO: re-enable once confident of sandboxing
enableACME = true;
# inherit kTLS;
locations."/" = {
# proxyPass = "http://ovpns.uninsane.org:9117";
proxyPass = "http://10.0.1.6:9117";
proxyPass = "http://${config.sane.netns.ovpns.netnsVethIpv4}:9117";
recommendedProxySettings = true;
};
};

View File

@ -4,12 +4,11 @@
{ config, lib, ... }:
let
ircServer = { name, additionalAddresses ? [], sasl ? true, port ? 6697 }: let
ircServer = { name, additionalAddresses ? [], ssl ? true, sasl ? true, port ? if ssl then 6697 else 6667 }: let
lowerName = lib.toLower name;
in {
# XXX sasl: appservice doesn't support NickServ identification (only SASL, or PASS if sasl = false)
inherit name additionalAddresses sasl port;
ssl = true;
inherit additionalAddresses name port sasl ssl;
botConfig = {
# bot has no presence in IRC channel; only real Matrix users
enabled = false;
@ -156,6 +155,10 @@ in
# - #sxmo-offtopic
};
"irc.rizon.net" = ircServer { name = "Rizon"; };
"wigle.net" = ircServer {
name = "WiGLE";
ssl = false;
};
};
};
};

View File

@ -17,14 +17,14 @@ in
sane.ports.ports."80" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
visibleTo.ovpn = true; # so that letsencrypt can procure a cert for the mx record
visibleTo.ovpns = true; # so that letsencrypt can procure a cert for the mx record
visibleTo.doof = true;
description = "colin-http-uninsane.org";
};
sane.ports.ports."443" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
visibleTo.doof = true;
description = "colin-https-uninsane.org";
};

View File

@ -86,7 +86,7 @@ in
sane.ports.ports."${builtins.toString altPort}" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
visibleTo.doof = true;
description = "colin-ntfy.uninsane.org";
};
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])" -p ntfy-sh
#!nix-shell -i python3 -p ntfy-sh -p python3
import argparse
import logging

View File

@ -47,7 +47,7 @@ in
};
sane.ntfy-waiter.package = mkOption {
type = types.package;
default = pkgs.static-nix-shell.mkPython3Bin {
default = pkgs.static-nix-shell.mkPython3 {
pname = "ntfy-waiter";
srcRoot = ./.;
pkgs = [ "ntfy-sh" ];
@ -62,8 +62,8 @@ in
sane.ports.ports = lib.mkMerge (lib.forEach portRange (port: {
"${builtins.toString port}" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-notification-waiter-${builtins.toString (port - portLow + 1)}-of-${builtins.toString numPorts}";
};
}));

View File

@ -61,42 +61,42 @@ in
];
sane.ports.ports."5000" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-prosody-fileshare-proxy65";
};
sane.ports.ports."5222" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-client-to-server";
};
sane.ports.ports."5223" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpps-client-to-server"; # XMPP over TLS
};
sane.ports.ports."5269" = {
protocol = [ "tcp" ];
visibleTo.wan = true;
visibleTo.doof = true;
description = "colin-xmpp-server-to-server";
};
sane.ports.ports."5270" = {
protocol = [ "tcp" ];
visibleTo.wan = true;
visibleTo.doof = true;
description = "colin-xmpps-server-to-server"; # XMPP over TLS
};
sane.ports.ports."5280" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-bosh";
};
sane.ports.ports."5281" = {
protocol = [ "tcp" ];
visibleTo.doof = true;
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-prosody-https"; # necessary?
};

View File

@ -22,8 +22,7 @@
sane.ports.ports."50300" = {
protocol = [ "tcp" ];
# not visible to WAN: i run this in a separate netns
visibleTo.ovpn = true;
# visibleTo.ovpns = true; #< not needed: it runs in the ovpns namespace
description = "colin-soulseek";
};
@ -33,7 +32,7 @@
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://10.0.1.6:5030";
proxyPass = "http://${config.sane.netns.ovpns.netnsVethIpv4}:5030";
proxyWebsockets = true;
};
};
@ -72,7 +71,7 @@
systemd.services.slskd.serviceConfig = {
# run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns";
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect 185.157.162.178" ]; # abort if public IP is not as expected
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect ${config.sane.netns.ovpns.netnsPubIpv4}" ]; # abort if public IP is not as expected
Restart = lib.mkForce "always"; # exits "success" when it fails to connect to soulseek server
RestartSec = "60s";

View File

@ -22,67 +22,19 @@ let
--replace-fail 'set(TR_USER_AGENT_PREFIX "''${TR_SEMVER}")' 'set(TR_USER_AGENT_PREFIX "3.00")'
'';
});
download-dir = "/var/media/torrents";
torrent-done = pkgs.writeShellApplication {
name = "torrent-done";
runtimeInputs = with pkgs; [
acl
coreutils
findutils
rsync
util-linux
download-dir = "/var/media/torrents"; #< keep in sync with consts embedded in `torrent-done`
torrent-done = pkgs.static-nix-shell.mkBash {
pname = "torrent-done";
srcRoot = ./.;
pkgs = [
"acl"
"coreutils"
"findutils"
"rsync"
"util-linux"
];
text = ''
destructive() {
if [ -n "''${TR_DRY_RUN-}" ]; then
echo "$*"
else
"$@"
fi
}
if [[ "$TR_TORRENT_DIR" =~ ^.*freeleech.*$ ]]; then
# freeleech torrents have no place in my permanent library
echo "freeleech: nothing to do"
exit 0
fi
if ! [[ "$TR_TORRENT_DIR" =~ ^${download-dir}/.*$ ]]; then
echo "unexpected torrent dir, aborting: $TR_TORRENT_DIR"
exit 0
fi
REL_DIR="''${TR_TORRENT_DIR#${download-dir}/}"
MEDIA_DIR="/var/media/$REL_DIR"
destructive mkdir -p "$(dirname "$MEDIA_DIR")"
destructive rsync -arv "$TR_TORRENT_DIR/" "$MEDIA_DIR/"
# make the media rwx by anyone in the group
destructive find "$MEDIA_DIR" -type d -exec setfacl --recursive --modify d:g::rwx,o::rx {} \;
destructive find "$MEDIA_DIR" -type d -exec chmod g+rw,a+rx {} \;
# if there's a single directory inside the media dir, then inline that
subdirs=("$MEDIA_DIR"/*)
if [ ''${#subdirs} -eq 1 ]; then
dirname="''${subdirs[0]}"
if [ -d "$dirname" ]; then
mv "$dirname"/* "$MEDIA_DIR/" && rmdir "$dirname"
fi
fi
# remove noisy files:
find "$MEDIA_DIR/" -type f \(\
-iname 'www.YTS.*.jpg' \
-o -iname 'WWW.YIFY*.COM.jpg' \
-o -iname 'YIFY*.com.txt' \
-o -iname 'YTS*.com.txt' \
\) -exec rm {} \;
# dedupe the whole media library.
# yeah, a bit excessive: move this to a cron job if that's problematic.
destructive hardlink /var/media --reflink=always --ignore-time --verbose
'';
};
in
lib.mkIf false #< TODO: re-enable once confident of sandboxing
{
sane.persist.sys.byStore.plaintext = [
# TODO: mode? we need this specifically for the stats tracking in .config/
@ -106,8 +58,8 @@ lib.mkIf false #< TODO: re-enable once confident of sandboxing
# DOCUMENTATION/options list: <https://github.com/transmission/transmission/blob/main/docs/Editing-Configuration-Files.md#options>
# message-level = 3; #< enable for debug logging. 0-3, default is 2.
# 10.0.1.6 => allow rpc only from the root servo ns. it'll tunnel things to the net, if need be.
rpc-bind-address = "10.0.1.6";
# ovpns.netnsVethIpv4 => allow rpc only from the root servo ns. it'll tunnel things to the net, if need be.
rpc-bind-address = config.sane.netns.ovpns.netnsVethIpv4;
#rpc-host-whitelist = "bt.uninsane.org";
#rpc-whitelist = "*.*.*.*";
rpc-authentication-required = true;
@ -118,7 +70,7 @@ lib.mkIf false #< TODO: re-enable once confident of sandboxing
rpc-whitelist-enabled = false;
# force behind ovpns in case the NetworkNamespace fails somehow
bind-address-ipv4 = "185.157.162.178";
bind-address-ipv4 = config.sane.netns.ovpns.netnsPubIpv4;
port-forwarding-enabled = false;
# hopefully, make the downloads world-readable
@ -160,7 +112,7 @@ lib.mkIf false #< TODO: re-enable once confident of sandboxing
systemd.services.transmission.serviceConfig = {
# run this behind the OVPN static VPN
NetworkNamespacePath = "/run/netns/ovpns";
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect 185.157.162.178" ]; # abort if public IP is not as expected
ExecStartPre = [ "${lib.getExe pkgs.sane-scripts.ip-check} --no-upnp --expect ${config.sane.netns.ovpns.netnsPubIpv4}" ]; # abort if public IP is not as expected
Restart = "on-failure";
RestartSec = "30s";
@ -190,14 +142,14 @@ lib.mkIf false #< TODO: re-enable once confident of sandboxing
# inherit kTLS;
locations."/" = {
# proxyPass = "http://ovpns.uninsane.org:9091";
proxyPass = "http://10.0.1.6:9091";
proxyPass = "http://${config.sane.netns.ovpns.netnsVethIpv4}:9091";
};
};
sane.dns.zones."uninsane.org".inet.CNAME."bt" = "native";
sane.ports.ports."51413" = {
protocol = [ "tcp" "udp" ];
visibleTo.ovpn = true;
# visibleTo.ovpns = true; #< not needed: it runs in the ovpns namespace
description = "colin-bittorrent";
};
}

View File

@ -0,0 +1,76 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p acl -p bash -p coreutils -p findutils -p rsync -p util-linux
# transmission invokes this with no args, and the following env vars:
# - TR_TORRENT_DIR: full path to the folder i told transmission to download it to.
# e.g. /var/media/torrents/Videos/Film/Jason.Bourne-2016
# optionally:
# - TR_DRY_RUN=1
# - TR_DEBUG=1
# - TR_NO_HARDLINK=1
DOWNLOAD_DIR=/var/media/torrents
destructive() {
if [ -n "${TR_DRY_RUN-}" ]; then
echo "[dry-run] $*"
else
debug "$@"
"$@"
fi
}
debug() {
if [ -n "${TR_DEBUG-}" ]; then
echo "$@"
fi
}
echo "TR_TORRENT_DIR=$TR_TORRENT_DIR torrent-done $*"
if [[ "$TR_TORRENT_DIR" =~ ^.*freeleech.*$ ]]; then
# freeleech torrents have no place in my permanent library
echo "freeleech: nothing to do"
exit 0
fi
if ! [[ "$TR_TORRENT_DIR" =~ ^$DOWNLOAD_DIR/.*$ ]]; then
echo "unexpected torrent dir, aborting: $TR_TORRENT_DIR"
exit 0
fi
REL_DIR="${TR_TORRENT_DIR#$DOWNLOAD_DIR/}"
MEDIA_DIR="/var/media/$REL_DIR"
destructive mkdir -p "$(dirname "$MEDIA_DIR")"
destructive rsync -arv "$TR_TORRENT_DIR/" "$MEDIA_DIR/"
# make the media rwx by anyone in the group
destructive find "$MEDIA_DIR" -type d -exec setfacl --recursive --modify d:g::rwx,o::rx {} \;
destructive find "$MEDIA_DIR" -type d -exec chmod g+rw,a+rx {} \;
# if there's a single directory inside the media dir, then inline that
subdirs=("$MEDIA_DIR"/*)
debug "top-level items in torrent dir:" "${subdirs[@]}"
if [ ${#subdirs[@]} -eq 1 ]; then
dirname="${subdirs[0]}"
debug "exactly one top-level item, checking if directory: $dirname"
if [ -d "$dirname" ]; then
destructive mv "$dirname"/* "$MEDIA_DIR/" && destructive rmdir "$dirname"
fi
fi
# remove noisy files:
destructive find "$MEDIA_DIR/" -type f \(\
-iname '.*downloaded.?from.*' \
-o -iname 'source.txt' \
-o -iname 'upcoming.?releases.*' \
-o -iname 'www.YTS.*.jpg' \
-o -iname 'WWW.YIFY*.COM.jpg' \
-o -iname 'YIFY*.com.txt' \
-o -iname 'YTS*.com.txt' \
\) -exec rm {} \;
if ! [ -n "${TR_NO_HARDLINK}" ]; then
# dedupe the whole media library.
# yeah, a bit excessive: move this to a cron job if that's problematic
# or make it run with only 1/N probability, etc.
destructive hardlink /var/media --reflink=always --ignore-time --verbose
fi

View File

@ -4,14 +4,14 @@
let
dyn-dns = config.sane.services.dyn-dns;
nativeAddrs = lib.mapAttrs (_name: builtins.head) config.sane.dns.zones."uninsane.org".inet.A;
bindOvpn = "10.0.1.5";
in
{
sane.ports.ports."53" = {
protocol = [ "udp" "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
visibleTo.ovpn = true;
# visibleTo.wan = true;
visibleTo.ovpns = true;
visibleTo.doof = true;
description = "colin-dns-hosting";
};
@ -39,6 +39,7 @@ in
CNAME."native" = "%CNAMENATIVE%";
A."@" = "%ANATIVE%";
A."servo.wan" = "%AWAN%";
A."servo.doof" = "%ADOOF%";
A."servo.lan" = config.sane.hosts.by-name."servo".lan-ip;
A."servo.hn" = config.sane.hosts.by-name."servo".wg-home.ip;
@ -46,9 +47,9 @@ in
# it's best that we keep this identical, or a superset of, what org. lists as our NS.
# so, org. can specify ns2/ns3 as being to the VPN, with no mention of ns1. we provide ns1 here.
A."ns1" = "%ANATIVE%";
A."ns2" = "185.157.162.178";
A."ns3" = "185.157.162.178";
A."ovpns" = "185.157.162.178";
A."ns2" = "%ADOOF%";
A."ns3" = "%AOVPNS%";
A."ovpns" = "%AOVPNS%";
NS."@" = [
"ns1.uninsane.org."
"ns2.uninsane.org."
@ -59,58 +60,64 @@ in
services.trust-dns.settings.zones = [ "uninsane.org" ];
networking.nat.enable = true;
networking.nat.extraCommands = ''
# redirect incoming DNS requests from LAN addresses
# to the LAN-specialized DNS service
# N.B.: use the `nixos-*` chains instead of e.g. PREROUTING
# because they get cleanly reset across activations or `systemctl restart firewall`
# instead of accumulating cruft
iptables -t nat -A nixos-nat-pre -p udp --dport 53 \
-m iprange --src-range 10.78.76.0-10.78.79.255 \
-j DNAT --to-destination :1053
iptables -t nat -A nixos-nat-pre -p tcp --dport 53 \
-m iprange --src-range 10.78.76.0-10.78.79.255 \
-j DNAT --to-destination :1053
'';
sane.ports.ports."1053" = {
# because the NAT above redirects in nixos-nat-pre, LAN requests behave as though they arrived on the external interface at the redirected port.
# TODO: try nixos-nat-post instead?
# TODO: or, don't NAT from port 53 -> port 1053, but rather nat from LAN addr to a loopback addr.
# - this is complicated in that loopback is a different interface than eth0, so rewriting the destination address would cause the packets to just be dropped by the interface
protocol = [ "udp" "tcp" ];
visibleTo.lan = true;
description = "colin-redirected-dns-for-lan-namespace";
};
networking.nat.enable = true; #< TODO: try removing this?
# networking.nat.extraCommands = ''
# # redirect incoming DNS requests from LAN addresses
# # to the LAN-specialized DNS service
# # N.B.: use the `nixos-*` chains instead of e.g. PREROUTING
# # because they get cleanly reset across activations or `systemctl restart firewall`
# # instead of accumulating cruft
# iptables -t nat -A nixos-nat-pre -p udp --dport 53 \
# -m iprange --src-range 10.78.76.0-10.78.79.255 \
# -j DNAT --to-destination :1053
# iptables -t nat -A nixos-nat-pre -p tcp --dport 53 \
# -m iprange --src-range 10.78.76.0-10.78.79.255 \
# -j DNAT --to-destination :1053
# '';
# sane.ports.ports."1053" = {
# # because the NAT above redirects in nixos-nat-pre, LAN requests behave as though they arrived on the external interface at the redirected port.
# # TODO: try nixos-nat-post instead?
# # TODO: or, don't NAT from port 53 -> port 1053, but rather nat from LAN addr to a loopback addr.
# # - this is complicated in that loopback is a different interface than eth0, so rewriting the destination address would cause the packets to just be dropped by the interface
# protocol = [ "udp" "tcp" ];
# visibleTo.lan = true;
# description = "colin-redirected-dns-for-lan-namespace";
# };
sane.services.trust-dns.enable = true;
sane.services.trust-dns.instances = let
mkSubstitutions = flavor: {
"%ADOOF%" = config.sane.netns.doof.netnsPubIpv4;
"%ANATIVE%" = nativeAddrs."servo.${flavor}";
"%AOVPNS%" = config.sane.netns.ovpns.netnsPubIpv4;
"%AWAN%" = "$(cat '${dyn-dns.ipPath}')";
"%CNAMENATIVE%" = "servo.${flavor}";
"%ANATIVE%" = nativeAddrs."servo.${flavor}";
"%AOVPNS%" = "185.157.162.178";
};
in
{
wan = {
substitutions = mkSubstitutions "wan";
doof = {
substitutions = mkSubstitutions "doof";
listenAddrsIpv4 = [
nativeAddrs."servo.lan"
bindOvpn
config.sane.netns.doof.hostVethIpv4
config.sane.netns.ovpns.hostVethIpv4
];
};
lan = {
substitutions = mkSubstitutions "lan";
listenAddrsIpv4 = [ nativeAddrs."servo.lan" ];
port = 1053;
};
hn = {
substitutions = mkSubstitutions "hn";
listenAddrsIpv4 = [ nativeAddrs."servo.hn" ];
port = 1053;
};
lan = {
substitutions = mkSubstitutions "lan";
listenAddrsIpv4 = [ nativeAddrs."servo.lan" ];
# port = 1053;
};
# wan = {
# substitutions = mkSubstitutions "wan";
# listenAddrsIpv4 = [
# nativeAddrs."servo.lan"
# ];
# };
# hn-resolver = {
# # don't need %AWAN% here because we forward to the hn instance.
# listenAddrsIpv4 = [ nativeAddrs."servo.hn" ];
@ -151,9 +158,10 @@ in
};
sane.services.dyn-dns.restartOnChange = [
"trust-dns-wan.service"
"trust-dns-lan.service"
"trust-dns-doof.service"
"trust-dns-hn.service"
"trust-dns-lan.service"
# "trust-dns-wan.service"
# "trust-dns-hn-resolver.service" # doesn't need restart because it doesn't know about WAN IP
];
}

View File

@ -135,6 +135,7 @@ let
(fromDb "artemis.sh" // tech)
(fromDb "ascii.textfiles.com" // tech) # Jason Scott
(fromDb "austinvernon.site" // tech)
(fromDb "buttondown.email" // tech)
(fromDb "ben-evans.com/benedictevans" // pol)
(fromDb "bitbashing.io" // tech)
(fromDb "bitsaboutmoney.com" // uncat)
@ -196,6 +197,7 @@ let
(fromDb "willow.phantoma.online") # wizard@xyzzy.link
(fromDb "xn--gckvb8fzb.com" // tech)
(fromDb "xorvoid.com" // tech)
(fromDb "www.thebignewsletter.com" // pol)
(mkSubstack "astralcodexten" // rat // daily) # Scott Alexander
(mkSubstack "eliqian" // rat // weekly)
(mkSubstack "oversharing" // pol // daily)

View File

@ -62,6 +62,7 @@
sane.ids.clightning.gid = 2419;
sane.ids.nix-serve.uid = 2420;
sane.ids.nix-serve.gid = 2420;
sane.ids.plugdev.gid = 2421;
sane.ids.colin.uid = 1000;
sane.ids.guest.uid = 1100;

View File

@ -20,7 +20,7 @@
# - each namespace may use a different /etc/resolv.conf to specify different DNS servers
# - nscd breaks namespacing: the host nscd is unaware of the guest's /etc/resolv.conf, and so directs the guest's DNS requests to the host's servers.
# - this is fixed by either removing `/var/run/nscd/socket` from the namespace, or disabling nscd altogether.
{ config, lib, ... }:
{ config, lib, pkgs, ... }:
lib.mkMerge [
{
sane.services.trust-dns.enable = lib.mkDefault config.sane.services.trust-dns.asSystemResolver;
@ -59,15 +59,35 @@ lib.mkMerge [
# in the netns and we query upstream DNS more often than needed. hm.
# services.nscd.enableNsncd = true;
# disabling nscd LOSES US SOME FUNCTIONALITY. in particular, only the glibc-builtin modules are accessible via /etc/resolv.conf.
# disabling nscd LOSES US SOME FUNCTIONALITY. in particular, only the glibc-builtin modules are accessible via /etc/resolv.conf (er, did i mean /etc/nsswitch.conf?).
# - dns: glibc-bultin
# - files: glibc-builtin
# - myhostname: systemd
# - mymachines: systemd
# - resolve: systemd
# in practice, i see no difference with nscd disabled.
# - the exception is when the system dns resolver doesn't do everything.
# for example, systemd-resolved does mDNS. hickory-dns does not. a hickory-dns system won't be mDNS-capable.
# disabling nscd VASTLY simplifies netns and process isolation. see explainer at top of file.
services.nscd.enable = false;
system.nssModules = lib.mkForce [];
# system.nssModules = lib.mkForce [];
sane.silencedAssertions = [''.*Loading NSS modules from system.nssModules.*requires services.nscd.enable being set to true.*''];
# add NSS modules into their own subdirectory.
# then i can add just the NSS modules library path to the global LD_LIBRARY_PATH, rather than ALL of /run/current-system/sw/lib.
# TODO: i'm doing this so as to achieve mdns DNS resolution (avahi). it would be better to just have trust-dns delegate .local to avahi
# (except avahi doesn't act as a local resolver over DNS protocol -- only dbus).
environment.systemPackages = [(pkgs.symlinkJoin {
name = "nss-modules";
paths = config.system.nssModules.list;
postBuild = ''
mkdir nss
mv $out/lib/libnss_* nss
rm -rf $out
mkdir -p $out/lib
mv nss $out/lib
'';
})];
environment.variables.LD_LIBRARY_PATH = [ "/run/current-system/sw/lib/nss" ];
systemd.globalEnvironment.LD_LIBRARY_PATH = "/run/current-system/sw/lib/nss"; #< specifically for `geoclue.service`
}
]

View File

@ -70,7 +70,7 @@
# ensure new deployments have a source of this repo with which they can bootstrap.
# this however changes on every commit and can be slow to copy for e.g. `moby`.
environment.etc."nixos" = lib.mkIf (config.sane.maxBuildCost >= 3) {
source = ../..;
source = pkgs.sane-nix-files;
};
environment.etc."nix/registry.json" = lib.mkIf (config.sane.maxBuildCost < 3) {
enable = false;

View File

@ -151,7 +151,7 @@ in
# "ponymix"
"pulsemixer"
"python3-repl"
# "python3Packages.eyeD3" # music tagging
# "python3.pkgs.eyeD3" # music tagging
"ripgrep" # needed as a user package so that its user-level config file can be installed
"rsync"
"sane-scripts.bittorrent"
@ -175,8 +175,12 @@ in
# "gh" # MS GitHub cli
"nix-index"
"nixpkgs-review"
"qmk-udev-rules"
"sane-scripts.dev"
"sequoia"
# "via"
"wally-cli"
# "zsa-udev-rules"
];
consoleMediaUtils = declPackageSet [
@ -363,6 +367,7 @@ in
"inkscape"
# "jellyfin-media-player"
"kdenlive"
# "keymapp"
# "kid3" # audio tagging
"krita"
"libreoffice" # TODO: replace with an office suite that uses saner packaging?
@ -574,10 +579,6 @@ in
gawk.sandbox.wrapperType = "inplace"; # /share/gawk libraries refer to /libexec
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
gdb.sandbox.autodetectCliPaths = true;
geoclue2-with-demo-agent = {};
# MS GitHub stores auth token in .config
@ -1181,13 +1182,12 @@ in
];
};
hardware.opengl = lib.mkIf config.sane.programs.guiApps.enabled ({
hardware.graphics = 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;
# upstream nixpkgs forbids setting enable32Bit unless specifically x86_64 (so aarch64 isn't allowed)
enable32Bit = lib.mkDefault true;
}));
system.activationScripts.notifyActive = lib.mkIf config.sane.programs.guiApps.enabled {

View File

@ -0,0 +1,36 @@
# Avahi zeroconf (mDNS) implementation.
# runs as systemd `avahi-daemon.service`
#
# - <https://avahi.org/>
# - code: <https://github.com/avahi/avahi>
# - IRC: #avahi on irc.libera.chat
#
# - `avahi-browse --help` for usage
# - `man avahi-daemon.conf`
# - `LD_LIBRARY_PATH=/nix/store/ngwj3jqmxh8k4qji2z0lj7y1f8vzqrn2-nss-mdns-0.15.1/lib getent hosts desko.local`
# nss-mdns goes through avahi-daemon, so there IS caching here
#
{ config, lib, ... }:
{
sane.programs.avahi = {
};
services.avahi = lib.mkIf config.sane.programs.avahi.enabled {
enable = true;
package = config.sane.programs.avahi.package;
publish.enable = true;
publish.userServices = true;
nssmdns4 = true;
nssmdns6 = true;
# reflector = true;
allowInterfaces = [
# particularly, the default config disallows loopback, which is kinda fucking retarded, right?
"ens1" #< servo
"enp5s0" #< desko
"lo"
"wg-home"
"wlan0" #< moby
"wlp3s0" #< lappy
"wlp4s0" #< desko
];
};
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])" -p blast-ugjka
#!nix-shell -i python3 -p blast-ugjka -p python3
# vim: set filetype=python :
import logging

View File

@ -31,7 +31,7 @@ in
sane.programs.blast-to-default = {
# helper to deal with blast's interactive CLI
packageUnwrapped = pkgs.static-nix-shell.mkPython3Bin {
packageUnwrapped = pkgs.static-nix-shell.mkPython3 {
pname = "blast-to-default";
pkgs = [ "blast-ugjka" ];
srcRoot = ./.;

View File

@ -111,7 +111,7 @@ in
'';
});
fs.".config/bonsai/bonsai_tree.json".symlink.text = builtins.toJSON cfg.config.transitions;
fs.".config/bonsai/bonsai_tree.json".symlink.target = pkgs.writers.writeJSON "bonsai_tree.json" cfg.config.transitions;
sandbox.method = "bwrap";
sandbox.extraRuntimePaths = [

View File

@ -66,6 +66,7 @@ end
if vars.percent ~= nil then
bat_args = bat_args .. " --percent-suffix '" .. vars.percent .. "'"
end
bat_args = bat_args .. " {bat}"
-- N.B.: `[[ <text> ]]` is Lua's multiline string literal
conky.text = [[
@ -73,8 +74,8 @@ ${color1}${shadecolor 707070}${font sans-serif:size=50:style=Bold}${alignc}${exe
${color2}${shadecolor a4d7d0}${font sans-serif:size=20}${alignc}${exec date +"%a %d %b"}${font}
${color1}${shadecolor}${font sans-serif:size=22:style=Bold}${alignc}${execp @bat@ ]] .. bat_args .. [[ }${font}
${color1}${shadecolor}${font sans-serif:size=20:style=Bold}${alignc}${texeci 600 @weather@ }${font}
${color1}${shadecolor}${font sans-serif:size=22:style=Bold}${alignc}${execp sane-sysload ]] .. bat_args .. [[ }${font}
${color1}${shadecolor}${font sans-serif:size=20:style=Bold}${alignc}${texeci 600 timeout 20 sane-weather }${font}
${color2}${shadecolor a4d7d0}${font sans-serif:size=16}${alignc}⇅ ${downspeedf wlan0}]] .. vars.kBps .. [[${font}

View File

@ -1,38 +1,22 @@
{ 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 = {
sandbox.method = "bwrap";
sandbox.net = "clearnet"; #< for the scripts it calls (weather)
sandbox.extraPaths = [
"/sys/class/power_supply"
"/sys/devices" # needed by battery_estimate
"/sys/devices" # needed by sane-sysload
# "/sys/devices/cpu"
# "/sys/devices/system"
];
sandbox.whitelistWayland = true;
suggestedPrograms = [
"sane-battery-estimate"
"sane-sysload"
"sane-weather"
];
fs.".config/conky/conky.conf".symlink.target = pkgs.substituteAll {
src = ./conky.conf;
bat = "sane-battery-estimate";
weather = "timeout 20 sane-weather";
};
fs.".config/conky/conky.conf".symlink.target = ./conky.conf;
services.conky = {
description = "conky dynamic desktop background";

View File

@ -1,183 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash
usage() {
echo "usage: battery_estimate [options...]"
echo
echo "pretty-prints a battery estimate (icon to indicate state, and a duration estimate)"
echo
echo "options:"
echo " --debug: output additional information, to stderr"
echo " --minute-suffix <string>: use the provided string as a minutes suffix"
echo " --hour-suffix <string>: use the provided string as an hours suffix"
echo " --icon-suffix <string>: use the provided string as an icon suffix"
echo " --percent-suffix <string>: use the provided string when displaying percents"
}
# these icons may only render in nerdfonts
icon_bat_chg=("󰢟" "󱊤" "󱊥" "󰂅")
icon_bat_dis=("󰂎" "󱊡" "󱊢" "󱊣")
suffix_icon="" # thin space
suffix_percent="%"
# suffix_icon=" "
# render time like: 2ʰ08ᵐ
# unicode sub/super-scripts: <https://en.wikipedia.org/wiki/Unicode_subscripts_and_superscripts>
# symbol_hr="ʰ"
# symbol_min="ᵐ"
# render time like: 2ₕ08ₘ
# symbol_hr="ₕ"
# symbol_min="ₘ"
# render time like: 2h08m
# symbol_hr="h"
# symbol_min="m"
# render time like: 2:08
# symbol_hr=":"
# symbol_min=
# render time like: 208⧗
symbol_hr=""
symbol_min="⧗"
# variants:
# symbol_hr=":"
# symbol_min="⧖"
# symbol_min="⌛"
# render time like: 2'08"
# symbol_hr="'"
# symbol_min='"'
log() {
if [ "$BATTERY_ESTIMATE_DEBUG" = "1" ]; then
printf "$@" >&2
echo >&2
fi
}
render_icon() {
# args:
# 1: "chg" or "dis"
# 2: current battery percentage
level=$(($2 / 25))
level=$(($level > 3 ? 3 : $level))
level=$(($level < 0 ? 0 : $level))
log "icon: %s %d" "$1" "$level"
if [ "$1" = "dis" ]; then
printf "%s" "${icon_bat_dis[$level]}"
elif [ "$1" = "chg" ]; then
printf "%s" "${icon_bat_chg[$level]}"
fi
}
try_path() {
# assigns output variables:
# - perc, perc_from_full (0-100)
# - full, rate (pos means charging)
if [ -f "$1/capacity" ]; then
log "perc, perc_from_full from %s" "$1/capacity"
perc=$(cat "$1/capacity")
perc_from_full=$((100 - $perc))
fi
if [ -f "$1/charge_full_design" ] && [ -f "$1/current_now" ]; then
log "full, rate from %s and %s" "$1/charge_full_design" "$1/current_now"
# current is positive when charging
full=$(cat "$1/charge_full_design")
rate=$(cat "$1/current_now")
elif [ -f "$1/energy_full" ] && [ -f "$1/power_now" ]; then
log "full, rate from %s and %s" "$1/energy_full" "$1/power_now"
# power_now is positive when discharging
full=$(cat "$1/energy_full")
rate=-$(cat "$1/power_now")
elif [ -f "$1/energy_full" ] && [ -f "$1/energy_now" ]; then
log "full, rate from %s and %s" "$1/energy_full" "$1/energy_now"
log " this is a compatibility path for legacy Thinkpad batteries which do not populate the 'power_now' field, and incorrectly populate 'energy_now' with power info"
# energy_now is positive when discharging
full=$(cat "$1/energy_full")
rate=-$(cat "$1/energy_now")
fi
}
try_all_paths() {
try_path "/sys/class/power_supply/axp20x-battery" # Pinephone
try_path "/sys/class/power_supply/BAT0" # Thinkpad
log "perc: %d, perc_from_full: %d" "$perc" "$perc_from_full"
log "full: %f, rate: %f" "$full" "$rate"
log " rate > 0 means charging, else discharging"
}
fmt_minutes() {
# args:
# 1: icon to render
# 2: string to show if charge/discharge time is indefinite
# 3: minutes to stable state (i.e. to full charge or full discharge)
# - we work in minutes instead of hours for precision: bash math is integer-only
log "charge/discharge time: %f min" "$3"
# args: <battery symbol> <text if ludicrous estimate> <estimated minutes to full/empty>
if [ -n "$3" ] && [ "$3" -lt 1440 ]; then
hr=$(($3 / 60))
hr_in_min=$(($hr * 60))
min=$(($3 - $hr_in_min))
printf "%s%s%d%s%02d%s" "$1" "$suffix_icon" "$hr" "$symbol_hr" "$min" "$symbol_min"
else
log "charge/discharge duration > 1d"
printf "%s%s%s" "$1" "$suffix_icon" "$2" # more than 1d
fi
}
pretty_output() {
if [ -n "$perc" ]; then
duration=""
if [ "$rate" -gt 0 ]; then
log "charging"
icon="$(render_icon chg $perc)"
duration="$(($full * 60 * $perc_from_full / (100 * $rate)))"
else
log "discharging"
icon="$(render_icon dis $perc)"
if [ "$rate" -lt 0 ]; then
duration="$(($full * 60 * $perc / (-100 * $rate)))"
fi
fi
fmt_minutes "$icon" "$perc$suffix_percent" "$duration"
fi
}
while [ "$#" -gt 0 ]; do
case "$1" in
"--debug")
shift
BATTERY_ESTIMATE_DEBUG=1
;;
"--icon-suffix")
shift
suffix_icon="$1"
shift
;;
"--hour-suffix")
shift
symbol_hr="$1"
shift
;;
"--minute-suffix")
shift
symbol_min="$1"
shift
;;
"--percent-suffix")
shift
suffix_percent="$1"
shift
;;
*)
usage
exit 1
;;
esac
done
try_all_paths
pretty_output

View File

@ -10,6 +10,7 @@
./assorted.nix
./audacity.nix
./ausyscall.nix
./avahi.nix
./bemenu.nix
./blast-ugjka
./bonsai.nix
@ -50,8 +51,11 @@
./fwupd.nix
./g4music.nix
./gajim.nix
./gdb.nix
./gdbus.nix
./geary.nix
./geoclue-demo-agent.nix
./geoclue2.nix
./git.nix
./gnome-clocks.nix
./gnome-feeds.nix
@ -60,6 +64,8 @@
./gnome-weather.nix
./go2tv.nix
./gpodder.nix
./gpsd.nix
./gps-share.nix
./grimshot.nix
./gst-device-monitor.nix
./gthumb.nix
@ -67,9 +73,11 @@
./handbrake.nix
./helix.nix
./htop
./iio-sensor-proxy.nix
./imagemagick.nix
./jellyfin-media-player.nix
./kdenlive.nix
./keymapp.nix
./komikku.nix
./koreader
./less.nix
@ -87,6 +95,7 @@
./msmtp.nix
./nautilus.nix
./neovim.nix
./networkmanager_dmenu
./newsflash.nix
./nheko.nix
./nicotine-plus.nix
@ -94,15 +103,21 @@
./nmcli.nix
./notejot.nix
./ntfy-sh.nix
./nwg-panel
./objdump.nix
./obsidian.nix
./offlineimap.nix
./ols.nix
./open-in-mpv.nix
./pactl.nix
./pidof.nix
./pipewire.nix
./pkill.nix
./planify.nix
./portfolio-filemanager.nix
./playerctl.nix
./ps.nix
./qmk-udev-rules.nix
./rhythmbox.nix
./ripgrep.nix
./rofi
@ -112,8 +127,10 @@
./sane-open.nix
./sane-screenshot.nix
./sane-scripts.nix
./sane-sysload.nix
./sane-theme.nix
./sanebox.nix
./satellite.nix
./schlock.nix
./seatd.nix
./sfeed.nix
@ -133,14 +150,17 @@
./swaylock.nix
./swaynotificationcenter
./switchboard.nix
./sysvol.nix
./syshud.nix
./tangram.nix
./tor-browser.nix
./tuba.nix
./unl0kr
./via.nix
./vlc.nix
./wally-cli.nix
./waybar
./waylock.nix
./where-am-i.nix
./wike.nix
./wine.nix
./wireplumber.nix
@ -156,6 +176,7 @@
./zeal.nix
./zecwallet-lite.nix
./zulip.nix
./zsa-udev-rules.nix
./zsh
];

View File

@ -50,32 +50,13 @@ in
};
};
packageUnwrapped = (pkgs.dino.override {
packageUnwrapped = pkgs.dino.override {
# XXX(2024/04/24): build without echo cancelation (i.e. force WITH_VOICE_PROCESSOR to be undefined).
# this means that if the other end of the call is on speaker phone, i'm liable to hear my own voice
# leave their speaker, enter their mic, and then return to me.
# the benefit is a >50% reduction in CPU use. insignificant on any modern PC; make-or-break on a low-power Pinephone.
webrtc-audio-processing = null;
}).overrideAttrs (upstream: {
# i'm updating experimentally to see if it improves call performance.
# i don't *think* this is actually necessary; i don't notice any difference.
version = "0.4.3-unstable-2024-04-28";
src = lib.warnIf (lib.versionOlder "0.4.3" upstream.version) "dino update: safe to remove sane patches" pkgs.fetchFromGitHub {
owner = "dino";
repo = "dino";
rev = "657502955567dd538e56f300e075c7db52e25d74";
hash = "sha256-SApJy9FgxxLOB5A/zGtpdFZtSqSiS03vggRrCte1tFE=";
};
# avoid double-application of upstreamed patches
# https://github.com/NixOS/nixpkgs/pull/309265
patches = [];
checkPhase = ''
runHook preCheck
./xmpp-vala-test
# ./signal-protocol-vala-test # doesn't exist anymore
runHook postCheck
'';
});
};
sandbox.method = "bwrap";
sandbox.net = "clearnet";

View File

@ -55,7 +55,7 @@ in
# - theme-demo
# - timeout-completed
# - window-close
fs.".config/feedbackd/themes/proxied.json".symlink.text = builtins.toJSON {
fs.".config/feedbackd/themes/proxied.json".symlink.target = pkgs.writers.writeJSON "proxied.json" {
name = "proxied";
parent-theme = "default";
profiles = [

View File

@ -0,0 +1,13 @@
{ pkgs, ... }:
{
sane.programs.gdb = {
sandbox.enable = false; # gdb doesn't sandbox well. i don't know how you could.
# sandbox.method = "landlock"; # permission denied when trying to attach, even as root
sandbox.autodetectCliPaths = true;
fs.".config/gdb/gdbinit".symlink.text = ''
# enable commands like `py-bt`, `py-list`, etc.
# for usage, see: <https://wiki.python.org/moin/DebuggingWithGdb>
source ${pkgs.python3}/share/gdb/libpython.py
'';
};
}

View File

@ -0,0 +1,16 @@
{ config, pkgs, ... }:
{
sane.programs.geoclue-demo-agent = {
packageUnwrapped = pkgs.linkFarm "geoclue-demo-agent" [{
# bring the demo agent into a `bin/` directory so it can be invokable via PATH
name = "bin/geoclue-demo-agent";
path = "${config.sane.programs.geoclue2.packageUnwrapped}/libexec/geoclue-2.0/demos/agent";
}];
services.geoclue-agent = {
description = "geoclue 'demo' agent";
command = "geoclue-demo-agent";
partOf = [ "graphical-session" ];
};
};
}

View File

@ -0,0 +1,63 @@
# geoclue location services daemon.
#
# SUPPORT:
# - irc: #gnome-maps on irc.gimp.org
# - Matrix: #gnome-maps:gnome.org (unclear if bridged to IRC)
# - forums: <https://discourse.gnome.org/c/platform>
# - git: <https://gitlab.freedesktop.org/geoclue/geoclue/>
# - D-Bus API docs: <https://www.freedesktop.org/software/geoclue/docs/>
#
# HOW TO TEST:
# - just invoke `where-am-i`: it should output the current latitude/longitude.
## more manual testing:
# - build `geoclue2-with-demo-agent`
# - run the service: `systemctl start geoclue` or "${geoclue2-with-demo-agent}/libexec/geoclue"
# - run "${geoclue2-with-demo-agent}/libexec/geoclue-2.0/demos/agent"
# - keep this running in the background
# - run "${geoclue2-with-demo-agent}/libexec/geoclue-2.0/demos/where-am-i"
#
# DATA FLOW:
# - geoclue2 does http calls into local `ols`, which either hits the local disk or queries https://wigle.net.
# - geoclue users like gnome-maps somehow depend on an "agent",
# a user service which launches the geoclue system service on-demand (via dbus activation).
#
{ config, lib, pkgs, ... }:
let
cfg = config.sane.programs.geoclue2;
in
{
sane.programs.geoclue2 = {
# packageUnwrapped = pkgs.rmDbusServices pkgs.geoclue2;
# packageUnwrapped = pkgs.geoclue2.override { withDemoAgent = true; };
packageUnwrapped = pkgs.geoclue2-with-demo-agent;
suggestedPrograms = [
"avahi" #< to discover LAN gps devices
"geoclue-demo-agent"
"gps-share"
"iio-sensor-proxy"
"ols" #< WiFi SSID -> lat/long lookups
"satellite" #< graphical view into GPS fix data
"where-am-i" #< handy debugging/testing tool
];
};
# sane.programs.geoclue2.enableFor.system = lib.mkIf (builtins.any (en: en) (builtins.attrValues cfg.enableFor.user)) true;
services.geoclue2 = lib.mkIf cfg.enabled {
enable = true;
geoProviderUrl = "http://127.0.0.1:8088/v1/geolocate"; #< ols
# XXX(2024/06/25): when Geoclue uses ModemManager's GPS API, it wants to enable GPS
# tracking at the start, and disable it at the end. that causes tracking to be lost, regularly.
# this is not optional behavior: if Geoclue fails to control modem manager (because of a polkit policy, say),
# then it won't even try to read the data from modem manager.
# SOLUTION: tell Geoclue to get GPS from gps-share ("enableNmea", i.e. `network-nmea.enable`)
# and NOT from modem manager.
enableModemGPS = false;
enableNmea = true;
};
systemd.user.services = lib.mkIf cfg.enabled {
# nixos services.geoclue2 runs the agent as a user service by default, but i don't use systemd so that doesn't work.
# i manage the agent myself, in sane.programs.geoclue-demo-agent.
geoclue-agent.enable = false;
};
}

View File

@ -40,6 +40,7 @@ in
alias.amend = "commit --amend --no-edit";
alias.br = "branch";
alias.co = "checkout";
alias.com = "commit";
alias.cp = "cherry-pick";
alias.d = "difftool";
alias.dif = "diff"; # common typo

View File

@ -1,12 +1,12 @@
# gnome feeds RSS viewer
{ config, lib, sane-lib, ... }:
{ config, lib, pkgs, sane-lib, ... }:
let
feeds = sane-lib.feeds;
all-feeds = config.sane.feeds;
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
in {
sane.programs.gnome-feeds.fs.".config/org.gabmus.gfeeds.json".symlink.text = builtins.toJSON {
sane.programs.gnome-feeds.fs.".config/org.gabmus.gfeeds.json".symlink.target = pkgs.writers.writeJSON "org.gabmus.gfeeds.json" {
# feed format is a map from URL to a dict,
# with dict["tags"] a list of string tags.
feeds = sane-lib.mapToAttrs (feed: {

View File

@ -1,7 +1,14 @@
# SUPPORT:
# - irc: #gnome-maps on irc.gimp.org
# - Matrix: #gnome-maps:gnome.org (unclear if bridged to IRC)
{ pkgs, ... }:
{
sane.programs."gnome.gnome-maps" = {
packageUnwrapped = pkgs.rmDbusServices pkgs.gnome.gnome-maps;
suggestedPrograms = [
"geoclue2"
];
sandbox.method = "bwrap";
sandbox.whitelistDri = true; # for perf
sandbox.whitelistDbus = [

View File

@ -0,0 +1,54 @@
# gps-share: <https://github.com/zeenix/gps-share>
# takes a local GPS device (e.g. /dev/ttyUSB1) and makes it available over TCP/Avahi (multicast DNS).
#
# common usecases:
# 1. make positioning available to any device on a network, even if that device has no local GPS
# - e.g. my desktop can use my phone's GPS device, if on the same network.
# 2. allow multiple clients to share a GPS device.
# GPS devices are serial devices, and so only one process can consume the data at a time.
# gps-share can camp the serial device, and then allow *multiple* subscribers
# 3. provide a *read-only* API to clients like Geoclue.
# that is, expose the GPS device *output* to a client, but don't let the client write to the device (e.g. enable/disable the GPS).
# this is the primary function i derive from gps-share
#
# HOW TO TEST:
# - `nc localhost 10110`
# should stream GPS NMEA output to the console
# - `avahi-browse --resolve _nmea-0183._tcp`: should show hosts on the local network which provide GPS info
{ config, lib, ... }:
let
cfg = config.sane.programs.gps-share;
in
{
sane.programs.gps-share = {
configOption = with lib; mkOption {
default = {};
type = types.submodule {
options.device = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
path to GPS device to share.
'';
example = "/dev/ttyUSB1";
};
};
};
services.gps-share = lib.mkIf (cfg.config.device != null) {
description = "gps-share: make local GPS serial readings available over Avahi";
# usage:
# gps-share --no-announce # to disable Avahi
# gps-share --no-tcp # only makes sense if using --socket-path
# gps-share --network-interface lo # defaults to all interfaces, but firewalling means actually more restrictive
# gps-share --socket-path $XDG_RUNTIME_DIR/gps-share/gps-share.sock # share over a unix socket
command = "gps-share ${cfg.config.device}";
# TODO: this should be `partOf = [ "gps" ]`:
# it fails to launch if the NMEA device doesn't yet exist, and so restart loop when modem is not booted
dependencyOf = [ "geoclue-agent" ];
};
};
# TODO: restrict this to just LAN devices!!
networking.firewall.allowedTCPPorts = lib.mkIf cfg.enabled [ 10110 ];
}

View File

@ -0,0 +1,33 @@
# test gpsd with `gpspipe -w -n 10 2> /dev/null | grep -m 1 TPV | jq '.lat, .lon' | tr '\n' ' '`
# ^ should return <lat> <long>
#
# TODO(2024/06/19): nixpkgs' gpsd service isn't sandboxed at ALL. i should sandbox that, or remove this integration.
#
# pinephone GPS happens in EG25 modem
# serial control interface to modem is /dev/ttyUSB2
# after enabling GPS, readout is /dev/ttyUSB1
#
# minimal process to enable modem and GPS:
# - `echo 1 > /sys/class/modem-power/modem-power/device/powered`
# - `screen /dev/ttyUSB2 115200`
# - `AT+QGPSCFG="nmeasrc",1`
# - `AT+QGPS=1`
# this process is automated by my `eg25-control` program and services (`eg25-control-powered`, `eg25-control-gps`)
# - see the `modules/` directory further up this repository.
#
# now, something like `gpsd` can directly read from /dev/ttyUSB1,
# or geoclue can query the GPS directly through modem-manager
#
# initial GPS fix can take 15+ minutes.
# meanwhile, services like eg25-manager or eg25-control-freshen-agps can speed this up by uploading assisted GPS data to the modem.
{ config, lib, ... }:
let
cfg = config.sane.programs.gpsd;
in
{
sane.programs.gpsd = {};
services.gpsd = lib.mkIf cfg.enabled {
enable = true;
devices = [ "/dev/ttyUSB1" ];
};
}

View File

@ -0,0 +1,25 @@
# src: <https://gitlab.freedesktop.org/hadess/iio-sensor-proxy>
# IIO = "Industrial I/O": <https://www.kernel.org/doc/html/v4.12/driver-api/iio/index.html>
# iio-sensor-proxy reads IIO data reported by the kernel at /sys/bus/iio/* and makes it available to dbus applications.
# this includes:
# - ambient light sensor
# - compass/magnetometer
# - accelerometer (rotation)
#
# use:
# - show available sensors: `gdbus introspect --system --dest net.hadess.SensorProxy --object-path /net/hadess/SensorProxy`
# - read sensors: `sudo -u geoclue monitor-sensor --compass`
# - default dbus policy only allows geoclue to use the compass
# - `sudo monitor-sensor` for light/rotation
{ config, lib, ... }:
let
cfg = config.sane.programs.iio-sensor-proxy;
in
{
sane.programs.iio-sensor-proxy = {
enableFor.system = lib.mkIf (builtins.any (en: en) (builtins.attrValues cfg.enableFor.user)) true; #< for dbus/polkit policies
};
services.udev.packages = lib.mkIf cfg.enabled [ cfg.package ];
# services.dbus.packages = lib.mkIf cfg.enabled [ cfg.package ]; #< for bus ownership policy
systemd.packages = lib.mkIf cfg.enabled [ cfg.package ]; #< for iio-sensor-proxy.service
}

View File

@ -0,0 +1,8 @@
# ZSA keyboard (Ergodox, Moonlander, ...) firmware flasher and keymap viewer.
# video: <https://www.zsa.io/flash>
# displays on launch:
# - "Error connecting to the keyboard, make sure the layout flashed on your keyboard was recently compiled with Oryx and that the [Live training] option is toggled on in the advanced settings."
{ ... }:
{
sane.programs.keymapp = {};
}

View File

@ -1,14 +1,18 @@
# docs: <https://git.sr.ht/~mil/mepo>
# irc #mepo:irc.oftc.net
#
{ config, lib, ... }:
{
sane.programs.mepo = {
sandbox.method = "bwrap";
sandbox.net = "all"; # for tiles *and* for localhost comm to gpsd
sandbox.whitelistDri = true;
sandbox.whitelistWayland = true;
sandbox.whitelistDbus = [ "user" ]; # for geoclue
sandbox.whitelistDbus = [
"system" # system is required for non-portal location services
"user" #< not sure if "user" is necessary?
];
sandbox.usePortal = false; # TODO: set up portal-based location services
persist.byStore.plaintext = [ ".cache/mepo/tiles" ];
# ~/.cache/mepo/savestate has precise coordinates and pins: keep those private
@ -16,11 +20,11 @@
{ type = "file"; path = ".cache/mepo/savestate"; }
];
# give mepo access to gpsd for location data, if that's enabled.
# same with geoclue2.
suggestedPrograms = lib.optional config.services.gpsd.enable "gpsd"
++ lib.optional config.services.geoclue2.enable "geoclue2-with-demo-agent"
;
# enable geoclue2 and gpsd for location data.
suggestedPrograms = [
"geoclue2"
# "gpsd" #< not required, and mepo only uses it if geoclue is unavailable
];
};
# programs.mepo = lib.mkIf config.sane.programs.mepo.enabled {

View File

@ -5,7 +5,7 @@
# alternative to mimeo is jaro: <https://github.com/isamert/jaro>
{ config, lib, pkgs, ... }:
let
mimeo-open-desktop = pkgs.static-nix-shell.mkPython3Bin {
mimeo-open-desktop = pkgs.static-nix-shell.mkPython3 {
pname = "mimeo-open-desktop";
srcRoot = ./.;
pkgs = [ "mimeo" ];

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])" -p mimeo
#!nix-shell -i python3 -p mimeo -p python3
# TODO: migrate nixpkgs mimeo to be `buildPythonPackage` to make it importable here.
# see <doc/languages-frameworks/python.section.md>

View File

@ -1,3 +1,19 @@
# GPS:
# - enable: `mmcli --modem any --location-enable-gps-unmanaged`
# - or `mmcli -m any --location-enable-gps-nmea`
# - or use `s6-rc start eg25-control-gps`
# - verify GPS is enabled: `mmcli --modem any --location-status`
# - query GPS coordinates: `mmcli -m any --location-get`
# - monitor constellation info: `mmcli -m any --location-monitor`
# - i.e. which satellites are in view
# - or just `cat /dev/ttyUSB1`
#
# interactions, warnings:
# - Geoclue (`where-am-i`) toggles mmcli GPS on/off every 60s, often resetting it to the "off" state
# - see: <https://gitlab.freedesktop.org/geoclue/geoclue/-/issues/180>
# - the effect is that GPS data is effectively useless inside apps like gnome-maps
# i think the trick is to get "--location-enable-gps-unmanaged" gps working again
# or use gnss-share/gpsd (this may be what "unmanaged" means).
{ pkgs, ... }:
{
sane.programs.mmcli = {

View File

@ -241,9 +241,10 @@ in
mime.associations."video/webm" = "mpv.desktop";
mime.associations."video/x-flv" = "mpv.desktop";
mime.associations."video/x-matroska" = "mpv.desktop";
mime.urlAssociations."^https?://(www.)?youtube.com/watch\?.*v=" = "mpv.desktop";
mime.urlAssociations."^https?://(www.)?youtube.com/v/" = "mpv.desktop";
mime.urlAssociations."^https?://(www.)?youtu.be/.+" = "mpv.desktop";
mime.urlAssociations."^https?://(m\.)?(www\.)?youtu.be/.+" = "mpv.desktop";
mime.urlAssociations."^https?://(m\.)?(www\.)?youtube.com/shorts/.+" = "mpv.desktop";
mime.urlAssociations."^https?://(m\.)?(www\.)?youtube.com/v/" = "mpv.desktop";
mime.urlAssociations."^https?://(m\.)?(www\.)?youtube.com/watch\?.*v=" = "mpv.desktop";
};
}

View File

@ -0,0 +1,44 @@
[dmenu]
dmenu_command = rofi -dmenu
# # Note that dmenu_command can contain arguments as well like:
# # `dmenu_command = rofi -dmenu -i -theme nmdm`
# # `dmenu_command = rofi -dmenu -width 30 -i`
# # `dmenu_command = dmenu -i -l 25 -b -nb #909090 -nf #303030`
# # `dmenu_command = fuzzel --dmenu`
rofi_highlight = True
compact = True
# pinentry = <Pinentry command> # (Default: None) e.g. `pinentry-gtk`
# wifi_chars = <string of 4 unicode characters representing 1-4 bars strength>
wifi_chars = ▂▄▆█
# wifi_icons = <characters representing signal strength as an icon>
wifi_icons = 󰤯󰤟󰤢󰤥󰤨
# format = <Python style format string for the access point entries>
# # TODO: replace `{sec}` with a locked/unlocked icon
format = {icon} {name} [{signal}%%] [{sec}]
# # Available variables are:
# # * {name} - Access point name
# # * {sec} - Security type
# # * {signal} - Signal strength on a scale of 0-100
# # * {bars} - Bar-based display of signal strength (see wifi_chars)
# # * {icon} - Icon-based display of signal strength (see wifi_icons)
# # * {max_len_name} and {max_len_sec} are the maximum lengths of {name} / {sec}
# # respectively and may be useful for formatting.
# list_saved = <True or False> # (Default: False) list saved connections
[dmenu_passphrase]
# # Uses the -password flag for Rofi, -x for bemenu. For dmenu, sets -nb and
# # -nf to the same color or uses -P if the dmenu password patch is applied
# # https://tools.suckless.org/dmenu/patches/password/
# obscure = True
# obscure_color = #222222
[pinentry]
# description = <Pinentry description> (Default: Get network password)
# prompt = <Pinentry prompt> (Default: Password:)
[editor]
# terminal = <name of terminal program>
# gui_if_available = <True or False> (Default: True)
[nmdm]
# rescan_delay = <seconds> # (seconds to wait after a wifi rescan before redisplaying the results)

View File

@ -0,0 +1,21 @@
# source: <https://github.com/firecat53/networkmanager-dmenu>
{ ... }:
{
sane.programs.networkmanager_dmenu = {
sandbox.method = "bwrap";
sandbox.isolatePids = false; #< so it can know that NetworkManager really is running... (?)
sandbox.whitelistDbus = [
"system"
];
sandbox.whitelistWayland = true;
sandbox.extraHomePaths = [
".cache/rofi"
".config/rofi"
];
suggestedPrograms = [
"pidof"
];
fs.".config/networkmanager-dmenu/config.ini".symlink.target = ./config.ini;
};
}

View File

@ -2,6 +2,9 @@
{
sane.programs.nmcli = {
packageUnwrapped = pkgs.networkmanager-split.nmcli;
# TODO: sandbox
sandbox.method = "bwrap";
sandbox.whitelistDbus = [
"system"
];
};
}

View File

@ -0,0 +1,7 @@
{
"restart-on-display": true,
"restart-delay": 500,
"run-through-compositor": false,
"processes-background-only": true,
"processes-own-only": true
}

View File

@ -0,0 +1,190 @@
# TODO:
# - try this PR to get custom workspace names to work:
# - <https://github.com/nwg-piotr/nwg-panel/pull/191>
# - add network/bluetooth indicator
# - <https://github.com/nwg-piotr/nwg-panel/issues/269>
# - add CPU/meminfo executor
# - use sane-sysload
{
controlsSettingsComponents,
height,
locker,
modulesRight,
playerctlChars,
mediaPrevNext,
windowIcon,
windowTitle,
workspaceHideEmpty,
workspaceNumbers,
}:
[
{
controls = "right";
css-name = "panel-top";
exclusive-zone = true;
height = height;
homogeneous = false; #< homogenous=false means to not force modules-{left,center,right} to an inflexible 33%/33%/33% real-estate split.
icons = "light";
items-padding = 0;
layer = "bottom";
margin-bottom = 0;
margin-top = 0;
menu-start = "off";
name = "panel-top";
# output = "All" => display the bar on every output.
# - documented: <https://github.com/nwg-piotr/nwg-panel/issues/48>
# alternatively, i could declare one bar per display,
# and then customize it so that the external display(s) render a less noisy bar.
# this will be easier once this is addressed: <https://github.com/nwg-piotr/nwg-panel/issues/215>
output = "All";
padding-horizontal = 0;
padding-vertical = 0;
position = "top";
sigrt = 64;
spacing = 0;
start-hidden = false;
use-sigrt = false;
width = "auto";
modules-left = [
"sway-workspaces"
];
modules-center = [
"clock"
];
modules-right = modulesRight;
clock = {
angle = 0.0;
calendar-css-name = "calendar-window";
calendar-icon-size = 24;
calendar-interval = 60;
calendar-margin-horizontal = 0;
calendar-margin-vertical = 0;
calendar-on = true;
calendar-path = "";
calendar-placement = "top";
css-name = "clock";
format = "%H:%M";
interval = 30;
on-left-click = "";
on-middle-click = "";
on-right-click = "";
on-scroll-down = "";
on-scroll-up = "";
root-css-name = "root-clock";
tooltip-date-format = true;
tooltip-text = "%a; %d %b %H:%M:%S";
};
controls-settings = {
battery-low-interval = 4; #< notify every N minutes when battery continues to remain low
battery-low-level = 15; #< notify if battery is lower than this percent
# commands.battery = ""; #< optional action to perform when battery icon is clicked in the drop-down menu
components = controlsSettingsComponents;
click-closes = false;
custom-items = [];
css-name = "controls-window";
hover-opens = false;
icon-size = 16;
interval = 1;
leave-closes = false;
menu.icon = "system-shutdown-symbolic";
menu.items = [
{
name = "Lock";
cmd = "s6-rc start ${locker}";
}
# {
# name = "Logout";
# cmd = "swaymsg exit";
# }
{
name = "Reboot";
cmd = "reboot";
}
{
name = "Shutdown";
cmd = "shutdown now";
}
];
menu.name = "Exit";
output-switcher = true; #< allow changing the default audio sink
#v `show-<x>` means "show the NUMERICAL VALUE corresponding to <x>"
# e.g. show-battery means "show the battery _percentage_ next to its icon".
show-battery = true;
show-brightness = false;
show-values = false;
show-volume = false;
# window-width: should be 360 for moby, but because of weird `margin` tweaks in style.css
# we have to add 20px to both sides
window-width = 400;
};
playerctl = {
button-css-name = "playerctl-button";
buttons-position = "left";
chars = playerctlChars;
icon-size = 16;
interval = 2;
label-css-name = "playerctl-label";
scroll = false;
show-cover = false; #< don't show the little music-note icon
show-previous = mediaPrevNext;
show-next = mediaPrevNext;
show-name = mediaPrevNext;
};
swaync = {
css-name = "swaync-label";
# interval = 1;
# icon-placement = "left";
# icon-size = 18;
# tooltip-text = "";
# on-left-click = "swaync-client -t";
# on-right-click = "";
# on-middle-click = "";
# on-scroll-up = "";
# on-scroll-down = "";
# always-show-icon = true;
};
sway-workspaces = {
angle = 0.0;
custom-labels = [];
focused-labels = [];
hide-empty = workspaceHideEmpty;
image-size = 16;
mark-autotiling = true;
mark-content = false;
name-length = 40;
numbers = workspaceNumbers;
show-icon = windowIcon;
show-layout = false;
show-name = windowTitle;
};
executor-sysload = {
script = "sane-sysload {mem} {cpu}";
interval = 10;
css-name = "";
on-right-click = "";
icon-size = 16;
show-icon = false;
tooltip-text = "";
on-left-click = "";
on-middle-click = "";
on-scroll-up = "";
on-scroll-down = "";
};
# unused modules:
brightness-slider = {};
dwl-tags = {};
hyprland-taskbar = {};
hyprland-workspaces = {};
keyboard-layout = {};
openweather = {};
scratchpad = {};
sway-mode = {};
sway-taskbar = {}; #< windows-style taskbar, usually placed at the bottom of the screen, to show open windows & tab to them on click
tray = {};
}
]

View File

@ -0,0 +1,160 @@
# nwg-panel: a wayland status bar (like waybar, etc)
# documentation is in the GitHub Wiki:
# - <https://github.com/nwg-piotr/nwg-panel/wiki/Configuration>
#
# interactively configure with: `nwg-panel-config`
# ^ note that this may interfere with the `nwg-panel` service
{ config, lib, pkgs, ... }:
let
cfg = config.sane.programs.nwg-panel;
mkEnableOption' = default: description: lib.mkOption {
type = lib.types.bool;
inherit default description;
};
in
{
sane.programs.nwg-panel = {
configOption = with lib; mkOption {
default = {};
type = types.submodule {
options = {
clockFontSize = mkOption {
type = types.int;
# what looks good:
# - 15px on moby
# - 24px on lappy
# there's about 10px padding total around this (above + below)
default = lib.min 24 (cfg.config.height - 11);
};
fontSize = mkOption {
type = types.int;
default = 16;
};
height = mkOption {
type = types.int;
default = 40;
description = ''
height of the top bar in px.
'';
};
locker = mkOption {
type = types.str;
default = config.sane.programs.swayidle.config.actions.lock.service;
description = ''
s6 service to start which can lock the screen
'';
};
battery = mkEnableOption' true "display battery status";
brightness = mkEnableOption' true "display backlight level and slider";
mediaTitle = mkEnableOption' true "display title of current song/media";
mediaPrevNext = mkEnableOption' true "display prev/next button in media";
sysload = mkEnableOption' true "display system load info (cpu/memory)";
windowIcon = mkEnableOption' true "display icon of active window";
windowTitle = mkEnableOption' true "display title of active window";
workspaceNumbers = mkOption {
type = types.listOf types.str;
default = [
# TODO: workspace 10 should be rendered as "TV"
"1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
];
description = ''
workspaces to monitor
'';
};
workspaceHideEmpty = mkOption {
type = types.bool;
default = true;
};
};
};
};
packageUnwrapped = (pkgs.nwg-panel.override {
# XXX(2024/06/13): hyprland does not cross compile
hyprland = null;
# XXX(2024/06/13): wlr-randr does not cross compile
wlr-randr = null; #< only used if not on sway/hyprland; or if using dwl
}).overrideAttrs (base: {
# patches = (base.patches or []) ++ lib.optionals (!cfg.config.mediaPrevNext) [
# ./playerctl-no-prev-next.diff
# ];
patches = (base.patches or []) ++ [
(pkgs.fetchpatch {
# upstreaming: <https://github.com/nwg-piotr/nwg-panel/pull/309>
url = "https://git.uninsane.org/colin/nwg-panel/commit/a714e4100c409feb02c454874d030d192bfb0ae5.patch";
name = "playerctl: add settings to control which elements are displayed";
hash = "sha256-OofS46wAI3EDE3JbYs/Nn+Vkw9TP1mwSFvk+vBERg2s=";
})
];
# - disable the drop-down chevron by the controls.
# it's precious space on moby, doesn't do much to help on lappy either.
# - disable brightness indicator for same reason.
# - *leave* the volume indicator: one *could* remove it, however on desko that would leave the controls pane empty
# making the dropdown inaccessible
# also, remove padding from the items. i can manage that in css and the python padding prevents that.
postPatch = (base.postPatch or "") + ''
substituteInPlace nwg_panel/modules/controls.py --replace-fail \
'self.box.pack_start(box, False, False, 6)' \
'self.box.pack_start(box, False, False, 0)'
substituteInPlace nwg_panel/modules/controls.py --replace-fail \
'box.pack_start(self.pan_image, False, False, 4)' \
'# box.pack_start(self.pan_image, False, False, 0)'
substituteInPlace nwg_panel/modules/controls.py --replace-fail \
'box.pack_start(self.bri_image, False, False, 4)' \
'# box.pack_start(self.bri_image, False, False, 0)'
substituteInPlace nwg_panel/modules/controls.py --replace-fail \
'box.pack_start(self.vol_image, False, False, 4)' \
'box.pack_start(self.vol_image, False, False, 0)'
'';
# XXX(2024/06/13) the bluetooth stuff doesn't cross compile, so disable it
propagatedBuildInputs = lib.filter (p: p.pname != "pybluez") base.propagatedBuildInputs;
strictDeps = true;
});
suggestedPrograms = [
"pactl" # pactl required by `per-app-volume` component.
];
fs.".config/nwg-panel/style.css".symlink.target = pkgs.substituteAll {
src = ./style.css;
inherit (cfg.config) fontSize clockFontSize;
};
fs.".config/nwg-panel/common-settings.json".symlink.target = ./common-settings.json;
fs.".config/nwg-panel/config".symlink.target = pkgs.writers.writeJSON "config" (import ./config.nix {
inherit (cfg.config) locker height mediaPrevNext windowIcon windowTitle workspaceHideEmpty workspaceNumbers;
# component order matters, mostly for the drop-down.
# default for most tools (e.g. swaync) is brightness control above volume.
controlsSettingsComponents =
lib.optionals cfg.config.brightness [
"brightness"
] ++ [
"volume"
"per-app-volume"
] ++ lib.optionals cfg.config.battery [
"battery"
]
;
modulesRight = [
"playerctl"
] ++ lib.optionals cfg.config.sysload [
"executor-sysload"
];
playerctlChars = if cfg.config.mediaTitle then 60 else 0;
});
services.nwg-panel = {
description = "nwg-panel status/topbar for wayland";
partOf = [ "graphical-session" ];
# to debug styling, run with GTK_DEBUG=interactive
# N.B.: G_MESSAGES_DEBUG=all causes the swaync icon to not render
# command = "env G_MESSAGES_DEBUG=all nwg-panel";
command = "nwg-panel";
};
};
}

View File

@ -0,0 +1,59 @@
commit 7aa759990b38b09abf9010dfe58e4cbdc1493282 (HEAD -> dev-sane)
Author: Colin <colin@uninsane.org>
Date: 2024-06-15 21:41:46 +0000
playerctl: remove backward/forward/music-note icons
these aren't worth the space cost on narrow devices (moby)
diff --git a/nwg_panel/modules/playerctl.py b/nwg_panel/modules/playerctl.py
index ff48d4c..43ae221 100644
--- a/nwg_panel/modules/playerctl.py
+++ b/nwg_panel/modules/playerctl.py
@@ -211,15 +211,6 @@ class Playerctl(Gtk.EventBox):
if self.settings["angle"] != 0.0:
button_box.set_orientation(Gtk.Orientation.VERTICAL)
- img = Gtk.Image()
- update_image(img, "media-skip-backward-symbolic", self.settings["icon-size"], icons_path=self.icons_path)
- btn = Gtk.Button()
- btn.set_image(img)
- if self.settings["button-css-name"]:
- btn.set_property("name", self.settings["button-css-name"])
- btn.connect("clicked", self.launch, self.PlayerOps.PREVIOUS)
- button_box.pack_start(btn, False, False, 1)
-
self.play_pause_btn = Gtk.Button()
if self.settings["button-css-name"]:
self.play_pause_btn.set_property("name", self.settings["button-css-name"])
@@ -229,15 +220,6 @@ class Playerctl(Gtk.EventBox):
self.play_pause_btn.connect("clicked", self.launch, self.PlayerOps.PLAY_PAUSE)
button_box.pack_start(self.play_pause_btn, False, False, 1)
- img = Gtk.Image()
- update_image(img, "media-skip-forward-symbolic", self.settings["icon-size"], icons_path=self.icons_path)
- btn = Gtk.Button()
- btn.set_image(img)
- if self.settings["button-css-name"]:
- btn.set_property("name", self.settings["button-css-name"])
- btn.connect("clicked", self.launch, self.PlayerOps.NEXT)
- button_box.pack_start(btn, False, False, 1)
-
self.num_players_lbl = Gtk.Label.new("")
if self.settings["label-css-name"]:
self.num_players_lbl.set_property("name", self.settings["label-css-name"])
@@ -257,13 +239,9 @@ class Playerctl(Gtk.EventBox):
self.box.pack_start(button_box, False, False, 2)
if self.settings["show-cover"]:
self.box.pack_start(self.cover_img, False, False, 0)
- self.box.pack_start(self.num_players_lbl, False, False, 0)
- self.box.pack_start(self.label, False, False, 5)
else:
if self.settings["show-cover"]:
self.box.pack_start(self.cover_img, False, False, 2)
- self.box.pack_start(self.num_players_lbl, False, False, 0)
- self.box.pack_start(self.label, False, False, 2)
self.box.pack_start(button_box, False, False, 10)
def launch(self, button, op):

View File

@ -0,0 +1,241 @@
/* foreground (text)/background */
@define-color fg0 #d8d8d8;
@define-color fg1 #ffffff;
@define-color bg0 #130c0c;
@define-color bg1 #1c1716;
/* green accents */
@define-color accent-g0 #1f5e54;
@define-color accent-g1 #418379;
@define-color accent-g2 #63a89c;
/* red accents */
@define-color accent-r0 #c96262;
@define-color accent-r1 #d27871;
@define-color accent-r2 #ff968b;
/* light (teal-white) accents */
@define-color accent-l0 #e1f0ef;
@define-color accent-l1 #f9fffc;
* {
font-size: @fontSize@px;
}
#task-box-focused {
background-color: @accent-g2;
}
#playerctl-button {
background-color: rgba(0, 0, 0, 0.08);
background-image: none;
border: none;
box-shadow: none;
/* remove the 1px gap between buttons, since that causes color stripes if the background is a different color */
margin-left: -1;
margin-right: -1;
outline: none;
/* prevent the buttons from pushing the whole bar down */
padding-top: 0px;
padding-bottom: 0px;
margin-top: 0px;
margin-bottom: 0px;
}
#panel-top {
background: @accent-g1;
color: @fg1;
}
/* fix up the top bar sections so that the clock can be centered, even without forcing it to take 1/3rd of the bar */
/* pair with `homogenous = false` in config. on overflow, the clock may be rendered on top of the left portion of the bar */
/* and the right portion of the bar will render on top of all */
#panel-top > box > box > box > #left-box {
margin-left: 0px;
margin-right: -16384px;
}
#panel-top > box > box > box > #center-box {
margin-left: 0px;
margin-right: 0px;
}
#panel-top > box > box > box > box {
/* this is the *parent* of #right-box, which is uniquely under an unnamed "helper box" */
/* i have to address this parent, because otherwise only the controls are visible and the executors (including playerctl) */
/* are packed in a fill mode that pushes them off the visible section of the bar */
margin-left: -16384px;
}
#right-box > widget > * {
/* TODO: tune this for moby */
padding-right: 3px;
padding-left: 2px;
}
#swaync-label {
/* move the notification count closer to the bell icon */
margin-left: -3px;
/* TODO: this should be main font size -1 */
font-size: 14px;
color: @accent-r2;
}
/* increase the size of each workspace icon */
#sway-workspaces-item > label {
padding-left: 1px;
padding-right: 1px;
}
/* default config highlights hovered workspace with a gray border */
#sway-workspaces > widget:selected {
box-shadow: none;
}
/* the CSS nodes are difficult to determine.
* reference: <https://github.com/numixproject/numix-gtk-theme/blob/master/src/gtk-3.20/scss/widgets/_calendar.scss>
*/
#calendar-window {
background-color: @accent-l0;
}
calendar {
background-color: @accent-l0;
}
calendar :selected {
background-color: @accent-r1;
}
#controls-window {
border-radius: 15px;
background: @bg1;
color: @fg1;
}
/* default config highlights selected items with a green border */
widget:selected {
box-shadow: none;
background-color: @accent-g0;
}
#controls-window widget:selected {
box-shadow: none;
background-color: @accent-r0;
}
/* default config puts a *ridiculous* amount of padding around the whole controls window */
#controls-window > widget > .vertical {
margin-left: -20px;
margin-right: -20px;
}
#controls-window > widget > .vertical > .horizontal {
margin-top: -14px; /* full reset would be -20px */
margin-bottom: -20px;
}
/* add back in a little bit of padding, but in a way such that my highlights apply to it */
#controls-window .horizontal widget > box,
#controls-window > widget > .vertical > .horizontal > .vertical > .horizontal
{
padding-left: 12px;
padding-right: 12px;
}
#controls-window > widget > .vertical > .horizontal > .vertical > widget > box
{
padding-top: 6px;
padding-bottom: 6px;
}
#controls-window > widget > .vertical > .horizontal > .vertical > box > widget > box
{
padding-top: 3px;
padding-bottom: 3px;
}
/* hierarchy is .horizontal > {image, scale > { value, contents > trough > { slider, highlight } } } */
scale {
padding-right: 0px;
padding-top: 0px;
padding-bottom: 0px;
}
scale trough {
padding-left: 9px;
padding-right: 9px;
border-radius: 9px;
border-color: rgba(0, 0, 0, 0);
background: @bg0;
}
scale highlight {
border-radius: 9px;
border-color: rgba(0, 0, 0, 0);
margin: 0px;
margin-left: -9px;
background: @accent-r1;
}
scale slider {
margin-top: -3px;
margin-bottom: -3px;
background: @accent-l1;
min-height: 25px;
min-width: 25px;
}
#clock {
font-family: monospace;
font-size: @clockFontSize@px;
}
/* UNUSED IN MY CURRENT CONFIG: COPIED FROM SAMPLE CONFIG */
/* Controls window in sample config uses this name */
/* Brightness slider popup window in sample config uses this name */
#brightness-popup {
border-radius: 15px;
background: @bg1;
color: @fg1;
}
#brightness-popup box {
padding: 15px;
}
/* Executors usually behave better in monospace fonts */
#executor-label {
font-family: monospace;
}
/* Bottom panel in sample config uses this name */
#panel-bottom {
background: #101010;
color: #eeeeee;
}
/* Sample executor-weather uses "css-name": "weather" */
#weather {
font-size: 16px;
}
/* dwl-tags module */
#dwl-tag-box {
padding-top: 4px;
padding-bottom: 4px;
}
#dwl-tag-occupied {
font-family: monospace;
color: #eee;
background-color: #006699;
padding-left: 3px;
padding-right: 3px;
}
#dwl-tag-free {
font-family: monospace;
color: #eee;
background-color: rgba (32, 50, 90, 1.0);
padding-left: 3px;
padding-right: 3px;
}
#dwl-tag-urgent {
font-family: monospace;
color: #eee;
background-color: #ee6600;
padding-left: 3px;
padding-right: 3px;
}
#dwl-tag-selected {
border: solid 2px;
border-color: #81a1c1;
}

View File

@ -0,0 +1,45 @@
# OLS: Offline Location Service: <https://codeberg.org/tpikonen/ols>
# fields {wifi SSID,cell tower} -> lat/long queries from geoclue
# satisfies queries via https://wigle.net, by learning about map tiles
# and caching those on-disk so that repeat queries may be serviced offline.
#
# it listens on localhost:8088, and one can validate its operation with a query like (substitute macAddresses for something real):
# - WiFi: curl -d '{"wifiAccessPoints":[{"macAddress":"01:23:45:67:89:ab","signalStrength":-78},{"macAddress":"cd:ef:01:23:45:56","signalStrength":-76}]}' http://127.0.0.1:8088/v1/geolocate
# - Cell: curl -d '{"cellTowers":[{ "radioType": "lte", "mobileCountryCode": 310, "mobileNetworkCode": 260, "locationAreaCode": NNNNN, "cellId": MMMMMMMM }]}' http://127.0.0.1:8088/v1/geolocate
#
## wigle docs:
# - IRC: #wigle on WiGLE.net:6667
# - API: <https://api.wigle.net/swagger>
# API return codes:
# - 429: "too many queries today."
#
# rate limiting:
# - as a new user you'll be limited to something ridiculous like 5 queries per day.
# supposedly this improves "based on history and participation".
# - source: <https://api.wigle.net/swagger#/Network%20search%20and%20information%20tools/search_2>
# - "API for some functions is limited on a daily basis for all users for the time being, but if you'd like increased access, please email us (include your username and usecase) at WiGLE-admin@wigle.net."
# - source: <https://wigle.net/account>
{ pkgs, ... }:
{
sane.programs.ols = {
packageUnwrapped = pkgs.geoclue-ols;
fs.".config/ols/cell.db".symlink.target = pkgs.runCommandLocal "cell.db" {
nativeBuildInputs = [ pkgs.geoclue-ols ];
} ''
cellid-ols-import -o "$out" "${pkgs.opencellid}"
'';
persist.byStore.private = [
".local/share/ols"
];
secrets.".config/ols/ols.toml" = ../../../secrets/common/ols.toml.bin;
services.ols = {
description = "ols: Offline Location Service";
command = "ols 2>&1"; # XXX: it logs to stderr, and my s6 infrastructure apparently doesn't handle that
partOf = [ "graphical-session" ];
};
};
}

View File

@ -0,0 +1,6 @@
{ pkgs, ... }:
{
sane.programs.pactl = {
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.pulseaudio "bin/pactl";
};
}

View File

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

View File

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

View File

@ -0,0 +1,9 @@
{ config, lib, ... }:
let
cfg = config.sane.programs.qmk-udev-rules;
in
{
sane.programs.qmk-udev-rules.sandbox.enable = false;
services.udev.packages = lib.mkIf cfg.enabled [ cfg.package ];
}

View File

@ -116,6 +116,7 @@ in
fs.".config/rofi/config.rasi".symlink.target = ./config.rasi;
fs."Apps".symlink.target = ".local/share/applications/rofi-applications.desktop";
fs."WiFi".symlink.target = ".local/share/applications/networkmanager_dmenu.desktop";
persist.byStore.cryptClearOnBoot = [
# this gets us a few things:
# - file browser remembers its last directory

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p sane-open
#!nix-shell -i bash -p bash -p sane-open
# use:
# rofi-run-command <handler>.desktop [cmd [args ...]]

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p gnused -p rofi -p wtype
#!nix-shell -i bash -p bash -p gnused -p rofi -p wtype
# "bookmarking"/snippets inspired by Luke Smith:
# - <https://www.youtube.com/watch?v=d_11QaTlf1I>

View File

@ -83,7 +83,7 @@ in
"jq"
"killall"
"playerctl"
"procps"
"procps" #< TODO: reduce to just those parts of procps which are really needed
"sane-open"
# "sway" #< TODO: circular dependency :-(
"wireplumber"

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p coreutils -p jq -p killall -p playerctl -p procps -p sane-open -p sway -p util-linux -p wireplumber
#!nix-shell -i bash -p bash -p coreutils -p jq -p killall -p playerctl -p procps -p sane-open -p sway -p util-linux -p wireplumber
# vim: set filetype=bash :
# input map considerations

View File

@ -279,5 +279,6 @@ in
".persist/private/.mozilla"
];
};
"sane-scripts.wipe".suggestedPrograms = [ "pkill" ];
};
}

View File

@ -0,0 +1,10 @@
{ ... }:
{
sane.programs.sane-sysload = {
sandbox.method = "bwrap";
sandbox.extraPaths = [
"/sys/class/power_supply"
"/sys/devices"
];
};
}

View File

@ -44,19 +44,19 @@ in
# XXX: /run/current-system symlink can't be cached without forcing regular mass rebuilds:
# mount it as if it were a directory instead.
"/run/current-system" = "";
} // lib.optionalAttrs config.hardware.opengl.enable {
} // lib.optionalAttrs config.hardware.graphics.enable {
"/run/opengl-driver" = let
gl = config.hardware.opengl;
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/opengl.nix>
gl = config.hardware.graphics;
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/graphics.nix>
package = pkgs.buildEnv {
name = "opengl-drivers";
paths = [ gl.package ] ++ gl.extraPackages;
};
in "${package}";
} // lib.optionalAttrs (config.hardware.opengl.enable && config.hardware.opengl.driSupport32Bit) {
} // lib.optionalAttrs (config.hardware.graphics.enable && config.hardware.graphics.enable32Bit) {
"/run/opengl-driver-32" = let
gl = config.hardware.opengl;
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/opengl.nix>
gl = config.hardware.graphics;
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/graphics.nix>
package = pkgs.buildEnv {
name = "opengl-drivers-32bit";
paths = [ gl.package32 ] ++ gl.extraPackages32;

View File

@ -0,0 +1,53 @@
# satellite-gtk: <https://codeberg.org/tpikonen/satellite>
# - presents GPS tracking *details* in a graphical way
# - shows which satellites are in view, their SNR, and the subset currently being used for triangulation
# - shows fix coordinates (time, lat, long, altitude, speed)
#
### how to read the bargraph (example):
#
# 14 | XXXXXXXXXXXXX 26
# 76 | =========== 23
# 15 | XXXXXXXX 16
# =
# +----------------|
# 0 30
#
# ^ this view means:
# - GPS is receiving from sats 14, 76, 15 (by PRN) -- this comes from GSGSV NMEA data (Satellites in-View)
# - sat 14 and 15 (shaded solid) are "active" -- this comes from GSGSA NMEA data ("Satellites Active")
# - i believe "active" means "this sat was used in the most recent solution"
#
### text fields
# - Modes (GP,GL,GA) ...
# one letter each, indicating the mode for GPS, GLONASS, Galileo sats:
# - N = no fix
# - A = autonomous
# - D = differential mode
# - E = estimated (dead reckoning)
# - etc
# - Active / in use sats
# - A/U, where A = number of satellites used in the previous fix,
# U = number of satellites mentioned in latest GNS + GGA messages
# - Receiving sats
# shows the count of sats with non-zero SNR, from GSV messages
# - Visible sats
# shows the count of sats from GSV messages
# - Age of update / fix
# - Sys. Time
# - Latitude
# - Longitude
# - Altitude
# - Geoidal separation
# - Speed
# - True Course
# - PDOP/HDOP/VDOP
# - shows how sensitive the reported location is to measurement error (low values are better)
# - HDOP = horizontal sensitivity, VDOP = vertical sensitivity, PDOP = positional (d) sensitivity
# - 1-2 => excellent fix
# - >10 => low confidence fix; recommended to discard the fix
# - <https://en.wikipedia.org/wiki/Dilution_of_precision_(navigation)>
#
{ ... }:
{
sane.programs.satellite = {};
}

View File

@ -44,6 +44,8 @@ in
".config/Signal"
];
buildCost = 1;
services.signal-desktop = {
description = "signal-desktop Signal Messenger client";
# depends = [ "graphical-session" ];

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p jq -p sway -p util-linux
#!nix-shell -i bash -p bash -p jq -p sway -p util-linux
help() {
echo "queries the focused window and apply an appropriate display-wide scale."

View File

@ -148,6 +148,8 @@ in
"fontconfig"
# "gnome.gnome-bluetooth" # XXX(2023/05/14): broken
# "gnome.gnome-control-center" # XXX(2023/06/28): depends on webkitgtk4_1
"networkmanager_dmenu"
"nwg-panel"
"pipewire"
"playerctl" # for waybar & particularly to have playerctld running
"rofi" # menu/launcher
@ -162,9 +164,9 @@ in
"swayidle" # enable if you need it
"swaynotificationcenter" # notification daemon
"switchboard" # network/bluetooth/sound control panel
"sysvol" # volume notifier
"syshud" # volume notifier
"unl0kr" # greeter
"waybar" # used by sway config
# "waybar"
"wdisplays" # like xrandr
"wireplumber" # used by sway config
"wl-clipboard"
@ -197,6 +199,7 @@ in
sandbox.whitelistAudio = true; # it runs playerctl directly
sandbox.whitelistDbus = [ "system" "user" ]; # to e.g. launch apps
sandbox.whitelistDri = true;
sandbox.whitelistS6 = true; #< for Super+L to start the screen locker service
sandbox.whitelistX = true; # sway invokes xwayland itself
sandbox.whitelistWayland = true;
sandbox.extraRuntimePaths = [
@ -226,7 +229,7 @@ in
'';
fs.".config/sway/config".symlink.target = pkgs.substituteAll {
src = ./sway-config;
src = ./config;
inherit (cfg.config)
extra_lines
font

View File

@ -32,6 +32,7 @@ in
};
sandbox.method = "bwrap";
sandbox.whitelistS6 = true;
sandbox.isolatePids = false; #< XXX: not sure why, but swaync segfaults under load without this!
};
sane.programs.swaync-fbcli = {
@ -61,6 +62,8 @@ in
name of entry in /sys/class/backlight which indicates the primary backlight.
'';
};
enableBacklight = mkEnableOption "include a backlight slider in the swaync dropdown (requires an active session with systemd-logind)";
enableMpris = (mkEnableOption "show the currently playing media in the swaync dropdown, and navigation buttons") // { default = true; };
};
};
default = {};
@ -116,27 +119,14 @@ in
env.GNOTIFICATION_BACKEND = "freedesktop";
fs.".config/swaync/style.css".symlink.target = ./style.css;
fs.".config/swaync/config.json".symlink.text = builtins.toJSON {
fs.".config/swaync/config.json".symlink.target = pkgs.writers.writeJSON "config.json" {
"$schema" = "/etc/xdg/swaync/configSchema.json";
positionX = "right";
positionY = "top";
layer = "overlay";
control-center-height = 600;
control-center-layer = "top";
layer-shell = true;
cssPriority = "user"; # "application"|"user". "user" in order to override the system gtk theme.
control-center-margin-top = 0;
control-center-margin-bottom = 0;
control-center-margin-right = 0;
control-center-margin-left = 0;
notification-2fa-action = true;
notification-inline-replies = false;
notification-icon-size = 64;
notification-body-image-height = 100;
notification-body-image-width = 200;
timeout = 30;
timeout-low = 5;
timeout-critical = 0;
fit-to-screen = true; #< have notification center take full vertical screen space
control-center-margin-right = 0;
control-center-margin-top = 0;
# control-center-width:
# pinephone native display is 720 x 1440
# - for compositor scale=2.0 => 360
@ -144,14 +134,28 @@ in
# - for compositor scale=1.6 => 450
# if it's set to something wider than the screen, then it overflows and items aren't visible.
control-center-width = 360;
control-center-height = 600;
notification-window-width = 360;
keyboard-shortcuts = true;
image-visibility = "when-available";
transition-time = 100;
hide-on-clear = true; #< hide control center when clicking "clear all"
cssPriority = "user"; # "application"|"user". "user" in order to override the system gtk theme.
fit-to-screen = true; #< have notification center take full vertical screen space
hide-on-action = true;
hide-on-clear = true; #< hide control center when clicking "clear all"
image-visibility = "when-available";
keyboard-shortcuts = true;
layer = "overlay";
layer-shell = true;
notification-2fa-action = true;
notification-body-image-height = 100;
notification-body-image-width = 200;
notification-icon-size = 64;
notification-inline-replies = false;
notification-window-width = 360;
positionX = "right";
positionY = "top";
script-fail-notify = true;
timeout = 30;
timeout-critical = 0;
timeout-low = 5;
transition-time = 100;
inherit scripts;
widgets = [
# what to show in the notification center (and in which order).
@ -164,9 +168,13 @@ in
"dnd"
"inhibitors"
"buttons-grid"
] ++ lib.optionals cfg.config.enableBacklight [
"backlight"
] ++ [
"volume"
] ++ lib.optionals cfg.config.enableMpris [
"mpris"
] ++ [
"notifications"
];
widget-config = {
@ -228,7 +236,10 @@ in
depends = [ "sound" ]; #< TODO: else it will NEVER see the pulse socket in its sandbox
partOf = [ "graphical-session" ];
command = "env G_MESSAGES_DEBUG=all swaync";
# N.B.: G_MESSAGES_DEBUG=all breaks DND mode:
# messages are still hidden, but are not silent!
# command = "env G_MESSAGES_DEBUG=all SWAYNC_DEBUG=1 swaync";
command = "swaync";
readiness.waitDbus = "org.freedesktop.Notifications";
};
};

View File

@ -24,7 +24,7 @@
# - SWAYNC_SUMMARY
# rules to use for testing. trigger with:
# - `notify-send --app-id=foo subject body` (etc)
# - `notify-send --app-name=foo subject body` (etc)
# should also be possible to trigger via any messaging app
fbcli-test-im = {
body = "test:message";

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p feedbackd -p procps -p swaynotificationcenter -p util-linux
#!nix-shell -i bash -p bash -p feedbackd -p procps -p swaynotificationcenter -p util-linux
# this script does some really unusual indirection with the `start` action:
# IT'S INTENTIONAL.

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p s6 -p s6-rc
#!nix-shell -i bash -p 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.
@ -17,7 +17,12 @@ log() {
checkActive() {
# 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
local s6Output=$(s6-rc -n 0 -b start "$service")
if [ -z "$s6Output" ]; then
echo true
else
echo false
fi
}
startService() {
log "startService: $service"

View File

@ -1,3 +1,6 @@
# BUGS
# - switchboard-plug-sound errors because
# GLib-GIO-ERROR **: Settings schema 'org.gnome.settings-daemon.plugins.media-keys' is not installed
{ pkgs, ... }:
{
sane.programs.switchboard = {
@ -6,7 +9,7 @@
# switchboard-plug-a11y
# switchboard-plug-about
# switchboard-plug-applications
switchboard-plug-bluetooth
# switchboard-plug-bluetooth #< TODO(2024/06/13): would be nice to have, but doesn't cross-compile
# switchboard-plug-datetime
# switchboard-plug-display # could be handy, but crashes
# switchboard-plug-keyboard
@ -22,6 +25,11 @@
switchboard-plug-sound
# switchboard-plug-wacom
];
xorg = pkgs.buildPackages.xorg; #< cross compilation fix (TODO: upstream)
};
sandbox.method = "bwrap";
sandbox.whitelistWayland = true;
sandbox.whitelistDbus = [ "system" ]; #< to speak with NetworkManager
sandbox.whitelistAudio = true; #< even with this, the sound plugin doesn't seem to work...
};
}

View File

@ -1,11 +1,15 @@
{ ... }:
{
sane.programs.sysvol = {
sane.programs.syshud = {
sandbox.method = "bwrap";
sandbox.whitelistAudio = true;
sandbox.whitelistWayland = true;
sandbox.extraPaths = [
"/sys/class/backlight" #< crashes if unable to access this directory
# "/sys/devices" #< only if you want it to actually show when the backlight changes
];
fs.".config/sys64/volume.css".symlink.text = ''
fs.".config/sys64/hud.css".symlink.text = ''
window {
background: transparent;
}
@ -53,13 +57,13 @@
}
'';
services."sysvol" = {
description = "sysvol: volume monitor/notifier";
services."syshud" = {
description = "syshud: volume monitor/notifier";
depends = [ "sound" ]; #< specifically wireplumber-pulse
partOf = [ "graphical-session" ];
# options:
# -p {0,1,2,3} to attach to top/right/bottom/left screen edge
# -p {bottom,left,right,top} to attach to the corresponding screen edge
# -t N for the notifier to be dismissed after N seconds (integer only)
# -T N reveal/hide transition time in milliseconds
# -m N to set the indicator this many pixels in from the edge.
@ -67,7 +71,7 @@
# -{H,W} N to set the height/width of the notifier, in px.
# -i N to set the size of the volume icon
# -P to hide percentage text
command = "sysvol -p 0 -t 1 -T 0 -m 22 -H 39 -W 256 -i 32 -P";
command = "syshud -p top -t 1 -T 0 -m 22 -H 39 -W 256 -i 32 -P";
};
};
}

View File

@ -3,7 +3,7 @@ let
cfg = config.sane.programs.unl0kr;
tty = "tty${builtins.toString cfg.config.vt}";
redirect-tty = pkgs.static-nix-shell.mkPython3Bin {
redirect-tty = pkgs.static-nix-shell.mkPython3 {
pname = "redirect-tty";
srcRoot = ./.;
};

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
# vim: set filetype=python :
"""

View File

@ -0,0 +1,17 @@
# - <https://nixos.wiki/wiki/Qmk>
# via lets one change the keymap on a QMK keyboard without reflashing
# - intro: <https://www.caniusevia.com/docs/specification>
{ config, lib, pkgs, ... }:
let
cfg = config.sane.programs.via;
in
{
sane.programs.via = {
enableFor.system = lib.mkIf (builtins.any (en: en) (builtins.attrValues cfg.enableFor.user)) true;
};
services.udev.packages = lib.mkIf cfg.enabled [ cfg.package pkgs.qmk-udev-rules ];
services.udev.extraRules = ''
# ZSA Ergodox Glow
SUBSYSTEMS=="usb", ATTRS{idVendor}=="3297", ATTRS{idProduct}=="4976", TAG+="uaccess"
'';
}

View File

@ -0,0 +1,5 @@
# wally-cli: allows flashing firmware to keyboards like ZSA Ergodox.
{ ... }:
{
sane.programs.wally-cli = {};
}

View File

@ -110,7 +110,7 @@ in
};
services.waybar = {
description = "swaybar graphical header bar/tray for sway";
description = "waybar status/topbar for sway";
partOf = [ "graphical-session" ];
# env G_MESSAGES_DEBUG=all

View File

@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p jq -p playerctl
#!nix-shell -i bash -p bash -p jq -p playerctl
status=$(playerctl status 2> /dev/null | tr 'A-Z' 'a-z')
if [ -z "$status" ]; then
status="inactive"

View File

@ -0,0 +1,11 @@
{ config, pkgs, ... }:
{
sane.programs.where-am-i = {
# packageUnwrapped = pkgs.linkIntoOwnPackage config.sane.programs.geoclue2.packageUnwrapped "libexec/geoclue-2.0/demos/where-am-i";
packageUnwrapped = pkgs.linkFarm "where-am-i" [{
# bring the `where-am-i` tool into a `bin/` directory so it can be invokable via PATH
name = "bin/where-am-i";
path = "${config.sane.programs.geoclue2.packageUnwrapped}/libexec/geoclue-2.0/demos/where-am-i";
}];
};
}

View File

@ -0,0 +1,8 @@
{ config, lib, ... }:
let
cfg = config.sane.programs.zsa-udev-rules;
in
{
sane.programs.zsa-udev-rules.sandbox.enable = false;
services.udev.packages = lib.mkIf cfg.enabled [ cfg.package ];
}

View File

@ -115,6 +115,7 @@ in
programs.zsh = lib.mkIf cfg.enabled {
enable = true;
shellAliases = {
":fg" = "fg";
":q" = "exit";
# common typos
"cd.." = "cd ..";

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