Compare commits

...

236 Commits

Author SHA1 Message Date
bcd467e60e NOT FOR MERGE: geoclue: disable polkit write access to the modem
unfortunately, geoclue misinterprets that as thinking it doesn't have *read* access either

hence, though it does prevent geoclue from changing GPS settings, it actually causes geoclue to simply not even read GPS (nor GSM)
2024-06-24 01:03:56 +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
74c188012a todo.md: install folio 2024-06-13 20:53:16 +00:00
e0c741427e ship "switchboard" program, for configuring bluetooth/network/sound 2024-06-13 19:51:19 +00:00
999a173001 sane-tag-music: --trackno "" fix-tags FOO can be used to clear FOOs track number field 2024-06-13 08:22:57 +00:00
330a64d820 feeds: add xorvoid.com 2024-06-13 04:46:12 +00:00
2e2f5dd373 scripts/sync: remove unnecessary sudo calls when mounting 2024-06-13 03:15:58 +00:00
5561dde31d readme: update for a flake-free world 2024-06-13 03:14:27 +00:00
c3ae60d71b flake.nix: remove (no longer used) 2024-06-13 03:09:45 +00:00
1c79209e23 scripts/sync: lift out of flake 2024-06-13 03:09:02 +00:00
6d1db1ee67 feeds: update metadata 2024-06-13 03:03:15 +00:00
88d462764f feeds: fix to work with scripts/update 2024-06-13 02:18:30 +00:00
8f634d9bb0 todo.md: address the sudo-related items 2024-06-13 01:30:44 +00:00
3e35210e4b systemd: allow wheel users to start/stop any service 2024-06-13 01:30:18 +00:00
04f4d330a8 programs: enable free 2024-06-13 01:09:48 +00:00
ce60e53b9a programs: add ps 2024-06-13 01:04:24 +00:00
3ff9f974a6 programs: enable watch 2024-06-13 00:59:34 +00:00
11e9ad5eca unl0kr.conf: fix formatting 2024-06-13 00:13:33 +00:00
bf99a64b89 unl0kr: fix that unl0kr wasnt always visible (so, wait for /dev/fb0 to appear before launch) 2024-06-13 00:13:19 +00:00
3b43562841 todo.md: address completed moby input-still-enabled-when-screen-off issue 2024-06-13 00:12:26 +00:00
131e43e975 scripts/deploy: avoid ssh-based copies to self 2024-06-13 00:12:00 +00:00
e34a9957e3 hosts/common/nix: migrate the nixpkgs-overlay integration point (part 2) 2024-06-12 23:32:18 +00:00
ea1a0b72b5 hosts/common/nix: migrate the nixpkgs-overlay integration point (part 1)
this has to be done in two steps to avoid nix-daemon bugs
2024-06-12 23:20:37 +00:00
aab9ed0d35 zsh: switch: pass through args 2024-06-12 23:09:35 +00:00
f477370e4c scripts/deploy: add more logging 2024-06-12 23:09:32 +00:00
b5fc8cfd4e scripts/deploy: when deploying all machines, dont let one failed deployment abort the whole job 2024-06-12 23:09:27 +00:00
4fdaacf8ad nit: use pkg.extend in place of pkgs.appendOverlays where applicable 2024-06-12 23:09:16 +00:00
f1705686b8 fix: dont double-apply overlays
previous behavior was that overlays were *implicitly* applied when i
imported nixpkgs, and then explicitly applied again later in the config.

for some reason i can't remove (or adjust?) the implicit application
without causing evals to hang w/o so much as any error message.
2024-06-12 23:08:04 +00:00
0d0fa8b37f nixpkgs: 2024-06-11 -> 2024-06-12 2024-06-12 09:42:55 +00:00
b5b39d1500 scripts/deploy: add the equivalent of my "pre-deploy" functionality 2024-06-12 09:04:17 +00:00
86482e922c scripts/update: add a --dry-run option 2024-06-12 08:44:02 +00:00
111c69b368 firefox.extensions.metamask: 11.16.8 -> 11.16.9 2024-06-12 08:37:59 +00:00
60c13d34a7 nixpkgs-wayland: 2024-06-08 -> 2024-06-12 2024-06-12 08:37:35 +00:00
823d064ab0 sops-nix: 2024-06-03 -> 2024-06-11 2024-06-12 08:35:54 +00:00
3f88d750c6 uassets: 2024-06-08 -> 2024-06-12 2024-06-12 08:35:34 +00:00
05f29ba01e sysvol: 2024-06-07 -> 2024-06-09 2024-06-12 08:35:22 +00:00
2b11bac1eb scripts: add an "update" script to update all my packages
it probably doesnt update feeds yet, though
2024-06-12 08:29:45 +00:00
86adc38537 zsh: fix switch alias for a post-flake world 2024-06-12 08:29:08 +00:00
b787289b39 scripts/deploy: if no host is specified, then deploy to the current host 2024-06-12 07:44:21 +00:00
63f3b8e89b handbrake: disable until i fix the build 2024-06-12 07:40:29 +00:00
448b8007ca scripts: remove outdated flake update script 2024-06-12 07:11:41 +00:00
9fc4119275 mesa-demos: deploy 2024-06-12 07:11:41 +00:00
8f1332797d crappy: dont auto-start messengers 2024-06-12 07:11:41 +00:00
368184e24f flake: add a crappy-min-next deploy target 2024-06-12 07:11:41 +00:00
c8e73d3f76 crappy: add user to "render" group 2024-06-12 07:11:41 +00:00
43da4955b7 crappy: deploy linux-exynos5-mainline kernel 2024-06-12 07:11:41 +00:00
46e9d5f758 programs: fix s6 deps when dbus isnt enabled 2024-06-12 07:11:41 +00:00
66a012b555 nixpkgs: 2024-06-08 -> 2024-06-11
i haven't actually deployed this yet: i'm pulling it for crappy-staging, but had to update all branches because the trust-dns patch didn't apply cleanly
2024-06-12 07:11:41 +00:00
fff965ab9b linux-postmarketos-exynos5: build with LIMA/MALI enabled as well (experimental) 2024-06-12 07:11:41 +00:00
406adde549 scripts/deploy: skip the signing step if we have no signing key 2024-06-12 07:11:14 +00:00
c9b2699c9f nixpkgs: fix sysvol patch hash 2024-06-12 07:03:23 +00:00
f91d3e35f3 flake: port deploy script to its own thing 2024-06-12 05:48:03 +00:00
4712ba9f2d check-nur: extract from the flake 2024-06-12 02:50:51 +00:00
03b2f2a433 rename health-check -> check-uninsane so i can expand the checks 2024-06-12 02:35:07 +00:00
51b1a6e679 default.nix: define attributes necessary to build any of my hosts or their packages 2024-06-12 02:21:50 +00:00
f148e5a580 pkgs: fix infinite recursion when evaluating nix-build -A MY_PKG 2024-06-12 01:18:17 +00:00
079f945f38 unl0kr: 2.0.0 -> 3.2.0 2024-06-12 00:49:26 +00:00
29cc7e4676 flake: add targets to deploy to crappy 2024-06-12 00:49:14 +00:00
187 changed files with 3282 additions and 1592 deletions

View File

@@ -2,6 +2,8 @@
# .❄≡We|_c0m3 7o m`/ f14k≡❄.
(er, it's not a flake anymore. welcome to my nix files.)
## What's Here
this is the top-level repo from which i configure/deploy all my NixOS machines:
@@ -29,11 +31,7 @@ you might specifically be interested in these files (elaborated further in #key-
## Using This Repo In Your Own Config
this should be a pretty "standard" flake. just reference it, and import either
- `nixosModules.sane` (for the modules)
- `overlays.pkgs` (for the packages)
or follow the instructions [here][NUR] to use it via the Nix User Repositories.
follow the instructions [here][NUR] to access my packages through the Nix User Repositories.
[NUR]: https://nur.nix-community.org/
@@ -41,19 +39,15 @@ or follow the instructions [here][NUR] to use it via the Nix User Repositories.
- `doc/`
- instructions for tasks i find myself doing semi-occasionally in this repo.
- `hosts/`
- the bulk of config which isn't factored with external use in mind.
- configs which aren't factored with external use in mind.
- that is, if you were to add this repo to a flake.nix for your own use,
you won't likely be depending on anything in this directory.
- `integrations/`
- code intended for consumption by external tools (e.g. the Nix User Repos)
- code intended for consumption by external tools (e.g. the Nix User Repos).
- `modules/`
- config which is gated behind `enable` flags, in similar style to nixpkgs'
`nixos/` directory.
- if you depend on this repo, it's most likely for something in this directory.
- `nixpatches/`
- literally, diffs i apply atop upstream nixpkgs before performing further eval.
- config which is gated behind `enable` flags, in similar style to nixpkgs' `nixos/` directory.
- if you depend on this repo for anything besides packages, it's most likely for something in this directory.
- `overlays/`
- exposed via the `overlays` output in `flake.nix`.
- predominantly a list of `callPackage` directives.
- `pkgs/`
- derivations for things not yet packaged in nixpkgs.
@@ -61,13 +55,12 @@ or follow the instructions [here][NUR] to use it via the Nix User Repositories.
- inline code for wholly custom packages (e.g. `pkgs/additional/sane-scripts/` for CLI tools
that are highly specific to my setup).
- `scripts/`
- scripts which aren't reachable on a deployed system, but may aid manual deployments
- scripts which aren't reachable on a deployed system, but may aid manual deployments.
- `secrets/`
- encrypted keys, API tokens, anything which one or more of my machines needs
read access to but shouldn't be world-readable.
- not much to see here
- not much to see here.
- `templates/`
- exposed via the `templates` output in `flake.nix`.
- used to instantiate short-lived environments.
- used to auto-fill the boiler-plate portions of new packages.

26
TODO.md
View File

@@ -2,7 +2,6 @@
- `rmDbusServices` may break sandboxing
- e.g. if the package ships a systemd unit which references $out, then make-sandboxed won't properly update that unit.
- `rmDbusServicesInPlace` is not affected
- moby: touchscreen input is still enabled when screen is off
- when moby wlan is explicitly set down (via ip link set wlan0 down), /var/lib/trust-dns/dhcp-configs doesn't get reset
- `ip monitor` can detect those manual link state changes (NM-dispatcher it seems cannot)
- or try dnsmasq?
@@ -16,7 +15,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`
@@ -25,6 +24,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
@@ -78,22 +84,21 @@
- it adds like 50-70ms launch time _on my laptop_. i'd hate to know how much that is on the pinephone.
- make dconf stuff less monolithic
- i.e. per-app dconf profiles for those which need it. possible static config.
- flatpak/spectrum has some stuff to proxy dconf per-app
- canaries for important services
- e.g. daily email checks; daily backup checks
- integrate `nix check` into Gitea actions?
#### sudo-free world
- `systemctl restart FOO`: needs `sudo`
- `systemctl daemon-reload`: needs sudo
- `watch ifconfig`: needs `SANEBOX_DISABLE=1`
### 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: swaync icon is stuck as the refresh icon
- nwg-panel: doesn't appear on all desktops
- nwg-panel: doesn't know that virtual-desktop 10/TV exists
- install apps:
- 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/>
@@ -103,6 +108,7 @@
- Gnome Highscore (retro games)?: <https://gitlab.gnome.org/World/highscore>
- better maps for mobile (Osmin (QtQuick)? Pure Maps (Qt/Kirigami)?
- note-taking app: <https://linuxphoneapps.org/categories/note-taking/>
- Folio is nice, uses standard markdown, though it only supports flat repos
- OSK overlay specifically for mobile gaming
- i.e. mock joysticks, for use with SuperTux and SuperTuxKart
- install mobile-friendly games:
@@ -125,11 +131,9 @@
- 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

View File

@@ -1,9 +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`
{ pkgs ? import <nixpkgs> {} }:
pkgs.appendOverlays [
(import ./overlays/all.nix)
]
{ ... }@args:
let
sane-nix-files = import ./pkgs/additional/sane-nix-files { };
in
import "${sane-nix-files}/impure.nix" args

7
flake.lock generated
View File

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

586
flake.nix
View File

@@ -1,586 +0,0 @@
# FLAKE FEEDBACK:
# - if flake inputs are meant to be human-readable, a human should be able to easily track them down given the URL.
# - this is not the case with registry URLs, like `nixpkgs/nixos-22.11`.
# - this is marginally the case with schemes like `github:nixos/nixpkgs`.
# - given the *existing* `git+https://` scheme, i propose expressing github URLs similarly:
# - `github+https://github.com/nixos/nixpkgs/tree/nixos-22.11`
# - this would allow for the same optimizations as today's `github:nixos/nixpkgs`, but without obscuring the source.
# a code reader could view the source being referenced simply by clicking the https:// portion of that URI.
# - need some way to apply local patches to inputs.
#
#
# DEVELOPMENT DOCS:
# - Flake docs: <https://nixos.wiki/wiki/Flakes>
# - Flake RFC: <https://github.com/tweag/rfcs/blob/flakes/rfcs/0049-flakes.md>
# - Discussion: <https://github.com/NixOS/rfcs/pull/49>
# - <https://serokell.io/blog/practical-nix-flakes>
#
#
# COMMON OPERATIONS:
# - update a specific flake input:
# - `nix flake lock --update-input nixpkgs`
{
outputs = {
self,
}@inputs:
let
inherit (builtins) attrNames elem listToAttrs map mapAttrs;
# redefine some nixpkgs `lib` functions to avoid the infinite recursion
# of if we tried to use patched `nixpkgs.lib` as part of the patching process.
mapAttrs' = f: set:
listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
optionalAttrs = cond: attrs: if cond then attrs else {};
# mapAttrs but without the `name` argument
mapAttrValues = f: mapAttrs (_: f);
nixpkgs' = import ./pkgs/additional/nixpkgs;
nixpkgsUnpatched = nixpkgs' { doPatch = false; localSystem = "x86_64-linux"; };
nixpkgsCompiledBy = { system, variant ? "master" }:
(nixpkgs' { inherit variant system; }).legacyPackages."${system}";
evalHost = { name, local, target, variant ? null, nixpkgs ? nixpkgs' { localSystem = local; system = target;} }: nixpkgs.nixos (
[
(optionalAttrs (variant == "light") {
sane.maxBuildCost = 2;
})
(optionalAttrs (variant == "min") {
sane.maxBuildCost = 0;
})
(import ./hosts/instantiate.nix { hostName = name; })
(import ./modules)
(nixpkgs.appendOverlays [ self.overlays.pkgs ]).sops-nix.nixosModules.sops
{
nixpkgs.overlays = [
self.overlays.sane-all
];
}
]
);
in {
nixosConfigurations = let
hosts = {
servo = { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
desko = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
desko-light = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; variant = "light"; };
lappy = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
lappy-light = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; variant = "light"; };
lappy-min = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; variant = "min"; };
moby = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
moby-light = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; variant = "light"; };
moby-min = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; variant = "min"; };
# crappy is technically armv7a, and armv7l uses only a _subset_ of the available ISA.
# but it's not as widely cached.
crappy = { name = "crappy"; local = "x86_64-linux"; target = "armv7l-linux"; };
crappy-min = { name = "crappy"; local = "x86_64-linux"; target = "armv7l-linux"; variant = "min"; };
crappy-7a = { name = "crappy"; local = "x86_64-linux"; target = "armv7a-linux"; variant = "min"; };
rescue = { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
};
hostsNext = mapAttrs' (h: v: {
name = "${h}-next";
value = v // {
nixpkgs = nixpkgs' {
localSystem = v.local;
system = v.target;
variant = "staging-next";
};
};
}) hosts;
hostsStaging = mapAttrs' (h: v: {
name = "${h}-staging";
value = v // {
nixpkgs = nixpkgs' {
localSystem = v.local;
system = v.target;
variant = "staging";
};
};
}) hosts;
in mapAttrValues evalHost (
hosts // hostsNext // hostsStaging
);
# unofficial output
# this produces a EFI-bootable .img file (GPT with a /boot partition and a system (/ or /nix) partition).
# after building this:
# - flash it to a bootable medium (SD card, flash drive, HDD)
# - resize the root partition (use cfdisk)
# - mount the part
# - chown root:nixbld <part>/nix/store
# - chown root:root -R <part>/nix/store/*
# - chown root:root -R <part>/persist # if using impermanence
# - populate any important things (persist/, home/colin/.ssh, etc)
# - boot
# - if fs wasn't resized automatically, then `sudo btrfs filesystem resize max /`
# - checkout this flake into /etc/nixos AND UPDATE THE FS UUIDS.
# - `nixos-rebuild --flake './#<host>' switch`
imgs = mapAttrValues (host: host.config.system.build.img) self.nixosConfigurations;
# unofficial output
hostConfigs = mapAttrValues (host: host.config) self.nixosConfigurations;
hostSystems = mapAttrValues (host: host.config.system.build.toplevel) self.nixosConfigurations;
hostPkgs = mapAttrValues (host: host.config.system.build.pkgs) self.nixosConfigurations;
hostPrograms = mapAttrValues (host: mapAttrValues (p: p.package) host.config.sane.programs) self.nixosConfigurations;
overlays = {
# N.B.: `nix flake check` requires every overlay to take `final: prev:` at defn site,
# hence the weird redundancy.
default = final: prev: self.overlays.pkgs final prev;
sane-all = final: prev: import ./overlays/all.nix final prev;
pkgs = final: prev: import ./overlays/pkgs.nix final prev;
preferences = final: prev: import ./overlays/preferences.nix final prev;
};
# this includes both our native packages and all the nixpkgs packages.
legacyPackages =
let
allPkgsFor = variant: additionalOverlays: system:
(nixpkgs' { inherit system variant; localSystem = "x86_64-linux"; })
.appendOverlays (
[
self.overlays.pkgs
] ++ additionalOverlays
);
allPkgsFor' = system: allPkgsFor
"master"
[(self: super: {
# build `pkgsNext.FOO` to build the package FOO from nixpkgs staging-next branch
pkgsNext = allPkgsFor "staging-next" [] system;
pkgsStaging = allPkgsFor "staging" [] system;
})]
system
;
in {
x86_64-linux = allPkgsFor' "x86_64-linux";
aarch64-linux = allPkgsFor' "aarch64-linux";
};
# extract only our own packages from the full set.
# because of `nix flake check`, we flatten the package set and only surface x86_64-linux packages.
packages = mapAttrs
(system: passthruPkgs: passthruPkgs.lib.filterAttrs
(name: pkg:
# keep only packages which will pass `nix flake check`, i.e. keep only:
# - derivations (not package sets)
# - packages that build for the given platform
(! elem name [ "feeds" "pythonPackagesExtensions" ])
&& (passthruPkgs.lib.meta.availableOn passthruPkgs.stdenv.hostPlatform pkg)
)
(
import ./pkgs { pkgs = passthruPkgs; }
)
)
# self.legacyPackages;
{
x86_64-linux = nixpkgs' { localSystem = "x86_64-linux"; };
}
;
apps."x86_64-linux" =
let
pkgs = self.legacyPackages."x86_64-linux";
sanePkgs = import ./pkgs { inherit pkgs; };
deployScript = host: addr: action: pkgs.writeShellScript "deploy-${host}" ''
set -e
host="${host}"
addr="${addr}"
action="${if action != null then action else ""}"
runOnTarget() {
# run the command ($@) on the machine we're deploying to.
# if that's a remote machine, then do it via ssh, else local shell.
if [ -n "$addr" ]; then
ssh "$addr" "$@"
else
"$@"
fi
}
nix build ".#nixosConfigurations.$host.config.system.build.toplevel" --out-link "./build/result-$host" "$@"
storePath="$(readlink ./build/result-$host)"
# mimic `nixos-rebuild --target-host`, in effect:
# - nix-copy-closure ...
# - nix-env --set ...
# - switch-to-configuration <boot|dry-activate|switch|test|>
# avoid the actual `nixos-rebuild` for a few reasons:
# - fewer nix evals
# - more introspectability and debuggability
# - sandbox friendliness (especially: `git` doesn't have to be run as root)
if [ -n "$addr" ]; then
sudo nix store sign -r -k /run/secrets/nix_signing_key "$storePath"
# add more `-v` for more verbosity (up to 5).
# builders-use-substitutes false: optimizes so that the remote machine doesn't try to get paths from its substituters.
# we already have all paths here, and the remote substitution is slow to check and SERIOUSLY flaky on moby in particular.
nix copy -vv --option builders-use-substitutes false --to "ssh-ng://$addr" "$storePath"
fi
if [ -n "$action" ]; then
runOnTarget sudo nix-env -p /nix/var/nix/profiles/system --set "$storePath"
runOnTarget sudo "$storePath/bin/switch-to-configuration" "$action"
fi
'';
deployApp = host: addr: action: {
type = "app";
program = ''${deployScript host addr action}'';
};
# pkg updating.
# a cleaner alternative lives here: <https://discourse.nixos.org/t/how-can-i-run-the-updatescript-of-personal-packages/25274/2>
# mkUpdater :: [ String ] -> { type = "app"; program = path; }
mkUpdater = attrPath: {
type = "app";
program = let
pkg = pkgs.lib.getAttrFromPath attrPath sanePkgs;
strAttrPath = pkgs.lib.concatStringsSep "." attrPath;
commandArgv = pkg.updateScript.command or pkg.updateScript;
command = pkgs.lib.escapeShellArgs commandArgv;
in builtins.toString (pkgs.writeShellScript "update-${strAttrPath}" ''
set -x
env UPDATE_NIX_NAME=${pkg.name} UPDATE_NIX_PNAME=${pkg.pname} UPDATE_NIX_OLD_VERSION=${pkg.version} UPDATE_NIX_ATTR_PATH=${strAttrPath} ${command}
'');
};
mkUpdatersNoAliases = opts: basePath: pkgs.lib.concatMapAttrs
(name: pkg:
if pkg.recurseForDerivations or false then {
"${name}" = mkUpdaters opts (basePath ++ [ name ]);
} else if pkg.updateScript or null != null then {
"${name}" = mkUpdater (basePath ++ [ name ]);
} else {}
)
(pkgs.lib.getAttrFromPath basePath sanePkgs);
mkUpdaters = { ignore ? [], flakePrefix ? [] }@opts: basePath:
let
updaters = mkUpdatersNoAliases opts basePath;
invokeUpdater = name: pkg:
let
fullPath = basePath ++ [ name ];
doUpdateByDefault = !builtins.elem fullPath ignore;
# in case `name` has a `.` in it, we have to quote it
escapedPath = builtins.map (p: ''"${p}"'') fullPath;
updatePath = builtins.concatStringsSep "." (flakePrefix ++ escapedPath);
in pkgs.lib.optionalString doUpdateByDefault (
pkgs.lib.escapeShellArgs [
"nix" "run" ".#${updatePath}"
]
);
in {
type = "app";
# top-level app just invokes the updater of everything one layer below it
program = builtins.toString (pkgs.writeShellScript
(builtins.concatStringsSep "-" (flakePrefix ++ basePath))
(builtins.concatStringsSep
"\n"
(pkgs.lib.mapAttrsToList invokeUpdater updaters)
)
);
} // updaters;
in {
help = {
type = "app";
program = let
helpMsg = builtins.toFile "nixos-config-help-message" ''
commands:
- `nix run '.#help'`
- show this message
- `nix run '.#update.pkgs'`
- updates every package
- `nix run '.#update.feeds'`
- updates metadata for all feeds
- `nix run '.#init-feed' <url>`
- `nix run '.#deploy.{desko,lappy,moby,servo}[-light|-test]' [nix args ...]`
- build and deploy the host
- `nix run '.#preDeploy.{desko,lappy,moby,servo}[-light]' [nix args ...]`
- copy closures to a host, but don't activate it
- or `nix run '.#preDeploy'` to target all hosts
- `nix run '.#check'`
- make sure all systems build; NUR evaluates
- `nix run '.#bench'`
- benchmark the eval time of common targets this flake provides
specific build targets of interest:
- `nix build '.#imgs.rescue'`
'';
in builtins.toString (pkgs.writeShellScript "nixos-config-help" ''
cat ${helpMsg}
echo ""
echo "complete flake structure:"
nix flake show --option allow-import-from-derivation true
'');
};
# wrangle some names to get package updaters which refer back into the flake, but also conditionally ignore certain paths (e.g. sane.feeds).
# TODO: better design
update = rec {
_impl.pkgs.sane = mkUpdaters { flakePrefix = [ "update" "_impl" "pkgs" ]; ignore = [ [ "sane" "feeds" ] ]; } [ "sane" ];
pkgs = _impl.pkgs.sane;
_impl.feeds.sane.feeds = mkUpdaters { flakePrefix = [ "update" "_impl" "feeds" ]; } [ "sane" "feeds" ];
feeds = _impl.feeds.sane.feeds;
};
init-feed = {
type = "app";
program = "${pkgs.feeds.init-feed}";
};
deploy = {
desko = deployApp "desko" "desko" "switch";
desko-light = deployApp "desko-light" "desko" "switch";
lappy = deployApp "lappy" "lappy" "switch";
lappy-light = deployApp "lappy-light" "lappy" "switch";
lappy-min = deployApp "lappy-min" "lappy" "switch";
moby = deployApp "moby" "moby" "switch";
moby-light = deployApp "moby-light" "moby" "switch";
moby-min = deployApp "moby-min" "moby" "switch";
moby-test = deployApp "moby" "moby" "test";
servo = deployApp "servo" "servo" "switch";
# like `nixos-rebuild --flake . switch`
self = deployApp "$(hostname)" "" "switch";
self-light = deployApp "$(hostname)-light" "" "switch";
self-min = deployApp "$(hostname)-min" "" "switch";
type = "app";
program = builtins.toString (pkgs.writeShellScript "deploy-all" ''
nix run '.#deploy.lappy'
nix run '.#deploy.moby'
nix run '.#deploy.desko'
nix run '.#deploy.servo'
'');
};
preDeploy = {
# build the host and copy the runtime closure to that host, but don't activate it.
desko = deployApp "desko" "desko" null;
desko-light = deployApp "desko-light" "desko" null;
lappy = deployApp "lappy" "lappy" null;
lappy-light = deployApp "lappy-light" "lappy" null;
lappy-min = deployApp "lappy-min" "lappy" null;
moby = deployApp "moby" "moby" null;
moby-light = deployApp "moby-light" "moby" null;
moby-min = deployApp "moby-min" "moby" null;
servo = deployApp "servo" "servo" null;
type = "app";
program = builtins.toString (pkgs.writeShellScript "predeploy-all" ''
# copy the -min/-light variants first; this might be run while waiting on a full build. or the full build failed.
nix run '.#preDeploy.moby-min' -- "$@"
nix run '.#preDeploy.lappy-min' -- "$@"
nix run '.#preDeploy.moby-light' -- "$@"
nix run '.#preDeploy.lappy-light' -- "$@"
nix run '.#preDeploy.desko-light' -- "$@"
nix run '.#preDeploy.lappy' -- "$@"
nix run '.#preDeploy.servo' -- "$@"
nix run '.#preDeploy.moby' -- "$@"
nix run '.#preDeploy.desko' -- "$@"
'');
};
sync = {
type = "app";
program = builtins.toString (pkgs.writeShellScript "sync-all" ''
RC_lappy=$(nix run '.#sync.lappy' -- "$@")
RC_moby=$(nix run '.#sync.moby' -- "$@")
RC_desko=$(nix run '.#sync.desko' -- "$@")
echo "lappy: $RC_lappy"
echo "moby: $RC_moby"
echo "desko: $RC_desko"
'');
};
sync.desko = {
# copy music from servo to desko
# can run this from any device that has ssh access to desko and servo
type = "app";
program = builtins.toString (pkgs.writeShellScript "sync-to-desko" ''
sudo mount /mnt/desko/home
${pkgs.sane-scripts.sync-music}/bin/sane-sync-music --compat /mnt/servo/media/Music /mnt/desko/home/Music "$@"
'');
};
sync.lappy = {
# copy music from servo to lappy
# can run this from any device that has ssh access to lappy and servo
type = "app";
program = builtins.toString (pkgs.writeShellScript "sync-to-lappy" ''
sudo mount /mnt/lappy/home
${pkgs.sane-scripts.sync-music}/bin/sane-sync-music --compress --compat /mnt/servo/media/Music /mnt/lappy/home/Music "$@"
'');
};
sync.moby = {
# copy music from servo to moby
# can run this from any device that has ssh access to moby and servo
type = "app";
program = builtins.toString (pkgs.writeShellScript "sync-to-moby" ''
sudo mount /mnt/moby/home
sudo mount /mnt/desko/home
sudo mount /mnt/servo/media/Books
# copy photos/screenshots from moby to desko:
${pkgs.rsync}/bin/rsync -arv --exclude servo-macros /mnt/moby/home/Pictures/ /mnt/desko/home/Pictures/moby/
# copy books from servo to moby; delete old/untracked ones, but keep KOreader state files (sdr)
${pkgs.rsync}/bin/rsync -arv --delete --exclude unprocessed --exclude '*.sdr' /mnt/servo/media/Books/ /mnt/moby/home/Books/local/servo/
# N.B.: limited by network/disk -> reduce job count to improve pause/resume behavior
${pkgs.sane-scripts.sync-music}/bin/sane-sync-music --compress --compat --jobs 4 /mnt/servo/media/Music /mnt/moby/home/Music "$@"
'');
};
check = {
type = "app";
program = builtins.toString (pkgs.writeShellScript "check-all" ''
nix run '.#check.nur'
RC0=$?
nix run '.#check.hostConfigs'
RC1=$?
nix run '.#check.rescue'
RC2=$?
echo "nur: $RC0"
echo "hostConfigs: $RC1"
echo "rescue: $RC2"
exit $(($RC0 | $RC1 | $RC2))
'');
};
check.nur = {
# `nix run '.#check-nur'`
# validates that my repo can be included in the Nix User Repository
type = "app";
program = builtins.toString (pkgs.writeShellScript "check-nur" ''
cd ${./.}/integrations/nur
NIX_PATH= NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1 nix-env -f . -qa \* --meta --xml \
--allowed-uris https://static.rust-lang.org \
--option restrict-eval true \
--option allow-import-from-derivation true \
--drv-path --show-trace \
-I nixpkgs=${nixpkgsUnpatched} \
-I nixpkgs-overlays=${./.}/hosts/common/nix/overlay \
-I ../../ \
| tee # tee to prevent interactive mode
'');
};
check.hostConfigs = {
type = "app";
program = let
checkHost = host: let
shellHost = pkgs.lib.replaceStrings [ "-" ] [ "_" ] host;
in ''
nix build -v '.#nixosConfigurations.${host}.config.system.build.toplevel' --out-link ./build/result-${host} -j2 "$@"
RC_${shellHost}=$?
'';
in builtins.toString (pkgs.writeShellScript
"check-host-configs"
''
# build minimally-usable hosts first, then their full image.
# this gives me a minimal image i can deploy or copy over, early.
${checkHost "lappy-min"}
${checkHost "moby-min"}
${checkHost "desko-light"}
${checkHost "moby-light"}
${checkHost "lappy-light"}
${checkHost "desko"}
${checkHost "lappy"}
${checkHost "servo"}
${checkHost "moby"}
${checkHost "rescue"}
# still want to build the -light variants first so as to avoid multiple simultaneous webkitgtk builds
${checkHost "desko-light-next"}
${checkHost "moby-light-next"}
${checkHost "desko-next"}
${checkHost "lappy-next"}
${checkHost "servo-next"}
${checkHost "moby-next"}
${checkHost "rescue-next"}
echo "desko: $RC_desko"
echo "lappy: $RC_lappy"
echo "servo: $RC_servo"
echo "moby: $RC_moby"
echo "rescue: $RC_rescue"
echo "desko-next: $RC_desko_next"
echo "lappy-next: $RC_lappy_next"
echo "servo-next: $RC_servo_next"
echo "moby-next: $RC_moby_next"
echo "rescue-next: $RC_rescue_next"
# i don't really care if the -next hosts fail. i build them mostly to keep the cache fresh/ready
exit $(($RC_desko | $RC_lappy | $RC_servo | $RC_moby | $RC_rescue))
''
);
};
check.rescue = {
type = "app";
program = builtins.toString (pkgs.writeShellScript "check-rescue" ''
nix build -v '.#imgs.rescue' --out-link ./build/result-rescue-img -j2
'');
};
bench = {
type = "app";
program = builtins.toString (pkgs.writeShellScript "bench" ''
doBench() {
attrPath="$1"
shift
echo -n "benchmarking eval of '$attrPath'... "
/run/current-system/sw/bin/time -f "%e sec" -o /dev/stdout \
nix eval --no-eval-cache --quiet --raw ".#$attrPath" --apply 'result: if result != null then "" else "unexpected null"' $@ 2> /dev/null
}
if [ -n "$1" ]; then
doBench "$@"
else
doBench hostConfigs
doBench hostConfigs.lappy
doBench hostConfigs.lappy.sane.programs
doBench hostConfigs.lappy.sane.users.colin
doBench hostConfigs.lappy.sane.fs
doBench hostConfigs.lappy.environment.systemPackages
fi
'');
};
};
templates = {
env.python-data = {
# initialize with:
# - `nix flake init -t '/home/colin/dev/nixos/#env.python-data'`
# then enter with:
# - `nix develop`
path = ./templates/env/python-data;
description = "python environment for data processing";
};
pkgs.make = {
# initialize with:
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.make'`
path = ./templates/pkgs/make;
description = "default Makefile-based derivation";
};
pkgs.python = {
# initialize with:
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.python'`
path = ./templates/pkgs/python;
description = "python package";
};
pkgs.rust-inline = {
# initialize with:
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.rust-inline'`
path = ./templates/pkgs/rust-inline;
description = "rust package and development environment (inline rust sources)";
};
pkgs.rust = {
# initialize with:
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.rust'`
path = ./templates/pkgs/rust;
description = "rust package fit to ship in nixpkgs";
};
};
};
}

View File

@@ -12,6 +12,7 @@
users.users.colin.initialPassword = "147147";
sane.programs.sway.enableFor.user.colin = true;
sane.programs.calls.enableFor.user.colin = false;
sane.programs.consoleMediaUtils.enableFor.user.colin = true;
sane.programs.epiphany.enableFor.user.colin = true;
@@ -21,6 +22,13 @@
sane.programs.signal-desktop.enableFor.user.colin = false;
sane.programs.wike.enableFor.user.colin = true;
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;
# sane.programs.pcGuiApps.enableFor.user.colin = false; #< errors!
sane.programs.blueberry.enableFor.user.colin = false; # bluetooth manager: doesn't cross compile!

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

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

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

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

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

@@ -82,7 +82,6 @@ let
'';
};
in
lib.mkIf false #< TODO: re-enable once confident of sandboxing
{
sane.persist.sys.byStore.plaintext = [
# TODO: mode? we need this specifically for the stats tracking in .config/
@@ -106,8 +105,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 +117,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 +159,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 +189,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

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

@@ -9,7 +9,7 @@
./ids.nix
./machine-id.nix
./net
./nix
./nix.nix
./persist.nix
./polyunfill.nix
./programs

View File

@@ -195,6 +195,7 @@ let
(fromDb "weekinethereumnews.com" // tech)
(fromDb "willow.phantoma.online") # wizard@xyzzy.link
(fromDb "xn--gckvb8fzb.com" // tech)
(fromDb "xorvoid.com" // tech)
(mkSubstack "astralcodexten" // rat // daily) # Scott Alexander
(mkSubstack "eliqian" // rat // weekly)
(mkSubstack "oversharing" // pol // daily)

View File

@@ -59,14 +59,18 @@
# note the import starts at repo root: this allows `./overlay/default.nix` to access the stuff at the root
# "nixpkgs-overlays=${../../..}/hosts/common/nix-path/overlay"
# as long as my system itself doesn't rely on NIXPKGS at runtime, we can point the overlays to git
# to avoid switching so much during development
"nixpkgs-overlays=/home/colin/dev/nixos/hosts/common/nix/overlay"
# to avoid `switch`ing so much during development.
# TODO: it would be nice to remove this someday!
# it's an impurity that touches way more than i need and tends to cause hard-to-debug eval issues
# when it goes wrong. should i port my `nix-shell` scripts to something more tailored to my uses
# and then delete `nixpkgs-overlays`?
"nixpkgs-overlays=/home/colin/dev/nixos/integrations/nixpkgs/nixpkgs-overlays.nix"
];
# 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

@@ -1,4 +0,0 @@
# XXX: NIX_PATH=...:nixpkgs-overlays=... will import every overlay in the directory
# so we prefer to give it a directory with just this *one* overlay, otherwise it imports conflicting overlays
# and gets stuck in a loop until it OOMs
import ../../../../overlays/all.nix

View File

@@ -50,6 +50,7 @@ in
"fd"
"file"
"forkstat" # monitor every spawned/forked process
"free"
# "fwupd"
"gawk"
"gdb" # to debug segfaults
@@ -84,6 +85,7 @@ in
"parted"
"pciutils"
"powertop"
"ps"
"pstree"
"ripgrep"
"s6-rc" # service manager
@@ -97,6 +99,7 @@ in
"usbutils" # lsusb
"util-linux" # lsblk, lscpu, etc
"valgrind"
"watch"
"wget"
"wirelesstools" # iwlist
# "xq" # jq for XML
@@ -294,6 +297,7 @@ in
"loupe" # image viewer
"mate.engrampa" # archive manager
"mepo" # maps viewer
"mesa-demos" # for eglinfo, glxinfo & other testing tools
"mpv"
"networkmanagerapplet" # for nm-connection-editor: it's better than not having any gui!
"ntfy-sh" # notification service
@@ -355,7 +359,7 @@ in
"gnome.gnome-disk-utility"
"gnome.nautilus" # file browser
# "gnome.totem" # video player, supposedly supports UPnP
"handbrake"
# "handbrake" #< TODO: fix build
"inkscape"
# "jellyfin-media-player"
"kdenlive"
@@ -570,10 +574,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
@@ -815,6 +815,8 @@ in
mercurial.sandbox.net = "clearnet";
mercurial.sandbox.whitelistPwd = true;
mesa-demos = {};
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
monero-gui.buildCost = 1;
# XXX: is it really safe to persist this? it doesn't have info that could de-anonymize if captured?
@@ -1117,6 +1119,8 @@ in
"tmp"
];
watch.sandbox.enable = false; #< it executes the command it's given
wdisplays.sandbox.method = "bwrap";
wdisplays.sandbox.whitelistWayland = true;
@@ -1173,13 +1177,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

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

@@ -45,12 +45,16 @@
./flare-signal.nix
./fontconfig.nix
./fractal.nix
./free.nix
./frozen-bubble.nix
./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
@@ -59,6 +63,7 @@
./gnome-weather.nix
./go2tv.nix
./gpodder.nix
./gpsd.nix
./grimshot.nix
./gst-device-monitor.nix
./gthumb.nix
@@ -86,6 +91,7 @@
./msmtp.nix
./nautilus.nix
./neovim.nix
./networkmanager_dmenu
./newsflash.nix
./nheko.nix
./nicotine-plus.nix
@@ -93,14 +99,19 @@
./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
./planify.nix
./portfolio-filemanager.nix
./playerctl.nix
./ps.nix
./rhythmbox.nix
./ripgrep.nix
./rofi
@@ -110,8 +121,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
@@ -130,7 +143,8 @@
./swayidle.nix
./swaylock.nix
./swaynotificationcenter
./sysvol.nix
./switchboard.nix
./syshud.nix
./tangram.nix
./tor-browser.nix
./tuba.nix
@@ -138,6 +152,7 @@
./vlc.nix
./waybar
./waylock.nix
./where-am-i.nix
./wike.nix
./wine.nix
./wireplumber.nix

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,9 @@
{ pkgs, ... }:
{
sane.programs.free = {
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.procps "bin/free";
sandbox.method = "bwrap";
sandbox.isolatePids = false;
};
}

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,62 @@
# 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 = [
"geoclue-demo-agent"
"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;
# prevent geoclue from modifying the GPS settings: i manage that myself, and trying to co-manage it with geoclue causes issues.
security.polkit.extraConfig = lib.optionalString cfg.enabled ''
polkit.addRule(function(action, subject) {
if (subject.user == "geoclue" && action.id == "org.freedesktop.ModemManager1.Device.Control") {
return polkit.Result.NO;
}
});
'';
services.geoclue2 = lib.mkIf cfg.enabled {
enable = true;
geoProviderUrl = "http://127.0.0.1:8088/v1/geolocate"; #< ols
};
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,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

@@ -1,7 +1,7 @@
# docs: <https://git.sr.ht/~mil/mepo>
# irc #mepo:irc.oftc.net
#
{ config, lib, ... }:
{
sane.programs.mepo = {
sandbox.method = "bwrap";
@@ -16,11 +16,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

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

@@ -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.python3Packages.ols;
fs.".config/ols/cell.db".symlink.target = pkgs.runCommandLocal "cell.db" {
nativeBuildInputs = [ pkgs.python3Packages.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.ps = {
packageUnwrapped = pkgs.linkIntoOwnPackage pkgs.procps "bin/ps";
sandbox.method = "bwrap";
sandbox.isolatePids = false;
};
}

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

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

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

@@ -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
@@ -161,9 +163,10 @@ in
"sway-contrib.grimshot" # used by sway config
"swayidle" # enable if you need it
"swaynotificationcenter" # notification daemon
"sysvol" # volume notifier
"switchboard" # network/bluetooth/sound control panel
"syshud" # volume notifier
"unl0kr" # greeter
"waybar" # used by sway config
# "waybar"
"wdisplays" # like xrandr
"wireplumber" # used by sway config
"wl-clipboard"
@@ -196,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 = [
@@ -225,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

@@ -0,0 +1,35 @@
# 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 = {
packageUnwrapped = with pkgs.pantheon; switchboard-with-plugs.override {
switchboardPlugs = [
# switchboard-plug-a11y
# switchboard-plug-about
# switchboard-plug-applications
# 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
# switchboard-plug-mouse-touchpad # changing settings here doesn't actually impact anything real
switchboard-plug-network
# switchboard-plug-notifications
# switchboard-plug-onlineaccounts
# switchboard-plug-pantheon-shell
# switchboard-plug-power # needs to be "unlocked" before it can do anything (like change display brightness)
# switchboard-plug-printers # requires cups
# switchboard-plug-security-privacy
# switchboard-plug-sharing
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

@@ -15,6 +15,15 @@ let
PATH=$PATH:$extraPath command -v "$1"
}
# give some time for the framebuffer device to appear;
# unl0kr depends on it but doesn't know to wait for it.
for _ in $(seq 25); do
if [ -e /dev/fb0 ]; then
break
fi
sleep 0.2
done
# TODO: make this more robust to failure.
# - if `unl0kr` fails, then the second `redirect-tty` sends a newline to `login`, causing it to exit and the service fails.
# - if `redirect-tty` fails, then... the service is left hanging.
@@ -134,8 +143,6 @@ in
# necessary for `sanebox` to be found. TODO: add this to every systemd service.
"/run/current-system/sw" # `/bin` is appended
];
# needed to find sanebox profiles (TODO: add this to every service)
environment.XDG_DATA_DIRS = "/run/current-system/sw/share";
serviceConfig.Type = "simple";
serviceConfig.Restart = "always";

View File

@@ -1,7 +1,7 @@
[general]
animations=false
#backend=fbdev|drm
#timeout=300
# backend=fbdev|drm
# timeout=300
[keyboard]
autohide=false
@@ -16,12 +16,14 @@ obscured=true
default=breezy-light
alternate=breezy-dark
#[input]
#keyboard=false
#pointer=false
#touchscreen=false
# [input]
# keyboard=false
# pointer=false
# touchscreen=false
#[quirks]
#fbdev_force_refresh=true
#terminal_prevent_graphics_mode=true
#terminal_allow_keyboard_input=true
# [quirks]
# fbdev_force_refresh=true
# terminal_prevent_graphics_mode=true
# TODO: terminal_allow_keyboard_input=true could be used to pipe my password
# straight into `login`, instead of the more convoluted redirect approach??
# terminal_allow_keyboard_input=true

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

@@ -115,6 +115,7 @@ in
programs.zsh = lib.mkIf cfg.enabled {
enable = true;
shellAliases = {
":fg" = "fg";
":q" = "exit";
# common typos
"cd.." = "cd ..";
@@ -186,7 +187,7 @@ in
};
function switch() {
nix run '.#deploy.self'
~/nixos/scripts/deploy "$@"
}
'';

View File

@@ -1,13 +1,17 @@
{ config, lib, sane-lib, ... }:
let
keysForHost = hostName: let
hostCfg = config.sane.hosts.by-name."${hostName}";
in {
"root@${hostName}" = hostCfg.ssh.host_pubkey;
"colin@${hostName}" = lib.mkIf (hostCfg.ssh.user_pubkey != null && hostCfg.ssh.authorized) hostCfg.ssh.user_pubkey;
};
hostKeys = builtins.map keysForHost (builtins.attrNames config.sane.hosts.by-name);
hostKeys = lib.mapAttrsToList
(hostName: hostCfg:
# generate `root@servo`, `colin@servo`, `root@servo-hn`, `colin@servo-hn`, ... as a single attrset:
lib.foldl' (acc: alias: acc // {
"root@${alias}" = hostCfg.ssh.host_pubkey;
"colin@${alias}" = lib.mkIf (hostCfg.ssh.user_pubkey != null && hostCfg.ssh.authorized) hostCfg.ssh.user_pubkey;
})
{}
hostCfg.names
)
config.sane.hosts.by-name;
in
{
sane.ssh.pubkeys = lib.mkMerge (hostKeys ++ [

View File

@@ -7,9 +7,12 @@ let
haltTimeout = 10;
in
{
# allow ordinary users to `reboot` or `shutdown`.
# source: <https://nixos.wiki/wiki/Polkit>
security.polkit.extraConfig = ''
/* allow ordinary users to:
* - reboot
* - shutdown
* source: <https://nixos.wiki/wiki/Polkit>
*/
polkit.addRule(function(action, subject) {
if (
subject.isInGroup("users")
@@ -24,6 +27,19 @@ in
return polkit.Result.YES;
}
})
/* allow members of wheel to:
* - systemctl daemon-reload
* - systemctl stop|start|restart SERVICE
*/
polkit.addRule(function(action, subject) {
if (subject.isInGroup("wheel") && (
action.id == "org.freedesktop.systemd1.reload-daemon" ||
action.id == "org.freedesktop.systemd1.manage-units"
)) {
return polkit.Result.YES;
}
})
'';
services.journald.extraConfig = ''

View File

@@ -22,6 +22,7 @@
"media" # servo
"networkmanager"
"nixbuild"
"render" # for crappy, /dev/dri/render*
"seat" # for sway, if using seatd
"systemd-journal" # allows to view other user's journals (esp system users)
"transmission" # servo

View File

@@ -1,10 +1,10 @@
# trampoline from flake.nix into the specific host definition, while doing a tiny bit of common setup
# args from flake-level `import`
{ hostName }:
{ hostName, variant }:
# module args
{ ... }:
{ lib, ... }:
{
imports = [
@@ -14,4 +14,14 @@
];
networking.hostName = hostName;
system.name = if variant == null then
hostName
else
"${hostName}-${variant}"
;
sane = lib.mkMerge [
(lib.mkIf (variant == "min") { maxBuildCost = 0; })
(lib.mkIf (variant == "light") { maxBuildCost = 2; })
];
}

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash
#!nix-shell -i bash -p bash
file="$1"
enc="$2"
nibbles="$3"

View File

@@ -128,36 +128,41 @@ in
# });
# boot.kernelPackages = with pkgs; linuxPackagesFor linux_6_1;
# boot.kernelPackages = with pkgs; linuxPackagesFor linux-exynos5-mainline;
boot.kernelPackages = with pkgs; linuxPackagesFor (linux-postmarketos-exynos5.override {
# linux = let version = "6.6.0-rc1"; rev = "6.6.0-rc6-bi-5264"; in {
# # src = pkgs.fetchzip {
# # url = "https://git.kernel.org/stable/t/linux-6.2.16.tar.gz";
# # };
# src = pkgs.fetchFromGitea {
# domain = "git.uninsane.org";
# owner = "colin";
# repo = "linux";
# rev = "v${rev}";
# hash = linuxSourceHashes."${rev}";
# };
# inherit version;
# modDirVersion = version;
# extraMakeFlags = [];
# };
# linux = linux_6_6;
# linux = linux_6_8;
# linux = linux_6_9;
linux = linux_latest;
# optimizeForSize = true;
# useEdpPanel = true;
revertPanelSimplePatch = true;
});
# boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-postmarketos-exynos5;
# boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux_latest.override {
# kernelPatches = [
# pkgs.linux-postmarketos-exynos5.sanePatches.revertPanelSimplePatch
# ];
# boot.kernelPackages = with pkgs; linuxPackagesFor (linux-postmarketos-exynos5.override {
# # linux = let version = "6.6.0-rc1"; rev = "6.6.0-rc6-bi-5264"; in {
# # # src = pkgs.fetchzip {
# # # url = "https://git.kernel.org/stable/t/linux-6.2.16.tar.gz";
# # # };
# # src = pkgs.fetchFromGitea {
# # domain = "git.uninsane.org";
# # owner = "colin";
# # repo = "linux";
# # rev = "v${rev}";
# # hash = linuxSourceHashes."${rev}";
# # };
# # inherit version;
# # modDirVersion = version;
# # extraMakeFlags = [];
# # };
# # linux = linux_6_6;
# # linux = linux_6_8;
# # linux = linux_6_9;
# linux = linux_latest;
# # optimizeForSize = true;
# # useEdpPanel = true;
# revertPanelSimplePatch = true;
# });
# boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-postmarketos-exynos5;
boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux-exynos5-mainline.override {
kernelPatches = [
pkgs.linux-postmarketos-exynos5.sanePatches.revertPanelSimplePatch
];
structuredExtraConfig = with lib.kernel; {
SECURITY = yes;
SECURITY_LANDLOCK = yes;
LSM = freeform "landlock,lockdown,yama,loadpin,safesetid,selinux,smack,tomoyo,apparmor,bpf";
};
});
system.build.u-boot = pkgs.buildUBoot {
defconfig = "snow_defconfig";

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p gnused
#!nix-shell -i bash -p bash -p gnused
# usage: install-bluetooth <source_dir> <destdir>
# source_dir contains plain-text files of any filename.
# for each file, this extracts the MAC and creates a symlink in destdir which

View File

@@ -45,6 +45,9 @@
actions.screenoff.delay = 300;
actions.screenoff.enable = true;
};
sane.programs.swaynotificationcenter.config = {
enableMpris = false; #< consumes too much screen real-estate
};
sane.programs.waybar.config = {
fontSize = 14;
@@ -56,6 +59,17 @@
modules.windowTitle = false;
# TODO: show modem state
};
sane.programs.nwg-panel.config = {
fontSize = 14;
height = 26;
windowIcon = false;
windowTitle = false;
mediaPrevNext = false;
mediaTitle = false;
sysload = false;
workspaceNumbers = [ "1" "2" "3" "4" "5" ];
workspaceHideEmpty = false;
};
sane.programs.zsh.config.showDeadlines = false; # unlikely to act on them when in shell
};

View File

@@ -80,6 +80,7 @@ in
protocol = [ "udp" ];
visibleTo.lan = true;
visibleTo.wan = cfg.visibleToWan;
visibleTo.doof = cfg.visibleToWan;
description = "colin-wireguard";
};

62
impure.nix Normal file
View File

@@ -0,0 +1,62 @@
# this entry-point exposes all packages, hosts, etc, but with no purity guarnatees.
# the intended way to use this is to first copy every .nix file and dependency in this repo to the nix store, then enter this file.
# entering this file *before* copying anything into the nix store can cause interesting
# race conditions or eval failures.
#
# see default.nix for a wrapper around this with better purity guarantees.
{ }:
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 (
[
(import ./hosts/instantiate.nix { hostName = name; inherit variant; })
(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 {}) // {
config = host.config;
fs = host.config.sane.fs;
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: {
# TODO: swap order: $host-{next,staging}-{min,light}:
# then lexicographically-adjacent targets would also have the minimal difference in closure,
# and the order in which each target should be built is more evident
"${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 {
inherit hosts;
} // (mkPkgs {})

View File

@@ -0,0 +1,5 @@
# this is the entry point for `nix-update`, used when i update the packages in this repo.
# nix-update needs to work on the actual out-of-store source,
# which means it can't call through the hermetic `default.nix` at the top of this repo,
# but rather needs the in-place `impure.nix` entry point.
import ../../impure.nix

View File

@@ -0,0 +1,5 @@
# this file exists so i can use my custom packages inside `nix-shell`.
# it works by using stock upstream `nixpkgs`
# and putting NIX_PATH=nixpkgs-overlays=/path/to/here on the nixbld environment.
#
[(import ../../overlays/all.nix)]

View File

@@ -4,6 +4,6 @@
"site_name": " bunnie's blog",
"site_url": "https://www.bunniestudios.com",
"title": "bunnie's blog",
"url": "https://www.bunniestudios.com/blog/?feed=rss2",
"velocity": 0.108
"url": "https://www.bunniestudios.com/blog/feed/",
"velocity": 0.12
}

View File

@@ -1,9 +1,9 @@
{
"description": "Radiolab",
"description": "Radiolab is on a curiosity bender. We ask deep questions and use investigative journalism to get the answers. A given episode might whirl you through science, legal history, and into the home of someone halfway across the world. The show is known for innovative sound design, smashing information into music. It is hosted by Lulu Miller and Latif Nasser.",
"is_podcast": true,
"site_name": "",
"site_url": "",
"title": "Radiolab",
"url": "https://feeds.feedburner.com/radiolab",
"velocity": 0.136
"url": "https://feeds.simplecast.com/EmVW7VGp",
"velocity": 0.138
}

View File

@@ -1,9 +1,9 @@
{
"description": "*** Named a best podcast of 2021 by Time, Vulture, Esquire and The Atlantic. ***\nEach Tuesday and Friday, Ezra Klein invites you into a conversation on something that matters. How do we address climate change if the political system fails to act? Has the logic of markets infiltrated too many aspects of our lives? What is the future of the Republican Party? What do psychedelics teach us about consciousness? What does sci-fi understand about our present that we miss? Can our food system be just to humans and animals alike?\n\nListen to this podcast in New York Times Audio, our new iOS app for news subscribers. Download now at nytimes.com/audioapp",
"description": "Each Tuesday and Friday, Ezra Klein invites you into a conversation on something that matters. How do we address climate change if the political system fails to act? Has the logic of markets infiltrated too many aspects of our lives? What is the future of the Republican Party? What do psychedelics teach us about consciousness? What does sci-fi understand about our present that we miss? Can our food system be just to humans and animals alike?\n\nListen to this podcast in New York Times Audio, our iOS app for news subscribers. Download now at nytimes.com/audioapp",
"is_podcast": true,
"site_name": "",
"site_url": "",
"title": "The Ezra Klein Show",
"url": "https://feeds.simplecast.com/82FI35Px",
"velocity": 0.264
"velocity": 0.257
}

View File

@@ -2,8 +2,8 @@
"description": "Long conversations with clever Nixers.",
"is_podcast": true,
"site_name": "",
"site_url": "",
"site_url": "https://feeds.transistor.fm",
"title": "Full Time Nix",
"url": "https://feeds.transistor.fm/full-time-nix",
"velocity": 0
"velocity": 0.048
}

View File

@@ -1,8 +1,8 @@
{
"description": "<p>Playful explorations of the rich past and exciting future that we're all building with our silly little computers. Hosted by Jimmy Miller and Ivan Reese.</p>",
"is_podcast": true,
"site_name": "",
"site_url": "",
"site_name": "Omny Studio",
"site_url": "https://www.omnycontent.com",
"title": "Future of Coding",
"url": "https://www.omnycontent.com/d/playlist/c4157e60-c7f8-470d-b13f-a7b30040df73/564f493f-af32-4c48-862f-a7b300e4df49/ac317852-8807-44b8-8eff-a7b300e4df52/podcast.rss",
"velocity": 0.028

View File

@@ -1,9 +1,9 @@
{
"description": "<p>The most unruly and least considered, most shameful among various Idiomdrottning components and libraries can be found here.</p>\n <p>To contact me, <a href=\"mailto:sandra.snan@idiomdrottning.org\">send mail to sandra.snan@idiomdrottning.org</a></p>",
"is_podcast": false,
"site_name": "Idiomdrottning",
"site_name": "I live like them already",
"site_url": "https://idiomdrottning.org",
"title": "Idiomdrottning",
"url": "https://idiomdrottning.org/blog",
"velocity": 0.402
"velocity": 0.867
}

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