Compare commits

...

235 Commits

Author SHA1 Message Date
3c5fee5d14 attempt to update swaynotificationcenter patch, but fail
the new version has problems: start swaync while one of the services is running, and then itll toggle that service on every control-center open -> close cycle
2023-11-08 21:26:42 +00:00
23c46079a9 image: allow configuring the sector size 2023-11-08 16:42:25 +00:00
df9ffcb7b1 zsh: auto-detect guiIntegrations feature 2023-11-08 15:33:15 +00:00
f4f1917ed6 rescue: remove extraneous generic-extlinux-compatible option 2023-11-08 15:33:15 +00:00
851b2cec88 rescue: disable persistence 2023-11-08 15:33:15 +00:00
28d4a4b065 persistence: move stores behind a byStore attr to support disabling persistence altogether (for e.g. rescue image) 2023-11-08 15:33:15 +00:00
7c5f5bd604 programs: add nvme, e2fsprogs to sysadminTools 2023-11-08 14:36:27 +00:00
7e4899832d wg-home: fix type error 2023-11-08 13:24:10 +00:00
226c4ba818 rescue: auto-login user 2023-11-08 13:18:30 +00:00
76b6b71879 mobile-nixos: pin to 2023-09-15 2023-11-08 12:13:50 +00:00
4951520584 flake: integrate rescue image building into the "check" target 2023-11-08 11:39:45 +00:00
e30d452254 flake: add help for building the rescue image 2023-11-08 11:35:32 +00:00
18a7598f62 programs: xdg-terminal-exec: move to gui programs 2023-11-08 11:31:49 +00:00
4d3e482174 zsh: remove vteIntegration from rescue image 2023-11-08 11:26:55 +00:00
68556222e2 fix rescue host build 2023-11-08 11:16:56 +00:00
2275fc20cd nixpatches: update hashes 2023-11-08 10:56:18 +00:00
7c247a6d39 initrd: add more helper (debugging) tools 2023-11-08 10:55:47 +00:00
1483dac941 cross: explain the webkitgtk situation better 2023-11-08 10:55:13 +00:00
e1a8c94ab9 programs: ship ddrescue 2023-11-06 23:57:48 +00:00
b0e66056ec WIP: signal-desktop-from-src: use node headers from electron.bin 2023-11-05 20:03:38 +00:00
08dd4ca641 sane-bt-add: leave a TODO for fixing InvalidSchema exceptions 2023-11-05 20:03:03 +00:00
f6eadd3696 devPkgs: add requests to python 2023-11-05 20:02:40 +00:00
b59685cc9d signal-desktop-from-src: get more working
no longer complains about ABI mismatches
2023-11-05 14:49:40 +00:00
c30e131aa7 signal-desktop-from-src: closer to working 2023-11-04 14:52:09 +00:00
5adf6c0194 snippets.txt: add billshare 2023-11-03 12:26:57 +00:00
6b7507384c sftpo: restart on failure (e.g. when it fails to bind address 2023-11-03 07:21:21 +00:00
e97d844380 signal-desktop-from-src: link in ringrtc, better-sqlite3
now it launches, but hangs at splashscreen
2023-11-02 15:52:23 +00:00
0628bd7880 ublock-origin: 1.52.3b17 -> 1.53.1b1 2023-11-02 10:35:54 +00:00
bee3b664c9 signal-desktop-from-src: remove comments which are no longer helpful 2023-11-02 10:25:49 +00:00
15cade99e7 signal-desktop-from-src: clean up a bit
still doesn't run, but the build process is cleaner
2023-11-02 10:24:23 +00:00
4150fab10b signal-desktop-from-src: get building (but it crashes at launch) 2023-11-02 09:10:08 +00:00
25e314c02e blogs: follow artemis.sh 2023-11-01 04:38:04 +00:00
ed0528fafa firefox: enable oversized scrollbars 2023-11-01 04:32:59 +00:00
c5ad11a243 nixpkgs: 2023-10-26 -> 2023-10-29; sops-nix; uninsane-dot-org
```
• Updated input 'nixpkgs-unpatched':
    'github:nixos/nixpkgs/63678e9f3d3afecfeafa0acead6239cdb447574c' (2023-10-26)
  → 'github:nixos/nixpkgs/0cbe9f69c234a7700596e943bfae7ef27a31b735' (2023-10-29)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/014e44d334a39481223a5d163530d4c4ca2e75cb' (2023-10-25)
  → 'github:Mic92/sops-nix/632c3161a6cc24142c8e3f5529f5d81042571165' (2023-10-29)
• Updated input 'sops-nix/nixpkgs-stable':
    'github:NixOS/nixpkgs/fb000224952bf7749a9e8b3779104ef7ea4465c8' (2023-10-21)
  → 'github:NixOS/nixpkgs/d87c5d8c41c9b3b39592563242f3a448b5cc4bc9' (2023-10-29)
• Updated input 'uninsane-dot-org':
    'git+https://git.uninsane.org/colin/uninsane?ref=refs/heads/master&rev=dea3e5cdd747ac321447ef00fa1e51423676aeda' (2023-10-08)
  → 'git+https://git.uninsane.org/colin/uninsane?ref=refs/heads/master&rev=2419750ca98fc04af42c91e50c49a29c68d465d2' (2023-10-30)
```
2023-10-31 14:24:39 +00:00
68de71084b flare-signal: leave more notes; disable 2023-10-31 07:57:30 +00:00
713bbffd7d new script: sane-wipe-flare 2023-10-31 06:54:53 +00:00
028689cf86 flakey tests: dont check gjs or tracker when emulating 2023-10-31 06:30:45 +00:00
5d34139da6 sane-deadlines: ceil the day countdown 2023-10-31 04:22:54 +00:00
626fe1946d flare-signal: get a better cross-compiled build (via emulation) 2023-10-31 01:33:42 +00:00
6d8f9edfd0 flare-signal: document problems 2023-10-30 14:02:24 +00:00
745362e05e ship flare-signal on all GUI platforms 2023-10-30 11:02:51 +00:00
000bae364e flare-signal: support cross compilation 2023-10-30 11:02:01 +00:00
3667484e80 fractal-nixified: doc: explain postPatch purpose 2023-10-30 10:48:22 +00:00
c459eb0118 flare-signal-nixified: working build 2023-10-30 10:47:58 +00:00
1c483992da flare-signal-nixified: init at 0.10.0 (deps build; flare itself does not) 2023-10-30 08:04:07 +00:00
55680b68b2 configure new program: flare (Signal GTK4 client) 2023-10-30 04:40:55 +00:00
b3f5bf4e80 koreader: disable isConnected patch 2023-10-30 01:52:47 +00:00
51995a7d95 update firefox-extension 2023-10-28 21:19:08 +00:00
462f9d3ab3 swaync: tune style and add 5g toggle to moby 2023-10-28 11:43:26 +00:00
fd00eaede8 net: add LTE connection details 2023-10-28 10:34:36 +00:00
85421f82c1 koreader: add a symlink for easier RSS browsing 2023-10-28 01:49:16 +00:00
e86d6934fd nixpkgs: 2023-10-24 -> 2023-10-26
```
• Updated input 'nixpkgs-unpatched':
    'github:nixos/nixpkgs/8efd5d1e283604f75a808a20e6cde0ef313d07d4' (2023-10-24)
  → 'github:nixos/nixpkgs/63678e9f3d3afecfeafa0acead6239cdb447574c' (2023-10-26)
```
2023-10-28 00:14:39 +00:00
db028dcfe2 fix servo build (IFD in iproute2) 2023-10-27 13:50:11 +00:00
ad2fef5b48 fix build from earlier nixpkgs update 2023-10-27 13:29:26 +00:00
66524685a9 koreader-from-src: build without emulation 2023-10-27 11:37:40 +00:00
1d7c54b20e todo.md: remove obsolete sxmo PATH task 2023-10-27 08:42:00 +00:00
d68cc761cc koreader-from-src: don't interrupt RSS sync on image DL failure 2023-10-27 08:41:02 +00:00
25c13705cd sane-bt-add: trim trailing space from the input URL 2023-10-26 10:38:28 +00:00
55e2aaf3a1 nixpkgs: 2023-10-19 -> 2023-10-24; sops-nix -> 2023-10-25; mobile-nixos
```
• Updated input 'mobile-nixos':
    'github:nixos/mobile-nixos/7cee346c3f8e73b25b1cfbf7a086a7652c11e0f3' (2023-10-01)
  → 'github:nixos/mobile-nixos/0251d0ae920a9882fd8527dc3fd9e3e54f122b2e' (2023-10-25)
• Updated input 'nixpkgs-unpatched':
    'github:nixos/nixpkgs/7c9cc5a6e5d38010801741ac830a3f8fd667a7a0' (2023-10-19)
  → 'github:nixos/nixpkgs/8efd5d1e283604f75a808a20e6cde0ef313d07d4' (2023-10-24)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/51186b8012068c417dac7c31fb12861726577898' (2023-10-15)
  → 'github:Mic92/sops-nix/014e44d334a39481223a5d163530d4c4ca2e75cb' (2023-10-25)
• Updated input 'sops-nix/nixpkgs-stable':
    'github:NixOS/nixpkgs/0e1cff585c1a85aeab059d3109f66134a8f76935' (2023-10-15)
  → 'github:NixOS/nixpkgs/fb000224952bf7749a9e8b3779104ef7ea4465c8' (2023-10-21)
```
2023-10-25 23:41:46 +00:00
94f2096219 remove outdated overlays which fixed tests which are no longer flakey 2023-10-25 14:44:20 +00:00
8f5f3933c1 cross: gvfs: update patch 2023-10-25 08:25:38 +00:00
e2d72f9e54 cross: snapper: push patches upstream 2023-10-24 17:01:08 +00:00
fc84aa88ee cross: remove upstreamed spdlog; add notes for upstream status of more packages 2023-10-24 16:53:55 +00:00
841fb4bf7a cross: hspell: push upstream 2023-10-24 16:53:24 +00:00
5f789b3db2 cross: gvfs: push upstream 2023-10-24 16:17:31 +00:00
49fbe5f4fa cross: gcr: push upstream 2023-10-24 15:28:48 +00:00
ec4b974f3d matrix-synapse: auto-register the ntfy-sh push gateway at launch 2023-10-24 14:47:59 +00:00
84ad85a81e mpv: types.string -> types.str 2023-10-24 13:07:16 +00:00
1af7450610 cross: gspell: push upstream 2023-10-24 13:06:52 +00:00
21912f0c4f overlays: gupnp: re-enable tests on x86 2023-10-24 12:32:05 +00:00
05513da298 rename host-pkgs -> hostPkgs 2023-10-24 12:25:39 +00:00
30486f4b4e geary: fix a typo 2023-10-24 10:29:40 +00:00
974ca87983 cross: remove upstreamed overlays 2023-10-24 10:28:01 +00:00
bb217ecd7b gsound: push cross compilation patch upstream 2023-10-24 10:27:33 +00:00
ed92fafdf6 todo.md: dont sleep when phone is ringing 2023-10-24 09:53:09 +00:00
228fd2353a cross compilation: support gnome.geary 2023-10-24 09:47:10 +00:00
69ac75131c apps: add geary 2023-10-24 04:50:31 +00:00
275f1ba49f trust-dns: 0.23.0 -> 0.24.0 2023-10-24 02:36:08 +00:00
501e79006c new script: sane-wipe-fractal 2023-10-24 00:41:05 +00:00
1ced3db806 moby: document more DRM_IOCTL_MODE_CREATE_DUMB 2023-10-24 00:15:13 +00:00
d1513b5816 moby: try out a scale of 1.6 2023-10-23 10:21:04 +00:00
a225b7e5f5 mpv: switch to wlshm vo backend on moby; default for desko 2023-10-23 08:36:43 +00:00
e7768572e5 fractal: update docs for fixing broken cache 2023-10-22 23:21:35 +00:00
a26a398181 todo.md: matrix/ntfy integrations 2023-10-22 23:21:20 +00:00
c59e9b09fc matrix: document push notification configuration 2023-10-22 14:47:52 +00:00
81c8af54a1 sxmo_suspend: deploy with verbose until i know its all working well 2023-10-22 13:01:33 +00:00
2d9ac4ca1e todo.md: remove stale items 2023-10-22 13:00:36 +00:00
a9f56d9216 sxmo_suspend.sh: be precise about which IP address we listen to for notifications 2023-10-22 12:53:32 +00:00
fb33ac6d1b sxmo_suspend: fix reversed getpeername -> getsockname 2023-10-22 12:36:57 +00:00
eaed914c8b sxmo_suspend: fix typo in getpeername 2023-10-22 12:14:57 +00:00
b10425f6b6 ntfy-waiter: never drop notifications, but rather sleep until client is ready to receive them 2023-10-22 12:10:52 +00:00
7541d5466e ntfy-waiter: add a todo for not dropping notifications (!) 2023-10-22 11:48:01 +00:00
644084f176 moby: disable ntfy-sh now that i've got a less racy notification method 2023-10-22 11:46:58 +00:00
baca7931ad static-nix-shell: add extraMakeWrapperArgs option 2023-10-22 11:45:44 +00:00
2ee7af064d sxmo_suspend.sh: be more precise in the wake condition 2023-10-22 11:28:10 +00:00
e1a80d6752 ntfy-waiter: forbid duplicate connections from the same IP
this is sort of a bandaid; it's still a bit iffy
2023-10-22 11:18:54 +00:00
523e859ee4 ntfy-waiter: more verbosity/debugging 2023-10-22 11:08:48 +00:00
230ca20017 sxmo_suspend.sh: explicitly shutdown the socket 2023-10-22 11:00:21 +00:00
30529182b0 sxmo_suspend.sh: allow mocking enough at runtime to run on desko 2023-10-22 10:28:17 +00:00
2947e6635d ntfy-waiter: move target from network -> default 2023-10-22 10:11:45 +00:00
3e1e7d49f8 sxmo_suspend.sh: open a ntfy socket 2023-10-22 10:08:59 +00:00
4894a68c62 sxmo_suspend: refactor 2023-10-22 09:45:38 +00:00
bd2775ded2 sxmo_suspend.sh: make the suspend time configurable 2023-10-22 09:41:36 +00:00
88ea557cd5 sxmo_suspend.sh: port to Python 2023-10-22 09:36:08 +00:00
3e8ad5b899 ntfy: implement a wrapper which converts ntfy subscriptions into a more specific wakeup signal 2023-10-22 06:11:49 +00:00
fafe7242f7 ntfy: refactor into multiple files 2023-10-22 04:16:24 +00:00
1a01a40e85 ntfy: move to own directory 2023-10-22 04:13:37 +00:00
f2f721234d nginx: link to docs 2023-10-22 04:12:34 +00:00
ea19eac1c9 update firefox-extensions: ether-metamask 11.2.0 -> 11.3.0; i2p 1.52.3b16 -> 1.52.3b17 2023-10-21 21:49:21 +00:00
ed1d4398a1 nixpkgs: 2023-10-16 -> 2023-10-19
```
• Updated input 'nixpkgs-unpatched':
    'github:nixos/nixpkgs/ca012a02bf8327be9e488546faecae5e05d7d749' (2023-10-16)
  → 'github:nixos/nixpkgs/7c9cc5a6e5d38010801741ac830a3f8fd667a7a0' (2023-10-19)
```
2023-10-21 11:50:37 +00:00
12e106ee2a moby: test a lima GPU timeout bugfix 2023-10-21 11:49:43 +00:00
d13007fc12 moby: migrate boot args from default.nix -> kernel.nix 2023-10-21 11:49:43 +00:00
2fa00b4c73 postfix: fix connectivity issues 2023-10-21 11:48:45 +00:00
c1e17a0693 nixpatches: try & abandon trust-dns updates 2023-10-21 10:15:03 +00:00
cd617cc034 coturn: document routability concerns 2023-10-20 23:22:34 +00:00
5607bae49b devPkgs: add lua 2023-10-20 23:07:02 +00:00
f70c467971 prosody: push to ntfy on incoming call 2023-10-20 23:06:44 +00:00
6cb5edbfff prosody: mod_sane_ntfy: hook to detect jingle calls 2023-10-20 10:39:57 +00:00
5a844762c2 prosody: ship a proof-of-concept hello world module 2023-10-20 10:25:42 +00:00
de9b1e6197 prosody: docs: not about watch:stanzas 2023-10-20 10:17:20 +00:00
f43bb446c8 prosody: move to own directory 2023-10-20 10:16:23 +00:00
fa8e014eae nixcache: fix typo 2023-10-20 06:22:59 +00:00
6191542805 nix-serve: port 5000 -> 5001; prosody: enable proxy65 on port 5000 2023-10-20 04:48:30 +00:00
b8f13cd965 prosody/coturn: debugging (this config works with JMP.chat) 2023-10-20 03:14:36 +00:00
ee2b1f245e koreader-from-src: 2023.06 -> unstable-2023-10-18 2023-10-20 00:44:03 +00:00
f11f91b9fc sane-bt-search: increase default result count 5 -> 12 2023-10-19 00:35:55 +00:00
296a48caf1 podcasts: unsub Trash Future (sorry, Cory) 2023-10-19 00:26:54 +00:00
f58bfb3c42 fractal: document a state corruption bug/fix 2023-10-18 22:16:28 +00:00
cbaaa984b6 phog: 0.1.4 -> 0.1.5 2023-10-18 22:11:26 +00:00
6e4f0af012 gpodder-adaptive: 3.11.3+1 -> 3.11.4+1 2023-10-18 22:11:07 +00:00
3942ae0f1b feeds: subscribe to Benjamin Mako 2023-10-18 21:57:56 +00:00
fa65b0b92e feeds: add Samana Harihareswara 2023-10-18 21:53:51 +00:00
ca998dc2be firefox-extensions: update (bypass-paywalls-clean, ether-metamask, sponsorblock, ublacklist 2023-10-18 21:46:48 +00:00
b6a2107b1c sane-bt-search: support filtering for books, in general 2023-10-18 21:46:11 +00:00
697ae02797 podcasts: The Daily: port to db 2023-10-18 21:37:12 +00:00
ab35a46e5f podcasts: sub Tech Wont Save Us, Trash Future 2023-10-18 21:35:36 +00:00
a6179b8234 feeds: unsub Emerge, Lateral, Witch Trials 2023-10-18 21:18:52 +00:00
d90aa693f9 podcasts: sort 2023-10-18 21:17:35 +00:00
b23c3cbf61 podcasts: move comments to the same line as the definition
this will facilitate sorting
2023-10-18 21:17:11 +00:00
55ad5dcc01 flake: check.host-configs: be more verbose 2023-10-18 06:00:07 +00:00
90b1215a89 s/types.string/types.str/ 2023-10-17 22:46:02 +00:00
a218ddb202 nixpkgs: 2023-10-11 -> 2023-10-16; sops-nix -> 2023-10-15
```
• Updated input 'nixpkgs-unpatched':
    'github:nixos/nixpkgs/5e4c2ada4fcd54b99d56d7bd62f384511a7e2593' (2023-10-11)
  → 'github:nixos/nixpkgs/ca012a02bf8327be9e488546faecae5e05d7d749' (2023-10-16)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/f995ea159252a53b25fa99824f2891e3b479d511' (2023-10-11)
  → 'github:Mic92/sops-nix/51186b8012068c417dac7c31fb12861726577898' (2023-10-15)
• Updated input 'sops-nix/nixpkgs-stable':
    'github:NixOS/nixpkgs/2f3b6b3fcd9fa0a4e6b544180c058a70890a7cc1' (2023-10-07)
  → 'github:NixOS/nixpkgs/0e1cff585c1a85aeab059d3109f66134a8f76935' (2023-10-15)
```
2023-10-17 22:43:07 +00:00
8dc7eff545 epiphany: mention WEBKIT_USE_SINGLE_WEB_PROCESS envvar 2023-10-17 22:42:15 +00:00
77b4e7ff09 slightly better prosody + coturn integration
still not able to receive incoming calls, but i pass more prosody self-checks
2023-10-17 09:43:55 +00:00
827d9626d6 ports: actually forward ovpns ports into the root namespace 2023-10-17 09:42:13 +00:00
cdfcf1a46d sftpgo: dont activate until we have network 2023-10-17 09:41:07 +00:00
e8c4555be7 prosody: partial integration with coturn
still missing something, which breaks inbound calls
2023-10-17 01:16:59 +00:00
0092ccacbe ejabberd: ensure coturn isnt running 2023-10-17 01:16:36 +00:00
184e37e2dc derived-secrets: make the mode configurable
this should probably be moved into sane.fs proper at some point
2023-10-17 01:16:08 +00:00
8859b4cf8a programs: persist data better for spotify, brave, tor 2023-10-16 19:18:47 +00:00
5a2382f61c prosody: remove dead code 2023-10-16 08:05:00 +00:00
f6c56969bc xmpp: switch from ejabberd to prosody 2023-10-16 07:56:47 +00:00
1f0fad62a7 fractal-nixified: add missing "gst-plugins-good" dependency
this is necessary to play mp4. should be sent to upstream nixpkgs fractal-next package too
2023-10-16 00:40:14 +00:00
5b633d20bc fractal-nixified: add convenient "optimized" and "unoptimized" passthru attributes
override isn't exposed to 'nix build ...', so this gives a way to build the variants from CLI
2023-10-16 00:21:18 +00:00
a918aa0c2f sxmo: suspend: dont wake on ARP unless absolutely necessary
it *should* be handled by the WiFi chip's ARP offload
2023-10-15 06:52:41 +00:00
93a265f34a sxmo: fix typo: avoid wakelock if wowlan_bits are 0x0 2023-10-14 21:54:44 +00:00
b818972597 sxmo: decrease the LED blink frequency further, to 8s 2023-10-14 10:24:35 +00:00
476b481fd7 moby: dont ship the rtl8723cs *bluetooth* firmware
it seems to conflict with Wake on Lan
2023-10-14 10:20:47 +00:00
631235e56b moby: sxmo_suspend: comment for future work to wake on Dino activity 2023-10-14 10:19:57 +00:00
ea4063340d moby: prioritize headset audio out 2023-10-14 10:19:31 +00:00
f2ad69af1f linux-megous: disable keep-power-in-suspend patch 2023-10-14 09:44:57 +00:00
e34ca0fec9 rtl8723cs-wowlan: support wake on UDP 2023-10-14 02:59:22 +00:00
43464e658f rtl8723cs-wowlan: factor the Ip frame out of Tcp frame
that'll make it easier to support UDP in future
2023-10-14 02:56:02 +00:00
56070547b1 nixpkgs: 2023-10-09 -> 2023-10-11
```
• Updated input 'nixpkgs-unpatched':
    'github:nixos/nixpkgs/f99e5f03cc0aa231ab5950a15ed02afec45ed51a' (2023-10-09)
  → 'github:nixos/nixpkgs/5e4c2ada4fcd54b99d56d7bd62f384511a7e2593' (2023-10-11)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/6b32358c22d2718a5407d39a8236c7bd9608f447' (2023-10-09)
  → 'github:Mic92/sops-nix/f995ea159252a53b25fa99824f2891e3b479d511' (2023-10-11)
```
2023-10-13 19:10:44 +00:00
0593971917 linux-megous: test some wowlan patches 2023-10-13 10:29:16 +00:00
b77650219a sxmo_suspend: wake on a broadcast ARP query 2023-10-13 06:15:51 +00:00
ad1ebc0ed3 rtl8723cs-wowlan: implement --dest-mac flag 2023-10-13 06:13:19 +00:00
ae64493564 sxmo_suspend: match packet destination IP for TCP packets 2023-10-13 05:56:26 +00:00
1272b941c2 rtl8723cs-wowlan: tcp: add dest-ip option 2023-10-13 05:55:10 +00:00
3d63c33669 rtl8723cs-wowlan: fix get_ipaddrs to handle multiple "hostname" binaries on PATH 2023-10-13 05:45:40 +00:00
fcbc558de9 sxmo_suspend.sh: fix "time_start" typo 2023-10-13 05:43:30 +00:00
b180adcf48 RealtimeKit: disable 2023-10-13 03:35:00 +00:00
342c9bbbef sxmo_suspend: track wifi IRQ count 2023-10-13 02:28:29 +00:00
233faaadac zsh: better l/ll aliases with eza 2023-10-12 22:11:05 +00:00
aaf9dbac1e ship gdb, mercurial 2023-10-12 01:59:28 +00:00
b7d90c3b6d cross: graphicsmagick: remove reference to build coreutils 2023-10-12 01:11:27 +00:00
a4b54cd9c1 rpm: 4.18.1 -> 4.19.0 2023-10-12 00:00:54 +00:00
d6c5580fc3 rtl8723cs-wowlan: remove dependency on moreutils 2023-10-11 22:36:47 +00:00
7d63960e6f cross: doc: clarify that moreutils isnt ever going to cross 2023-10-11 22:32:01 +00:00
8dc1cbbbd2 programs: ship binutils-unwrapped instead of binutils
it has better cross compilation properties
2023-10-11 22:15:28 +00:00
6253995f6c moby: cross: avoid runtime dependency on binutils wrapper via dtrx 2023-10-11 22:06:59 +00:00
835397ad29 hspell: remove references to build perl from the output 2023-10-11 20:58:09 +00:00
042e6ae3f9 sxmo-utils-latest: 2023-10-10 -> 2023-10-11 2023-10-11 20:31:43 +00:00
5b5cfc40a8 cross: fix broken refs in snapper build 2023-10-11 20:24:49 +00:00
3cf636f681 cross: remove dated libavif hack
it builds upstream now
2023-10-11 19:44:44 +00:00
a5281c7f98 cross: document more runtime closure problems 2023-10-11 19:41:49 +00:00
30c7fd8b09 nixpatches: assign a version so that "nixpatches-patched-uninsane" package formats friendlier 2023-10-11 19:12:29 +00:00
710e4cc066 nixpkgs: 2023-10-06 -> 2023-10-09
```
• Updated input 'nixpkgs-unpatched':
    'github:nixos/nixpkgs/87828a0e03d1418e848d3dd3f3014a632e4a4f64' (2023-10-06)
  → 'github:nixos/nixpkgs/f99e5f03cc0aa231ab5950a15ed02afec45ed51a' (2023-10-09)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/d7380c38d407eaf06d111832f4368ba3486b800e' (2023-10-08)
  → 'github:Mic92/sops-nix/6b32358c22d2718a5407d39a8236c7bd9608f447' (2023-10-09)
```
2023-10-11 10:08:11 +00:00
8b4a0a916b noop: test but dont actually enable pre-emption 2023-10-11 10:08:11 +00:00
5cfde63d5d wowlan: document theory on wake failure 2023-10-11 10:01:15 +00:00
1cf442dffd sway: build without wrapperFeatures.gtk 2023-10-11 09:59:10 +00:00
6cda5cf49b moby: remove some build artifacts from the host/runtime closure 2023-10-11 09:58:44 +00:00
0a3e6b34c7 sxmo_hook_postwake.sh: prevent rapid re-entry into sleep 2023-10-11 07:53:41 +00:00
322ef2c333 mpv: fix cross compilation to have no build deps in closure 2023-10-11 06:46:32 +00:00
6ff72c83ae patch: mesa: dont depend on build python 2023-10-11 06:19:06 +00:00
dc40395136 linux-megous: build with SCHED_DEBUG=y 2023-10-11 05:39:47 +00:00
28a2042664 gPodder: store data in ~/.local/share/gPodder, not ~/gPodder 2023-10-11 05:14:20 +00:00
7aa3f1f989 cross: fix moreutils build 2023-10-11 02:55:33 +00:00
08c92151eb rtl8723cs-wowlan: automatically derive the IP address to watch for ARP packets on 2023-10-11 02:44:34 +00:00
5a753583bf sxmo: reduce the screenoff LED frequency 2s -> 5s
this should hopefully allow entering sleep more reliably
2023-10-11 02:41:12 +00:00
c3d0b6b486 sxmo-utils-latest: 2023-10-05 -> 2023-10-10 2023-10-11 01:30:43 +00:00
ff89819940 sxmo_suspend.sh: notes about wowlan and blocking suspend here 2023-10-11 00:58:49 +00:00
9a69d8bd0d ship eza (ls substitute) 2023-10-10 22:08:58 +00:00
091e525846 enable rtkit/RealtimeKit 2023-10-10 21:45:19 +00:00
6dd1d5759b wowlan: document a new failure mode/workaround 2023-10-10 21:33:34 +00:00
f3162544f7 firefox-extensions: update 2023-10-10 20:51:06 +00:00
1bf829dcf0 sxmo_suspend: rework time accounting to be more similar to upstream 2023-10-10 10:05:09 +00:00
760326b38b sxmo_suspend.sh: switch from sudo -> doas
idk, some path problem with sudo ending up in /etc/profiles/per-user/colin/bin/sudo
2023-10-10 09:50:13 +00:00
0293773e64 sxmo_suspend.sh: output formatting improvements 2023-10-10 09:47:41 +00:00
6b6a9504e4 sxmo_suspend.sh: invoke rtl8723cs-wowlan with expected permissions 2023-10-10 09:39:38 +00:00
2de947d96e wowlan: move the implementation into sxmo_suspend.sh instead of a systemd service 2023-10-10 09:26:48 +00:00
c493fcfd7f rtl8723cs-wowlan: iwprv -> iwpriv typo fix 2023-10-10 08:38:40 +00:00
85e5d30b0f wowlan module: port to rtl8723cs-wowlan python script 2023-10-10 08:34:02 +00:00
330864c866 moby: ship rtl8723cs-wowlan script 2023-10-10 08:03:45 +00:00
29dde0240b wowlan: define a script which can set the patterns at runtime
this will be a little easier to debug on the device itself
2023-10-10 08:03:45 +00:00
114df5efab wowlan: enable CONFIG_ARP_KEEP_ALIVE (experimental) 2023-10-10 05:24:57 +00:00
e28e60769a sxmo: postwake: show the human-readable wakeup reason 2023-10-10 03:21:23 +00:00
bc8cf58b5a sxmo: inputhandler: map powerx3 from screenoff state 2023-10-10 00:02:31 +00:00
d740dbe049 sxmo-utils: fix some forgotten superd users to systemd 2023-10-09 22:18:07 +00:00
0eb8244897 sxmo: doc: link to Aren's SXMO fork 2023-10-09 22:05:37 +00:00
69fe55961f sxmo: link poweroff/reboot hooks into user hooks dir 2023-10-09 20:37:51 +00:00
aa18af8635 sxmo-utils: apply documentation-related patches 2023-10-09 20:25:48 +00:00
d47ed3dec9 nixpkgs: 2023-10-03 -> 2023-10-06; sops-nix -> 2023-10-08; uninsane-dot-org
```
• Updated input 'nixpkgs-unpatched':
    'github:nixos/nixpkgs/81e8f48ebdecf07aab321182011b067aafc78896' (2023-10-03)
  → 'github:nixos/nixpkgs/87828a0e03d1418e848d3dd3f3014a632e4a4f64' (2023-10-06)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/746c7fa1a64c1671a4bf287737c27fdc7101c4c2' (2023-10-03)
  → 'github:Mic92/sops-nix/d7380c38d407eaf06d111832f4368ba3486b800e' (2023-10-08)
• Updated input 'sops-nix/nixpkgs-stable':
    'github:NixOS/nixpkgs/dbe90e63a36762f1fbde546e26a84af774a32455' (2023-10-01)
  → 'github:NixOS/nixpkgs/2f3b6b3fcd9fa0a4e6b544180c058a70890a7cc1' (2023-10-07)
• Updated input 'uninsane-dot-org':
    'git+https://git.uninsane.org/colin/uninsane?ref=refs/heads/master&rev=1f588493031168d92a1e60705f26aaf4b2cdc07e' (2023-10-03)
  → 'git+https://git.uninsane.org/colin/uninsane?ref=refs/heads/master&rev=dea3e5cdd747ac321447ef00fa1e51423676aeda' (2023-10-08)
```
2023-10-09 08:21:41 +00:00
045b5f0294 sxmo: finish porting to systemd (everything tested works now) 2023-10-09 00:25:03 +00:00
45e5752a05 journald: dont compress the journal 2023-10-09 00:25:03 +00:00
2b39cfb57e sxmo-utils: add deps via PATH suffix, not prefix
that makes them overridable by the user, more easily
2023-10-09 00:25:03 +00:00
1ffaa232d8 sxmo: bemenu: configure via package override, not profile
this is just easier to integrate, rather than ensuring everywhere gets
the env var
2023-10-09 00:25:03 +00:00
a9ddfb2752 WIP: sxmo: port to systemd 2023-10-09 00:25:03 +00:00
4682ca32e2 wowlan: document another failure 2023-10-09 00:25:03 +00:00
b8ae4a284d linux-megous: revert LPS patch until i know its really an improvement 2023-10-09 00:25:03 +00:00
f3c60ad136 sxmo: revert the sxmo_log patch: tee is good enough 2023-10-09 00:25:03 +00:00
3c6c70ba9f sxmo: suspend: dump wowlan_last_wake_reason on wakeup 2023-10-09 00:25:03 +00:00
c0feffef1e sxmo: simplify suspend hook and cap suspend time to just 5min 2023-10-09 00:25:03 +00:00
6e80d4dfdf sxmo: inline the sxmo_suspend.sh script
this is exactly how it presently appears upstream (less shebang/comment changes)
2023-10-09 00:25:03 +00:00
1f73573fe3 stepmania: include link to nix definition in the game dir 2023-10-08 02:41:00 +00:00
170 changed files with 62184 additions and 1323 deletions

15
TODO.md
View File

@@ -1,7 +1,7 @@
## BUGS
- why i need to manually restart `wireguard-wg-ovpns` on servo periodically
- else DNS fails
- fix epiphany URL bar input on moby
- ringer (i.e. dino incoming call) doesn't prevent moby from sleeping
## REFACTORING:
@@ -30,6 +30,8 @@
## IMPROVEMENTS:
### security/resilience
- matrix/ntfy: automatically add the ntfy.uninsane.org push URL as part of synapse launch
- ntfy: use a more secure topic
- validate duplicity backups!
- encrypt more ~ dirs (~/archives, ~/records, ..?)
- best to do this after i know for sure i have good backups
@@ -59,6 +61,7 @@
- this is a problem of playerctld, i guess
- add option to change audio output
- fix colors (red alert) to match overall theme
- extend width to 100% of portrait mode
- moby: tune GPS
- run only geoclue, and not gpsd, to save power?
- tune QGPS setting in eg25-control, for less jitter?
@@ -70,12 +73,6 @@
- sxmo: port to swaybar like i use on desktop
- users in #sxmo claim it's way better perf
- sxmo: fix youtube scripts (package youtube-cli)
- sxmo: don't put all deps on PATH
- maybe: use resholve to hard-code them
- this is the most "correct", but least patchable
- maybe: express each invocation as a function in sxmo_common.sh
- this will require some patching to handle `exec <foo>` style
- maybe: save original PATH and reset it before invoking user files
- moby: theme GTK apps (i.e. non-adwaita styles)
- combine multiple icon themes to get one which has the full icon set?
- get adwaita-icon-theme to ship everything even when cross-compiled?
@@ -104,10 +101,6 @@
- add `pkgs.impure-cached.<foo>` package set to build things with ccache enabled
- every package here can be auto-generated, and marked with some env var so that it doesn't pollute the pure package set
- would be super handy for package prototyping!
- why does nixos-rebuild switch take 5 minutes when net is flakey?
- trying to auto-mount servo?
- something to do with systemd services restarting/stalling
- maybe wireguard & its refresh operation, specifically?
- get moby to build without binfmt emulation (i.e. make all emulation explicit)
- then i can distribute builds across servo + desko, and also allow servo to pull packages from desko w/o worrying about purity

33
flake.lock generated
View File

@@ -21,26 +21,27 @@
"mobile-nixos": {
"flake": false,
"locked": {
"lastModified": 1696124168,
"narHash": "sha256-EzGHYAR7rozQQLZEHbKEcb5VpUFGoxwEsM0OWfW4wqU=",
"lastModified": 1694749521,
"narHash": "sha256-MiVokKlpcJmfoGuWAMeW1En7gZ5hk0rCQArYm6P9XCc=",
"owner": "nixos",
"repo": "mobile-nixos",
"rev": "7cee346c3f8e73b25b1cfbf7a086a7652c11e0f3",
"rev": "d25d3b87e7f300d8066e31d792337d9cd7ecd23b",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "d25d3b87e7f300d8066e31d792337d9cd7ecd23b",
"repo": "mobile-nixos",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1696123266,
"narHash": "sha256-S6MZEneQeE4M/E/C8SMnr7B7oBnjH/hbm96Kak5hAAI=",
"lastModified": 1698544399,
"narHash": "sha256-vhRmPyEyoPkrXF2iykBsWHA05MIaOSmMRLMF7Hul6+s=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "dbe90e63a36762f1fbde546e26a84af774a32455",
"rev": "d87c5d8c41c9b3b39592563242f3a448b5cc4bc9",
"type": "github"
},
"original": {
@@ -52,11 +53,11 @@
},
"nixpkgs-unpatched": {
"locked": {
"lastModified": 1696375444,
"narHash": "sha256-Sv0ICt/pXfpnFhTGYTsX6lUr1SljnuXWejYTI2ZqHa4=",
"lastModified": 1698611440,
"narHash": "sha256-jPjHjrerhYDy3q9+s5EAsuhyhuknNfowY6yt6pjn9pc=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "81e8f48ebdecf07aab321182011b067aafc78896",
"rev": "0cbe9f69c234a7700596e943bfae7ef27a31b735",
"type": "github"
},
"original": {
@@ -82,11 +83,11 @@
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1696320910,
"narHash": "sha256-fbuEc6wylH+0VxG48lhPBK+SQJHfo2lusUwWHZNipIM=",
"lastModified": 1698548647,
"narHash": "sha256-7c03OjBGqnwDW0FBaBc+NjfEBxMkza+dxZGJPyIzfFE=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "746c7fa1a64c1671a4bf287737c27fdc7101c4c2",
"rev": "632c3161a6cc24142c8e3f5529f5d81042571165",
"type": "github"
},
"original": {
@@ -118,11 +119,11 @@
]
},
"locked": {
"lastModified": 1696306988,
"narHash": "sha256-I/OyJxIxu0n5h1eFqwVw0C6wTN3ewBXp2lGAdo1ur70=",
"lastModified": 1698634059,
"narHash": "sha256-+Oyv6vDyCtBzab/5cTG0nUrHD9gj7KgGfD4D1Rn4fCk=",
"ref": "refs/heads/master",
"rev": "1f588493031168d92a1e60705f26aaf4b2cdc07e",
"revCount": 208,
"rev": "2419750ca98fc04af42c91e50c49a29c68d465d2",
"revCount": 210,
"type": "git",
"url": "https://git.uninsane.org/colin/uninsane"
},

View File

@@ -49,7 +49,10 @@
mobile-nixos = {
# <https://github.com/nixos/mobile-nixos>
# only used for building disk images, not relevant after deployment
url = "github:nixos/mobile-nixos";
# TODO: replace with something else. commit `0f3ac0bef1aea70254a3bae35e3cc2561623f4c1`
# replaces the imageBuilder with a "new implementation from celun" and wildly breaks my use.
# pinning to d25d3b... is equivalent to holding at 2023-09-15
url = "github:nixos/mobile-nixos?ref=d25d3b87e7f300d8066e31d792337d9cd7ecd23b";
flake = false;
};
sops-nix = {
@@ -184,8 +187,8 @@
imgs = mapAttrValues (host: host.config.system.build.img) self.nixosConfigurations;
# unofficial output
host-pkgs = mapAttrValues (host: host.config.system.build.pkgs) self.nixosConfigurations;
host-programs = mapAttrValues (host: mapAttrValues (p: p.package) host.config.sane.programs) 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,
@@ -332,6 +335,9 @@
- `nix run '.#deploy-{lappy,moby,moby-test,servo}' [nixos-rebuild args ...]`
- `nix run '.#check'`
- make sure all systems build; NUR evaluates
specific build targets of interest:
- `nix build '.#imgs.rescue'`
'';
in builtins.toString (pkgs.writeShellScript "nixos-config-help" ''
cat ${helpMsg}
@@ -392,9 +398,12 @@
RC0=$?
nix run '.#check.host-configs'
RC1=$?
nix run '.#check.rescue'
RC2=$?
echo "nur: $RC0"
echo "host-configs: $RC1"
exit $(($RC0 | $RC1))
echo "rescue: $RC2"
exit $(($RC0 | $RC1 | $RC2))
'');
};
@@ -419,7 +428,7 @@
type = "app";
program = let
checkHost = host: ''
nix build '.#nixosConfigurations.${host}.config.system.build.toplevel' --out-link ./result-${host} -j2 $@
nix build -v '.#nixosConfigurations.${host}.config.system.build.toplevel' --out-link ./result-${host} -j2 $@
RC_${host}=$?
'';
in builtins.toString (pkgs.writeShellScript
@@ -439,6 +448,13 @@
''
);
};
check.rescue = {
type = "app";
program = builtins.toString (pkgs.writeShellScript "check-rescue" ''
nix build -v '.#imgs.rescue' --out-link ./result-rescue-img -j2
'');
};
};
templates = {

View File

@@ -33,7 +33,7 @@
# and so it just wouldn't handle any button inputs (sxmo_hook_inputhandler.sh not on path)
SXMO_DEVICE_NAME = "three_button_touchscreen";
};
package = pkgs.sxmo-utils-latest.overrideAttrs (base: {
package = (pkgs.sxmo-utils-latest.override { preferSystemd = true; }).overrideAttrs (base: {
postPatch = (base.postPatch or "") + ''
# after volume-button navigation mode, restore full keyboard functionality
cp ${./xkb_mobile_normal_buttons} ./configs/xkb/xkb_mobile_normal_buttons

View File

@@ -23,12 +23,6 @@
sane.zsh.showDeadlines = false; # unlikely to act on them when in shell
sane.services.wg-home.enable = true;
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;
sane.wowlan.enable = true;
sane.wowlan.patterns = [
{ ipv4.destPort = 22; } # wake on SSH
{ ipv4.srcPort = 2587; } # wake on `ntfy-sh` push from servo
{ arp.queryIp = [ 10 78 79 54 ]; } # wake when somebody is doing an ARP query against us
];
# XXX colin: phosh doesn't work well with passwordless login,
# so set this more reliable default password should anything go wrong
@@ -42,15 +36,20 @@
# sane.programs.consoleUtils.enableFor.user.colin = false;
# sane.programs.guiApps.enableFor.user.colin = false;
sane.programs.blueberry.enableFor.user.colin = false; # bluetooth manager: doesn't cross compile!
sane.programs.mercurial.enableFor.user.colin = false; # does not cross compile
sane.programs.sequoia.enableFor.user.colin = false;
sane.programs.tuiApps.enableFor.user.colin = false; # visidata, others, don't compile well
# disabled for faster deploys
sane.programs.soundconverter.enableFor.user.colin = false;
sane.programs.eg25-control.enableFor.user.colin = true;
sane.programs.ntfy-sh.config.autostart = true;
# enabled for easier debugging
sane.programs.eg25-control.enableFor.user.colin = true;
sane.programs.rtl8723cs-wowlan.enableFor.user.colin = true;
# sane.programs.ntfy-sh.config.autostart = true;
sane.programs.dino.config.autostart = true;
# sane.programs.calls.config.autostart = true;
sane.programs.mpv.config.vo = "wlshm"; #< see hosts/common/programs/mpv.nix for details
sane.programs.firefox.mime.priority = 300; # prefer other browsers when possible
# HACK/TODO: make `programs.P.env.VAR` behave according to `mime.priority`
@@ -85,8 +84,6 @@
}
'';
# sane.programs.mpv.enableFor.user.colin = true;
boot.loader.efi.canTouchEfiVariables = false;
# /boot space is at a premium. default was 20.
# even 10 can be too much
@@ -95,16 +92,6 @@
# mobile.boot.stage-1.enable = false;
# boot.initrd.systemd.enable = false;
# boot.initrd.services.swraid.enable = false; # attempt to fix dm_mod stuff
# disable proximity sensor.
# the filtering/calibration is bad that it causes the screen to go fully dark at times.
boot.blacklistedKernelModules = [ "stk3310" ];
# without this some GUI apps fail: `DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory`
# this is because they can't allocate enough video ram.
# the default CMA seems to be 32M.
# i was running fine with 256MB from 2022/07-ish through 2022/12-ish, but then the phone quit reliably coming back from sleep: maybe a memory leak?
# `cat /proc/meminfo` to see CmaTotal/CmaFree if interested in tuning this.
boot.kernelParams = [ "cma=512M" ];
# hardware.firmware makes the referenced files visible to the kernel, for whenever a driver explicitly asks for them.
# these files are visible from userspace by following `/sys/module/firmware_class/parameters/path`
@@ -115,7 +102,14 @@
# ov5640_af.bin (camera module)
# hardware.firmware = [ config.mobile.device.firmware ];
# hardware.firmware = [ pkgs.rtl8723cs-firmware ];
hardware.firmware = [ pkgs.linux-firmware-megous ];
hardware.firmware = [
(pkgs.linux-firmware-megous.override {
# rtl_bt = false probably means no bluetooth connectivity.
# N.B.: DON'T RE-ENABLE without first confirming that wake-on-lan works during suspend (rtcwake).
# it seems the rtl_bt stuff ("bluetooth coexist") might make wake-on-LAN radically more flaky.
rtl_bt = false;
})
];
system.stateVersion = "21.11";
@@ -133,7 +127,12 @@
# see pkgs/patched/alsa-ucm-conf for more info.
environment.variables.ALSA_CONFIG_UCM2 = "/run/current-system/sw/share/alsa/ucm2";
environment.pathsToLink = [ "/share/alsa/ucm2" ];
environment.systemPackages = [ pkgs.alsa-ucm-conf-sane ];
environment.systemPackages = [
(pkgs.alsa-ucm-conf-sane.override {
# internal speaker has a tendency to break :(
preferEarpiece = true;
})
];
systemd = let
ucm-env = config.environment.variables.ALSA_CONFIG_UCM2;
in {

View File

@@ -66,6 +66,24 @@ in
# target = "zImage"; # <-- confuses other parts of nixos :-(
};
# disable proximity sensor.
# the filtering/calibration is bad that it causes the screen to go fully dark at times.
boot.blacklistedKernelModules = [ "stk3310" ];
boot.kernelParams = [
# without this some GUI apps fail: `DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory`
# this is because they can't allocate enough video ram.
# see related nixpkgs issue: <https://github.com/NixOS/nixpkgs/issues/260222>
#
# the default CMA seems to be 32M.
# i was running fine with 256MB from 2022/07-ish through 2022/12-ish, but then the phone quit reliably coming back from sleep (phosh): maybe a memory leak?
# `cat /proc/meminfo` to see CmaTotal/CmaFree if interested in tuning this.
"cma=512M"
# 2023/10/20: potential fix for the lima (GPU) timeout bugs:
# - <https://gitlab.com/postmarketOS/pmaports/-/issues/805#note_890467824>
"lima.sched_timeout_ms=2000"
];
services.xserver.displayManager.job.preStart = ensureHWReady;
systemd.services.greetd.preStart = ensureHWReady;
}

View File

@@ -31,92 +31,7 @@
SXMO_LISGD_INPUT_DEVICE = "/dev/input/by-path/platform-1c2ac00.i2c-event";
# vol and power are detected correctly by upstream
### preferences
# notable bemenu options:
# - see `bemenu --help` for all
# -P, --prefix text to show before highlighted item.
# --scrollbar display scrollbar. (none (default), always, autohide)
# -H, --line-height defines the height to make each menu line (0 = default height). (wx)
# -M, --margin defines the empty space on either side of the menu. (wx)
# -W, --width-factor defines the relative width factor of the menu (from 0 to 1). (wx)
# -B, --border defines the width of the border in pixels around the menu. (wx)
# -R --border-radius defines the radius of the border around the menu (0 = no curved borders).
# --ch defines the height of the cursor (0 = scales with line height). (wx)
# --cw defines the width of the cursor. (wx)
# --hp defines the horizontal padding for the entries in single line mode. (wx)
# --fn defines the font to be used ('name [size]'). (wx)
# --tb defines the title background color. (wx)
# --tf defines the title foreground color. (wx)
# --fb defines the filter background color. (wx)
# --ff defines the filter foreground color. (wx)
# --nb defines the normal background color. (wx)
# --nf defines the normal foreground color. (wx)
# --hb defines the highlighted background color. (wx)
# --hf defines the highlighted foreground color. (wx)
# --fbb defines the feedback background color. (wx)
# --fbf defines the feedback foreground color. (wx)
# --sb defines the selected background color. (wx)
# --sf defines the selected foreground color. (wx)
# --ab defines the alternating background color. (wx)
# --af defines the alternating foreground color. (wx)
# --scb defines the scrollbar background color. (wx)
# --scf defines the scrollbar foreground color. (wx)
# --bdr defines the border color. (wx)
#
# colors are specified as `#RRGGBB`
# defaults:
# --ab "#222222"
# --af "#bbbbbb"
# --bdr "#005577"
# --border 3
# --cb "#222222"
# --center
# --cf "#bbbbbb"
# --fb "#222222"
# --fbb "#eeeeee"
# --fbf "#222222"
# --ff "#bbbbbb"
# --fixed-height
# --fn 'Sxmo 14'
# --hb "#005577"
# --hf "#eeeeee"
# --line-height 20
# --list 16
# --margin 40
# --nb "#222222"
# --nf "#bbbbbb"
# --no-overlap
# --no-spacing
# --sb "#323232"
# --scb "#005577"
# --scf "#eeeeee"
# --scrollbar autohide
# --tb "#005577"
# --tf "#eeeeee"
# --wrap
BEMENU_OPTS = let
bg = "#1d1721"; # slight purple
fg0 = "#d8d8d8"; # inactive text (light grey)
fg1 = "#ffffff"; # active text (white)
accent0 = "#1f5e54"; # darker but saturated teal
accent1 = "#418379"; # teal (matches nixos-bg)
accent2 = "#5b938a"; # brighter but muted teal
in lib.concatStringsSep " " [
"--wrap --scrollbar autohide --fixed-height"
"--center --margin 45"
"--no-spacing"
# XXX: font size doesn't seem to take effect (would prefer larger)
"--fn 'monospace 14' --line-height 22 --border 3"
"--bdr '${accent0}'" # border
"--scf '${accent2}' --scb '${accent0}'" # scrollbar
"--tb '${accent0}' --tf '${fg0}'" # title
"--fb '${accent0}' --ff '${fg1}'" # filter (i.e. text that's been entered)
"--hb '${accent1}' --hf '${fg1}'" # selected item
"--nb '${bg}' --nf '${fg0}'" # normal lines (even)
"--ab '${bg}' --af '${fg0}'" # alternated lines (odd)
"--cf '${accent0}' --cb '${accent0}'" # cursor (not very useful)
];
DEFAULT_COUNTRY = "US";
SXMO_AUTOROTATE = "1"; # enable auto-rotation at launch. has no meaning in stock/upstream sxmo-utils
@@ -141,9 +56,22 @@
# SXMO_ROTATION_GRAVITY = "12500"; # kinda uncomfortable when walking
SXMO_ROTATION_GRAVITY = "12000";
SXMO_SCREENSHOT_DIR = "/home/colin/Pictures"; # default: "$HOME"
# test new scales by running `swaymsg -- output DSI-1 scale x.y`
# sway/wayland scaling:
# - conflicting info out there on how scaling actually works
# at the least, for things where it matters (mpv), it seems like scale settings have 0 effect on perf
# ways to enforce scaling:
# - <https://wiki.archlinux.org/title/HiDPI>
# - `swaymsg -- output DSI-1 scale 2.0` (scales everything)
# - `dconf write /org/gnome/desktop/interface/text-scaling-factor 2.0` (scales ONLY TEXT)
# - `GDK_DPI_SCALE=2.0` (scales ONLY TEXT)
#
# application notes:
# - cozy: in landscape, playback position is not visible unless scale <= 1.7
# - if in a tab, then scale 1.6 is the max
# SXMO_SWAY_SCALE = "1.5"; # hard to press gPodder icons
SXMO_SWAY_SCALE = "1.8";
SXMO_SWAY_SCALE = "1.6";
# SXMO_SWAY_SCALE = "1.8";
# SXMO_SWAY_SCALE = "2";
SXMO_WORKSPACE_WRAPPING = "5"; # how many workspaces. default: 4

View File

@@ -4,12 +4,15 @@
./fs.nix
];
boot.loader.generic-extlinux-compatible.enable = true;
boot.loader.efi.canTouchEfiVariables = false;
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
# sane.persist.enable = false; # TODO: disable (but run `nix flake check` to ensure it works!)
sane.persist.enable = false;
sane.nixcache.enable = false; # don't want to be calling out to dead machines that we're *trying* to rescue
# auto-login at shell
services.getty.autologinUser = "colin";
# users.users.colin.initialPassword = "colin";
# docs: https://nixos.org/manual/nixos/stable/options.html#opt-system.stateVersion
system.stateVersion = "21.05";
}

View File

@@ -36,7 +36,7 @@
};
sane.fs."/mnt/persist/ext".mount = {};
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: this is overly broad; only need media and share directories to be persisted
{ user = "colin"; group = "users"; path = "/var/lib/uninsane"; }
];

View File

@@ -1,220 +1,233 @@
{ config, pkgs, ... }:
{ config, lib, pkgs, ... }:
let
portOpts = with lib; types.submodule {
options = {
visibleTo.ovpn = mkOption {
type = types.bool;
default = false;
};
};
};
in
{
networking.domain = "uninsane.org";
sane.ports.openFirewall = true;
sane.ports.openUpnp = true;
# view refused packets with: `sudo journalctl -k`
# networking.firewall.logRefusedPackets = true;
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
# Per-interface useDHCP will be mandatory in the future, so this generated config
# replicates the default behaviour.
networking.useDHCP = false;
networking.interfaces.eth0.useDHCP = true;
# XXX colin: probably don't need this. wlan0 won't be populated unless i touch a value in networking.interfaces.wlan0
networking.wireless.enable = false;
# this is needed to forward packets from the VPN to the host
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
# unless we add interface-specific settings for each VPN, we have to define nameservers globally.
# networking.nameservers = [
# "1.1.1.1"
# "9.9.9.9"
# ];
# use systemd's stub resolver.
# /etc/resolv.conf isn't sophisticated enough to use different servers per net namespace (or link).
# instead, running the stub resolver on a known address in the root ns lets us rewrite packets
# in the ovnps namespace to use the provider's DNS resolvers.
# a weakness is we can only query 1 NS at a time (unless we were to clone the packets?)
# there also seems to be some cache somewhere that's shared between the two namespaces.
# i think this is a libc thing. might need to leverage proper cgroups to _really_ kill it.
# - getent ahostsv4 www.google.com
# - try fix: <https://serverfault.com/questions/765989/connect-to-3rd-party-vpn-server-but-dont-use-it-as-the-default-route/766290#766290>
services.resolved.enable = true;
# without DNSSEC:
# - dig matrix.org => works
# - curl https://matrix.org => works
# with default DNSSEC:
# - dig matrix.org => works
# - curl https://matrix.org => fails
# i don't know why. this might somehow be interfering with the DNS run on this device (trust-dns)
services.resolved.dnssec = "false";
networking.nameservers = [
# use systemd-resolved resolver
# full resolver (which understands /etc/hosts) lives on 127.0.0.53
# stub resolver (just forwards upstream) lives on 127.0.0.54
"127.0.0.53"
];
# nscd -- the Name Service Caching Daemon -- caches DNS query responses
# in a way that's unaware of my VPN routing, so routes are frequently poor against
# services which advertise different IPs based on geolocation.
# nscd claims to be usable without a cache, but in practice i can't get it to not cache!
# nsncd is the Name Service NON-Caching Daemon. it's a drop-in that doesn't cache;
# this is OK on the host -- because systemd-resolved caches. it's probably sub-optimal
# in the netns and we query upstream DNS more often than needed. hm.
# TODO: run a separate recursive resolver in each namespace.
services.nscd.enableNsncd = true;
# services.resolved.extraConfig = ''
# # docs: `man resolved.conf`
# # DNS servers to use via the `wg-ovpns` interface.
# # i hope that from the root ns, these aren't visible.
# DNS=46.227.67.134%wg-ovpns 192.165.9.158%wg-ovpns
# FallbackDNS=1.1.1.1 9.9.9.9
# '';
# 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";
in {
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"
];
peers = [
{
publicKey = "SkkEZDCBde22KTs/Hc7FWvDBfdOCQA4YtBEuC3n5KGs=";
endpoint = "185.157.162.10:9930";
# alternatively: use hostname, but that presents bootstrapping issues (e.g. if host net flakes)
# endpoint = "vpn36.prd.amsterdam.ovpn.com:9930";
allowedIPs = [ "0.0.0.0/0" ];
# nixOS says this is important for keeping NATs active
persistentKeepalive = 25;
# re-executes wg this often. docs hint that this might help wg notice DNS/hostname changes.
# so, maybe that helps if we specify endpoint as a domain name
# dynamicEndpointRefreshSeconds = 30;
# when refresh fails, try it again after this period instead.
# TODO: not avail until nixpkgs upgrade
# dynamicEndpointRefreshRestartSeconds = 5;
}
];
preSetup = "" + ''
${ip} netns add 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
# bridge HTTP traffic:
# any external port-80 request sent to the VPN addr will be forwarded to the rootns.
# this exists so LetsEncrypt can procure a cert for the MX over http.
# TODO: we could use _acme_challence.mx.uninsane.org CNAME to avoid this forwarding
# - <https://community.letsencrypt.org/t/where-does-letsencrypt-resolve-dns-from/37607/8>
${in-ns} ${iptables} -A PREROUTING -t nat -p tcp --dport 80 -m iprange --dst-range ${vpn-ip} \
-j DNAT --to-destination ${veth-host-ip}:80
# we also bridge DNS traffic
${in-ns} ${iptables} -A PREROUTING -t nat -p udp --dport 53 -m iprange --dst-range ${vpn-ip} \
-j DNAT --to-destination ${veth-host-ip}
${in-ns} ${iptables} -A PREROUTING -t nat -p tcp --dport 53 -m iprange --dst-range ${vpn-ip} \
-j DNAT --to-destination ${veth-host-ip}
# 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
'';
options = with lib; {
sane.ports.ports = mkOption {
# add the `visibleTo.ovpn` option
type = types.attrsOf portOpts;
};
};
# 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;
config = {
networking.domain = "uninsane.org";
sane.ports.openFirewall = true;
sane.ports.openUpnp = true;
# view refused packets with: `sudo journalctl -k`
# networking.firewall.logRefusedPackets = true;
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
# Per-interface useDHCP will be mandatory in the future, so this generated config
# replicates the default behaviour.
networking.useDHCP = false;
networking.interfaces.eth0.useDHCP = true;
# XXX colin: probably don't need this. wlan0 won't be populated unless i touch a value in networking.interfaces.wlan0
networking.wireless.enable = false;
# this is needed to forward packets from the VPN to the host
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
# unless we add interface-specific settings for each VPN, we have to define nameservers globally.
# networking.nameservers = [
# "1.1.1.1"
# "9.9.9.9"
# ];
# use systemd's stub resolver.
# /etc/resolv.conf isn't sophisticated enough to use different servers per net namespace (or link).
# instead, running the stub resolver on a known address in the root ns lets us rewrite packets
# in the ovnps namespace to use the provider's DNS resolvers.
# a weakness is we can only query 1 NS at a time (unless we were to clone the packets?)
# there also seems to be some cache somewhere that's shared between the two namespaces.
# i think this is a libc thing. might need to leverage proper cgroups to _really_ kill it.
# - getent ahostsv4 www.google.com
# - try fix: <https://serverfault.com/questions/765989/connect-to-3rd-party-vpn-server-but-dont-use-it-as-the-default-route/766290#766290>
services.resolved.enable = true;
# without DNSSEC:
# - dig matrix.org => works
# - curl https://matrix.org => works
# with default DNSSEC:
# - dig matrix.org => works
# - curl https://matrix.org => fails
# i don't know why. this might somehow be interfering with the DNS run on this device (trust-dns)
services.resolved.dnssec = "false";
networking.nameservers = [
# use systemd-resolved resolver
# full resolver (which understands /etc/hosts) lives on 127.0.0.53
# stub resolver (just forwards upstream) lives on 127.0.0.54
"127.0.0.53"
];
# nscd -- the Name Service Caching Daemon -- caches DNS query responses
# in a way that's unaware of my VPN routing, so routes are frequently poor against
# services which advertise different IPs based on geolocation.
# nscd claims to be usable without a cache, but in practice i can't get it to not cache!
# nsncd is the Name Service NON-Caching Daemon. it's a drop-in that doesn't cache;
# this is OK on the host -- because systemd-resolved caches. it's probably sub-optimal
# in the netns and we query upstream DNS more often than needed. hm.
# TODO: run a separate recursive resolver in each namespace.
services.nscd.enableNsncd = true;
# services.resolved.extraConfig = ''
# # docs: `man resolved.conf`
# # DNS servers to use via the `wg-ovpns` interface.
# # i hope that from the root ns, these aren't visible.
# DNS=46.227.67.134%wg-ovpns 192.165.9.158%wg-ovpns
# FallbackDNS=1.1.1.1 9.9.9.9
# '';
# 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 {
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"
];
peers = [
{
publicKey = "SkkEZDCBde22KTs/Hc7FWvDBfdOCQA4YtBEuC3n5KGs=";
endpoint = "185.157.162.10:9930";
# alternatively: use hostname, but that presents bootstrapping issues (e.g. if host net flakes)
# endpoint = "vpn36.prd.amsterdam.ovpn.com:9930";
allowedIPs = [ "0.0.0.0/0" ];
# nixOS says this is important for keeping NATs active
persistentKeepalive = 25;
# re-executes wg this often. docs hint that this might help wg notice DNS/hostname changes.
# so, maybe that helps if we specify endpoint as a domain name
# dynamicEndpointRefreshSeconds = 30;
# when refresh fails, try it again after this period instead.
# TODO: not avail until nixpkgs upgrade
# dynamicEndpointRefreshRestartSeconds = 5;
}
];
preSetup = ''
${ip} netns add 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";
# }
# ];
# };
# 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
# # 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
};
}

View File

@@ -12,7 +12,7 @@ in
# > AttributeError: 'NoneType' object has no attribute 'query'
lib.mkIf false
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ inherit user group; mode = "0700"; path = svc-dir; }
];

View File

@@ -0,0 +1,124 @@
# TURN/STUN NAT traversal service
# commonly used to establish realtime calls with prosody, or possibly matrix/synapse
#
# - <https://github.com/coturn/coturn/>
# - `man turnserver`
# - config docs: <https://github.com/coturn/coturn/blob/master/examples/etc/turnserver.conf>
#
# N.B. during operation it's NORMAL to see "error 401".
# during session creation:
# - client sends Allocate request
# - server replies error 401, providing a realm and nonce
# - client uses realm + nonce + shared secret to construct an auth key & call Allocate again
# - server replies Allocate Success Response
# - source: <https://stackoverflow.com/a/66643135>
#
# N.B. this safest implementation routes all traffic THROUGH A VPN
# - that adds a lot of latency, but in practice turns out to be inconsequential.
# i guess ICE allows clients to prefer the other party's lower-latency server, in practice?
# - still, this is the "safe" implementation because STUN works with IP addresses instead of domain names:
# 1. client A queries the STUN server to determine its own IP address/port.
# 2. client A tells client B which IP address/port client A is visible on.
# 3. client B contacts that IP address/port
# this only works so long as the IP address/port which STUN server sees client A on is publicly routable.
# that is NOT the case when the STUN server and client A are on the same LAN
# even if client A contacts the STUN server via its WAN address with port reflection enabled.
# hence, there's no obvious way to put the STUN server on the same LAN as either client and expect the rest to work.
{ lib, ... }:
let
# TODO: this range could be larger, but right now that's costly because each element is its own UPnP forward
# TURN port range (inclusive)
turnPortLow = 49152;
turnPortHigh = 49167;
turnPortRange = lib.range turnPortLow turnPortHigh;
in
{
sane.ports.ports = lib.mkMerge ([
{
"3478" = {
# this is the "control" port.
# i.e. no client data is forwarded through it, but it's where clients request tunnels.
protocol = [ "tcp" "udp" ];
# visibleTo.lan = true;
# visibleTo.wan = true;
visibleTo.ovpn = true;
description = "colin-stun-turn";
};
"5349" = {
# the other port 3478 also supports TLS/DTLS, but presumably clients wanting TLS will default 5349
protocol = [ "tcp" ];
# visibleTo.lan = true;
# visibleTo.wan = true;
visibleTo.ovpn = true;
description = "colin-stun-turn-over-tls";
};
}
] ++ (builtins.map
(port: {
"${builtins.toString port}" = let
count = port - turnPortLow + 1;
numPorts = turnPortHigh - turnPortLow + 1;
in {
protocol = [ "tcp" "udp" ];
# visibleTo.lan = true;
# visibleTo.wan = true;
visibleTo.ovpn = true;
description = "colin-turn-${builtins.toString count}-of-${builtins.toString numPorts}";
};
})
turnPortRange
));
services.nginx.virtualHosts."turn.uninsane.org" = {
# allow ACME to procure a cert via nginx for this domain
enableACME = true;
};
sane.dns.zones."uninsane.org".inet = {
# CNAME."turn" = "servo.wan";
# CNAME."turn" = "ovpns";
# CNAME."turn" = "native";
# XXX: SRV records have to point to something with a A/AAAA record; no CNAMEs
A."turn" = "%AOVPNS%";
# A."turn" = "%AWAN%";
SRV."_stun._udp" = "5 50 3478 turn";
SRV."_stun._tcp" = "5 50 3478 turn";
SRV."_stuns._tcp" = "5 50 5349 turn";
SRV."_turn._udp" = "5 50 3478 turn";
SRV."_turn._tcp" = "5 50 3478 turn";
SRV."_turns._tcp" = "5 50 5349 turn";
};
sane.derived-secrets."/var/lib/coturn/shared_secret.bin" = {
encoding = "base64";
# TODO: make this not globally readable
acl.mode = "0644";
};
sane.fs."/var/lib/coturn/shared_secret.bin".wantedBeforeBy = [ "coturn.service" ];
# provide access to certs
users.users.turnserver.extraGroups = [ "nginx" ];
services.coturn.enable = true;
services.coturn.realm = "turn.uninsane.org";
services.coturn.cert = "/var/lib/acme/turn.uninsane.org/fullchain.pem";
services.coturn.pkey = "/var/lib/acme/turn.uninsane.org/key.pem";
services.coturn.use-auth-secret = true;
services.coturn.static-auth-secret-file = "/var/lib/coturn/shared_secret.bin";
services.coturn.lt-cred-mech = true;
services.coturn.min-port = turnPortLow;
services.coturn.max-port = turnPortHigh;
# services.coturn.secure-stun = true;
services.coturn.extraConfig = lib.concatStringsSep "\n" [
"verbose"
# "Verbose" #< even MORE verbosity than "verbose"
# "no-multicast-peers" # disables sending to IPv4 broadcast addresses (e.g. 224.0.0.0/3)
"listening-ip=10.0.1.5"
# "external-ip=185.157.162.178/10.0.1.5"
"external-ip=185.157.162.178"
# "listening-ip=10.78.79.51" # can be specified multiple times; omit for *
# "external-ip=97.113.128.229/10.78.79.51"
# "external-ip=97.113.128.229"
# "mobility" # "mobility with ICE (MICE) specs support" (?)
];
}

View File

@@ -2,6 +2,7 @@
{
imports = [
./calibre.nix
./coturn.nix
./ddns-afraid.nix
./ddns-he.nix
./email
@@ -20,11 +21,11 @@
./navidrome.nix
./nginx.nix
./nixserve.nix
./ntfy.nix
./ntfy
./pict-rs.nix
./pleroma.nix
./postgres.nix
./prosody.nix
./prosody
./transmission.nix
./trust-dns.nix
./wikipedia.nix

View File

@@ -40,8 +40,11 @@ let
turnPortHigh = 49167;
turnPortRange = lib.range turnPortLow turnPortHigh;
in
# XXX(2023/10/15): disabled in favor of Prosody.
# everything configured below was fine: used ejabberd for several months.
lib.mkIf false
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "ejabberd"; group = "ejabberd"; path = "/var/lib/ejabberd"; }
];
sane.ports.ports = lib.mkMerge ([
@@ -114,6 +117,9 @@ in
turnPortRange
));
# this ejabberd config uses builtin STUN/TURN server, so hack to ensure no other implementation fights for ports
services.coturn.enable = false;
# provide access to certs
# TODO: this should just be `acme`. then we also add nginx to the `acme` group.
# why is /var/lib/acme/* owned by `nginx` group??

View File

@@ -22,6 +22,13 @@
# - but postfix delegates authorization of that outgoing mail to dovecot, on the server side
#
# - local clients (i.e. sendmail) interact only with postfix
#
# debugging: general connectivity issues
# - test that inbound port 25 is unblocked:
# - `curl https://canyouseeme.org/ --data 'port=25&IP=185.157.162.178' | grep 'see your service'`
# - and retry with port 465, 587
# - i think this API requires the queried IP match the source IP
# - if necessary, `systemctl stop postfix` and `sudo nc -l 185.157.162.178 25`, then try https://canyouseeme.org
{ ... }:
{

View File

@@ -18,7 +18,7 @@ let
};
in
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode? could be more granular
{ user = "opendkim"; group = "opendkim"; path = "/var/lib/opendkim"; }
{ user = "root"; group = "root"; path = "/var/lib/postfix"; }
@@ -28,21 +28,25 @@ in
# "/var/lib/dovecot"
];
sane.ports.ports."25" = {
protocol = [ "tcp" ];
visibleTo.ovpn = true;
description = "colin-smtp-mx.uninsane.org";
};
sane.ports.ports."465" = {
protocol = [ "tcp" ];
visibleTo.ovpn = true;
description = "colin-smtps-mx.uninsane.org";
};
sane.ports.ports."587" = {
protocol = [ "tcp" ];
visibleTo.ovpn = true;
description = "colin-smtps-submission-mx.uninsane.org";
};
# XXX(2023/10/20): opening these ports in the firewall has the OPPOSITE effect as intended.
# these ports are only routable so long as they AREN'T opened.
# probably some cursed interaction with network namespaces introduced after 2023/10/10.
# sane.ports.ports."25" = {
# protocol = [ "tcp" ];
# # XXX visibleTo.lan effectively means "open firewall, but don't configure any NAT/forwarding"
# visibleTo.lan = true;
# description = "colin-smtp-mx.uninsane.org";
# };
# sane.ports.ports."465" = {
# protocol = [ "tcp" ];
# visibleTo.lan = true;
# description = "colin-smtps-mx.uninsane.org";
# };
# sane.ports.ports."587" = {
# protocol = [ "tcp" ];
# visibleTo.lan = true;
# description = "colin-smtps-submission-mx.uninsane.org";
# };
# exists only to manage certs for Postfix
services.nginx.virtualHosts."mx.uninsane.org" = {

View File

@@ -175,5 +175,10 @@ in
systemd.services.sftpgo.serviceConfig = {
ReadOnlyPaths = [ "/var/export" ];
ReadWritePaths = [ "/var/export/playground" ];
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
Restart = "always";
RestartSec = "20s";
};
}

View File

@@ -15,7 +15,7 @@
owner = config.users.users.freshrss.name;
mode = "0400";
};
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "freshrss"; group = "freshrss"; path = "/var/lib/freshrss"; }
];

View File

@@ -2,7 +2,7 @@
{ config, pkgs, lib, ... }:
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode? could be more granular
{ user = "git"; group = "gitea"; path = "/var/lib/gitea"; }
];

View File

@@ -10,7 +10,7 @@
lib.mkIf false # i don't actively use ipfs anymore
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode? could be more granular
{ user = "261"; group = "261"; path = "/var/lib/ipfs"; }
];

View File

@@ -1,7 +1,7 @@
{ ... }:
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode? we only need this to save Indexer creds ==> migrate to config?
{ user = "root"; group = "root"; path = "/var/lib/jackett"; }
];

View File

@@ -40,7 +40,7 @@
description = "colin-jellyfin-https-lan";
};
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; path = "/var/lib/jellyfin"; }
];
sane.fs."/var/lib/jellyfin/config/logging.json" = {

View File

@@ -4,7 +4,7 @@ let
inherit (svc-cfg) user group port stateDir;
in
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ inherit user group; mode = "0700"; path = stateDir; }
];

View File

@@ -1,6 +1,16 @@
# docs: <https://nixos.wiki/wiki/Matrix>
# docs: <https://nixos.org/manual/nixos/stable/index.html#module-services-matrix-synapse>
# example config: <https://github.com/matrix-org/synapse/blob/develop/docs/sample_config.yaml>
#
# ENABLING PUSH NOTIFICATIONS (with UnifiedPush/ntfy):
# - Matrix "pushers" API spec: <https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3pushersset>
# - first, view notification settings:
# - obtain your client's auth token. e.g. Element -> profile -> help/about -> access token.
# - `curl --header 'Authorization: Bearer <your_access_token>' localhost:8008/_matrix/client/v3/pushers | jq .`
# - enable a new notification destination:
# - `curl --header "Authorization: Bearer <your_access_token>" --data '{ "app_display_name": "<topic>", "app_id": "ntfy.uninsane.org", "data": { "url": "https://ntfy.uninsane.org/_matrix/push/v1/notify", "format": "event_id_only" }, "device_display_name": "<topic>", "kind": "http", "lang": "en-US", "profile_tag": "", "pushkey": "<topic>" }' localhost:8008/_matrix/client/v3/pushers/set`
# - delete a notification destination by setting `kind` to `null` (otherwise, request is identical to above)
#
{ config, lib, pkgs, ... }:
{
@@ -10,7 +20,7 @@
./signal.nix
];
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "matrix-synapse"; group = "matrix-synapse"; path = "/var/lib/matrix-synapse"; }
];
services.matrix-synapse.enable = true;
@@ -60,25 +70,23 @@
config.sops.secrets."matrix_synapse_secrets.yaml".path
];
# services.matrix-synapse.extraConfigFiles = [builtins.toFile "matrix-synapse-extra-config" ''
# admin_contact: "admin.matrix@uninsane.org"
# registrations_require_3pid:
# - email
# email:
# smtp_host: "mx.uninsane.org"
# smtp_port: 587
# smtp_user: "matrix-synapse"
# smtp_pass: "${secrets.matrix-synapse.smtp_pass}"
# require_transport_security: true
# enable_tls: true
# notif_from: "%(app)s <notify.matrix@uninsane.org>"
# app_name: "Uninsane Matrix"
# enable_notifs: true
# validation_token_lifetime: 96h
# invite_client_location: "https://web.matrix.uninsane.org"
# subjects:
# email_validation: "[%(server_name)s] Validate your email"
# ''];
systemd.services.matrix-synapse.postStart = ''
ACCESS_TOKEN=$(${pkgs.coreutils}/bin/cat ${config.sops.secrets.matrix_access_token.path})
TOPIC=$(${pkgs.coreutils}/bin/cat ${config.sops.secrets.ntfy-sh-topic.path})
echo "ensuring ntfy push gateway"
${pkgs.curl}/bin/curl \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--data "{ \"app_display_name\": \"ntfy-adapter\", \"app_id\": \"ntfy.uninsane.org\", \"data\": { \"url\": \"https://ntfy.uninsane.org/_matrix/push/v1/notify\", \"format\": \"event_id_only\" }, \"device_display_name\": \"ntfy-adapter\", \"kind\": \"http\", \"lang\": \"en-US\", \"profile_tag\": \"\", \"pushkey\": \"$TOPIC\" }" \
localhost:8008/_matrix/client/v3/pushers/set
echo "registered push gateways:"
${pkgs.curl}/bin/curl \
--header "Authorization: Bearer $ACCESS_TOKEN" \
localhost:8008/_matrix/client/v3/pushers \
| ${pkgs.jq}/bin/jq .
'';
# new users may be registered on the CLI:
# register_new_matrix_user -c /nix/store/8n6kcka37jhmi4qpd2r03aj71pkyh21s-homeserver.yaml http://localhost:8008
@@ -149,4 +157,9 @@
sops.secrets."matrix_synapse_secrets.yaml" = {
owner = config.users.users.matrix-synapse.name;
};
sops.secrets."matrix_access_token" = {
owner = config.users.users.matrix-synapse.name;
};
# provide access to ntfy-sh-topic secret
users.users.matrix-synapse.extraGroups = [ "ntfy-sh" ];
}

View File

@@ -5,7 +5,7 @@
# - recommended to use mautrix-discord: <https://github.com/NixOS/nixpkgs/pull/200462>
lib.mkIf false
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "matrix-synapse"; group = "matrix-synapse"; path = "/var/lib/mx-puppet-discord"; }
];

View File

@@ -101,7 +101,7 @@ in
})
];
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode?
{ user = "matrix-appservice-irc"; group = "matrix-appservice-irc"; path = "/var/lib/matrix-appservice-irc"; }
];

View File

@@ -2,7 +2,7 @@
# - <https://github.com/mautrix/signal/blob/master/mautrix_signal/example-config.yaml>
{ config, pkgs, ... }:
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "mautrix-signal"; group = "mautrix-signal"; path = "/var/lib/mautrix-signal"; }
{ user = "signald"; group = "signald"; path = "/var/lib/signald"; }
];

View File

@@ -1,7 +1,7 @@
{ lib, ... }:
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "navidrome"; group = "navidrome"; path = "/var/lib/navidrome"; }
];
services.navidrome.enable = true;

View File

@@ -1,4 +1,5 @@
# docs: https://nixos.wiki/wiki/Nginx
# docs: <https://nixos.wiki/wiki/Nginx>
# docs: <https://nginx.org/en/docs/>
{ config, lib, pkgs, ... }:
let
@@ -133,7 +134,7 @@ in
security.acme.acceptTerms = true;
security.acme.defaults.email = "admin.acme@uninsane.org";
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode?
{ user = "acme"; group = "acme"; path = "/var/lib/acme"; }
{ user = "colin"; group = "users"; path = "/var/www/sites"; }

View File

@@ -0,0 +1,14 @@
# ntfy: UnifiedPush notification delivery system
# - used to get push notifications out of Matrix and onto a Phone (iOS, Android, or a custom client)
{ config, ... }:
{
imports = [
./ntfy-waiter.nix
./ntfy-sh.nix
];
sops.secrets."ntfy-sh-topic" = {
mode = "0440";
owner = config.users.users.ntfy-sh.name;
group = config.users.users.ntfy-sh.name;
};
}

View File

@@ -30,7 +30,7 @@ let
altPort = 2587;
in
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# not 100% necessary to persist this, but ntfy does keep a 12hr (by default) cache
# for pushing notifications to users who become offline.
# ACLs also live here.
@@ -61,12 +61,6 @@ in
${pkgs.ntfy-sh}/bin/ntfy access everyone "$topic" read-write
'';
sops.secrets."ntfy-sh-topic" = {
mode = "0440";
owner = config.users.users.ntfy-sh.name;
group = config.users.users.ntfy-sh.name;
};
services.nginx.virtualHosts."ntfy.uninsane.org" = {
forceSSL = true;

View File

@@ -0,0 +1,151 @@
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])" -p ntfy-sh
import argparse
import logging
import os
import socket
import subprocess
import sys
import threading
import time
logger = logging.getLogger(__name__)
LISTEN_QUEUE = 3
WAKE_MESSAGE = b'notification\n'
class Client:
def __init__(self, sock, addr_info, live_after: float):
self.live_after = live_after
self.sock = sock
self.addr_info = addr_info
def __cmp__(self, other: 'Client'):
return cmp(self.addr_info, other.addr_info)
def try_notify(self, message: bytes) -> bool:
"""
returns true if we send a packet to notify client.
fals otherwise (e.g. the socket is dead).
"""
ttl = self.live_after - time.time()
if ttl > 0:
logger.debug(f"sleeping {ttl:.2f}s until client {self.addr_info} is ready to receive notification")
time.sleep(ttl)
try:
self.sock.sendall(message)
except Exception as e:
logger.warning(f"failed to notify client {self.addr_info} {e}")
return False
else:
logger.info(f"successfully notified {self.addr_info}: {message}")
return True
class Adapter:
def __init__(self, host: str, port: int, silence: int, topic: str):
self.host = host
self.port = port
self.silence = silence
self.topic = topic
self.clients = set()
def log_clients(self):
clients_str = '\n'.join(f' {c.addr_info}' for c in self.clients)
logger.debug(f"clients alive ({len(self.clients)}):\n{clients_str}")
def add_client(self, client: Client):
# it's a little bit risky to keep more than one client at the same IP address,
# because it's possible a notification comes in and we ring the old connection,
# even when the new connection says "don't ring yet".
for c in set(self.clients):
if c.addr_info[0] == client.addr_info[0]:
logger.info(f"purging old client before adding new one at same address: {c.addr_info} -> {client.addr_info}")
self.clients.remove(c)
logger.info(f"accepted client at {client.addr_info}")
self.clients.add(client)
def listener_loop(self):
logger.info(f"listening for connections on {self.host}:{self.port}")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((self.host, self.port))
s.listen(LISTEN_QUEUE)
while True:
conn, addr_info = s.accept()
self.add_client(Client(conn, addr_info, live_after = time.time() + self.silence))
def notify_clients(self, message: bytes = WAKE_MESSAGE):
# notify every client, and drop any which have disconnected.
# note that we notify based on age (oldest -> youngest)
# because notifying young clients might entail sleeping until they're ready.
clients = sorted(self.clients, key=lambda c: (c.live_after, c.addr_info))
dead_clients = [
c for c in clients if not c.try_notify(message)
]
for c in dead_clients:
self.clients.remove(c)
self.log_clients()
def notify_loop(self):
logger.info("waiting for notification events")
ntfy_proc = subprocess.Popen(
[
"ntfy",
"sub",
f"https://ntfy.uninsane.org/{self.topic}"
],
stdout=subprocess.PIPE
)
for line in iter(ntfy_proc.stdout.readline, b''):
logger.debug(f"received notification: {line}")
self.notify_clients()
def get_topic() -> str:
return open('/run/secrets/ntfy-sh-topic', 'rt').read().strip()
def run_forever(callable):
try:
callable()
except Exception as e:
logger.error(f"{callable} failed: {e}")
else:
logger.error(f"{callable} unexpectedly returned")
# sys.exit(1)
os._exit(1) # sometimes `sys.exit()` doesn't actually exit...
def main():
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
parser = argparse.ArgumentParser(description="accept connections and notify the other end upon ntfy activity, with a guaranteed amount of silence")
parser.add_argument('--verbose', action='store_true')
parser.add_argument('--host', type=str, default='')
parser.add_argument('--port', type=int)
parser.add_argument('--silence', type=int, help="number of seconds to remain silent upon accepting a connection")
args = parser.parse_args()
if args.verbose:
logging.getLogger().setLevel(logging.DEBUG)
else:
logging.getLogger().setLevel(logging.INFO)
adapter = Adapter(args.host, args.port, args.silence, get_topic())
listener_loop = threading.Thread(target=run_forever, name="listener_loop", args=(adapter.listener_loop,))
notify_loop = threading.Thread(target=run_forever, name="notify_loop", args=(adapter.notify_loop,))
# TODO: this method of exiting seems to sometimes leave the listener behind (?)
# preventing anyone else from re-binding the port.
listener_loop.start()
notify_loop.start()
listener_loop.join()
notify_loop.join()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,72 @@
# service which adapts ntfy-sh into something suitable specifically for the Pinephone's
# wake-on-lan (WoL) feature.
# notably, it provides a mechanism by which the caller can be confident of an interval in which
# zero traffic will occur on the TCP connection, thus allowing it to enter sleep w/o fear of hitting
# race conditions in the Pinephone WoL feature.
{ config, lib, pkgs, ... }:
let
cfg = config.sane.ntfy-waiter;
portLow = 5550;
portHigh = 5559;
portRange = lib.range portLow portHigh;
numPorts = portHigh - portLow + 1;
mkService = port: let
silence = port - portLow;
flags = lib.optional cfg.verbose "--verbose";
cli = [
"${cfg.package}/bin/ntfy-waiter"
"--port"
"${builtins.toString port}"
"--silence"
"${builtins.toString silence}"
] ++ flags;
in {
"ntfy-waiter-${builtins.toString silence}" = {
# TODO: run not as root (e.g. as ntfy-sh)
description = "wait for notification, with ${builtins.toString silence} seconds of guaranteed silence";
serviceConfig = {
Type = "simple";
Restart = "always";
RestartSec = "5s";
ExecStart = lib.concatStringsSep " " cli;
};
after = [ "network.target" ];
wantedBy = [ "default.target" ];
};
};
in
{
options = with lib; {
sane.ntfy-waiter.enable = mkOption {
type = types.bool;
default = true;
};
sane.ntfy-waiter.verbose = mkOption {
type = types.bool;
default = true;
};
sane.ntfy-waiter.package = mkOption {
type = types.package;
default = pkgs.static-nix-shell.mkPython3Bin {
pname = "ntfy-waiter";
src = ./.;
pkgs = [ "ntfy-sh" ];
};
description = ''
exposed to provide an attr-path by which one may build the package for manual testing.
'';
};
};
config = lib.mkIf cfg.enable {
sane.ports.ports = lib.mkMerge (lib.forEach portRange (port: {
"${builtins.toString port}" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-notification-waiter-${builtins.toString (port+1)}-of-${builtins.toString numPorts}";
};
}));
systemd.services = lib.mkMerge (builtins.map mkService portRange);
};
}

View File

@@ -5,7 +5,7 @@ let
cfg = config.services.pict-rs;
in
{
sane.persist.sys.plaintext = lib.mkIf cfg.enable [
sane.persist.sys.byStore.plaintext = lib.mkIf cfg.enable [
{ user = "pict-rs"; group = "pict-rs"; path = cfg.dataDir; }
];

View File

@@ -14,7 +14,7 @@ let
# logLevel = "debug";
in
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "pleroma"; group = "pleroma"; path = "/var/lib/pleroma"; }
];
services.pleroma.enable = true;

View File

@@ -6,7 +6,7 @@ let
KiB = n: 1024*n;
in
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode?
{ user = "postgres"; group = "postgres"; path = "/var/lib/postgresql"; }
];

View File

@@ -1,81 +0,0 @@
# example configs:
# - <https://github.com/kittywitch/nixfiles/blob/main/services/prosody.nix>
# create users with:
# - `sudo -u prosody prosodyctl adduser colin@uninsane.org`
{ lib, ... }:
# XXX disabled: doesn't send messages to nixnet.social (only receives them).
# nixnet runs ejabberd, so revisiting that.
lib.mkIf false
{
sane.persist.sys.plaintext = [
{ user = "prosody"; group = "prosody"; path = "/var/lib/prosody"; }
];
sane.ports.ports."5222" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-client-to-server";
};
sane.ports.ports."5269" = {
protocol = [ "tcp" ];
visibleTo.wan = true;
description = "colin-xmpp-server-to-server";
};
sane.ports.ports."5280" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-bosh";
};
sane.ports.ports."5281" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-prosody-https"; # necessary?
};
# provide access to certs
users.users.prosody.extraGroups = [ "nginx" ];
security.acme.certs."uninsane.org".extraDomainNames = [
"conference.xmpp.uninsane.org"
"upload.xmpp.uninsane.org"
];
services.prosody = {
enable = true;
admins = [ "colin@uninsane.org" ];
# allowRegistration = false;
# extraConfig = ''
# s2s_require_encryption = true
# c2s_require_encryption = true
# '';
extraModules = [ "private" "vcard" "privacy" "compression" "component" "muc" "pep" "adhoc" "lastactivity" "admin_adhoc" "blocklist"];
ssl.cert = "/var/lib/acme/uninsane.org/fullchain.pem";
ssl.key = "/var/lib/acme/uninsane.org/key.pem";
muc = [
{
domain = "conference.xmpp.uninsane.org";
}
];
uploadHttp.domain = "upload.xmpp.uninsane.org";
virtualHosts = {
localhost = {
domain = "localhost";
enabled = true;
};
"xmpp.uninsane.org" = {
domain = "uninsane.org";
enabled = true;
ssl.cert = "/var/lib/acme/uninsane.org/fullchain.pem";
ssl.key = "/var/lib/acme/uninsane.org/key.pem";
};
};
};
}

View File

@@ -0,0 +1,289 @@
# example configs:
# - official: <https://prosody.im/doc/example_config>
# - nixos: <https://github.com/kittywitch/nixfiles/blob/main/services/prosody.nix>
# config options:
# - <https://prosody.im/doc/configure>
#
# modules:
# - main: <https://prosody.im/doc/modules>
# - community: <https://modules.prosody.im/index.html>
#
# debugging:
# - logging:
# - enable `stanza_debug` module
# - enable `log.debug = "*syslog"` in extraConfig
# - interactive:
# - `telnet localhost 5582` (this is equal to `prosodyctl shell` -- but doesn't hang)
# - `watch:stanzas(target_spec, filter)` -> to log stanzas, for version > 0.12
# - console docs: <https://prosody.im/doc/console>
# - can modify/inspect arbitrary internals (lua) by prefixing line with `> `
# - e.g. `> _G` to print all globals
#
# sanity checks:
# - `sudo -u prosody -g prosody prosodyctl check connectivity`
# - `sudo -u prosody -g prosody prosodyctl check turn`
# - `sudo -u prosody -g prosody prosodyctl check turn -v --ping=stun.conversations.im`
# - checks that my stun/turn server is usable by clients of conversations.im (?)
# - `sudo -u prosody -g prosody prosodyctl check` (dns, config, certs)
#
#
# create users with:
# - `sudo -u prosody prosodyctl adduser colin@uninsane.org`
#
#
# federation/support matrix:
# - nixnet.services (runs ejabberd):
# - WORKS: sending and receiving PMs and calls (2023/10/15)
# - N.B.: it didn't originally work; was solved by disabling the lua-unbound DNS option & forcing the system/local resolver
# - cheogram (XMPP <-> SMS gateway):
# - WORKS: sending and receiving PMs, images (2023/10/15)
# - PARTIAL: calls (xmpp -> tel works; tel -> xmpp fails)
# - maybe i need to setup stun/turn
#
# TODO:
# - enable push notifications (mod_cloud_notify)
# - optimize coturn (e.g. move off of the VPN!)
# - ensure muc is working
# - enable file uploads
# - "upload.xmpp.uninsane.org:http_upload: URL: <https://upload.xmpp.uninsane.org:5281/upload> - Ensure this can be reached by users"
# - disable or fix bosh (jabber over http):
# - "certmanager: No certificate/key found for client_https port 0"
{ lib, pkgs, ... }:
let
# enables very verbose logging
enableDebug = false;
in
{
sane.persist.sys.byStore.plaintext = [
{ user = "prosody"; group = "prosody"; path = "/var/lib/prosody"; }
];
sane.ports.ports."5000" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-prosody-fileshare-proxy65";
};
sane.ports.ports."5222" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-client-to-server";
};
sane.ports.ports."5223" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpps-client-to-server"; # XMPP over TLS
};
sane.ports.ports."5269" = {
protocol = [ "tcp" ];
visibleTo.wan = true;
description = "colin-xmpp-server-to-server";
};
sane.ports.ports."5270" = {
protocol = [ "tcp" ];
visibleTo.wan = true;
description = "colin-xmpps-server-to-server"; # XMPP over TLS
};
sane.ports.ports."5280" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-bosh";
};
sane.ports.ports."5281" = {
protocol = [ "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
description = "colin-xmpp-prosody-https"; # necessary?
};
users.users.prosody.extraGroups = [
"nginx" # provide access to certs
"ntfy-sh" # access to secret ntfy topic
];
security.acme.certs."uninsane.org".extraDomainNames = [
"xmpp.uninsane.org"
"conference.xmpp.uninsane.org"
"upload.xmpp.uninsane.org"
];
# exists so the XMPP server's cert can obtain altNames for all its resources
services.nginx.virtualHosts."xmpp.uninsane.org" = {
useACMEHost = "uninsane.org";
};
services.nginx.virtualHosts."conference.xmpp.uninsane.org" = {
useACMEHost = "uninsane.org";
};
services.nginx.virtualHosts."upload.xmpp.uninsane.org" = {
useACMEHost = "uninsane.org";
};
sane.dns.zones."uninsane.org".inet = {
# XXX: SRV records have to point to something with a A/AAAA record; no CNAMEs
A."xmpp" = "%ANATIVE%";
CNAME."conference.xmpp" = "xmpp";
CNAME."upload.xmpp" = "xmpp";
# _Service._Proto.Name TTL Class SRV Priority Weight Port Target
# - <https://xmpp.org/extensions/xep-0368.html>
# something's requesting the SRV records for conference.xmpp, so let's include it
# nothing seems to request XMPP SRVs for the other records (except @)
# lower numerical priority field tells clients to prefer this method
SRV."_xmpps-client._tcp.conference.xmpp" = "3 50 5223 xmpp";
SRV."_xmpps-server._tcp.conference.xmpp" = "3 50 5270 xmpp";
SRV."_xmpp-client._tcp.conference.xmpp" = "5 50 5222 xmpp";
SRV."_xmpp-server._tcp.conference.xmpp" = "5 50 5269 xmpp";
SRV."_xmpps-client._tcp" = "3 50 5223 xmpp";
SRV."_xmpps-server._tcp" = "3 50 5270 xmpp";
SRV."_xmpp-client._tcp" = "5 50 5222 xmpp";
SRV."_xmpp-server._tcp" = "5 50 5269 xmpp";
};
# help Prosody find its certificates.
# pointing it to /var/lib/acme doesn't quite work because it expects the private key
# to be named `privkey.pem` instead of acme's `key.pem`
# <https://prosody.im/doc/certificates#automatic_location>
sane.fs."/etc/prosody/certs/uninsane.org/fullchain.pem" = {
symlink.target = "/var/lib/acme/uninsane.org/fullchain.pem";
wantedBeforeBy = [ "prosody.service" ];
};
sane.fs."/etc/prosody/certs/uninsane.org/privkey.pem" = {
symlink.target = "/var/lib/acme/uninsane.org/key.pem";
wantedBeforeBy = [ "prosody.service" ];
};
services.prosody = {
enable = true;
package = pkgs.prosody.override {
# XXX(2023/10/15): build without lua-unbound support.
# this forces Prosody to fall back to the default Lua DNS resolver, which seems more reliable.
# fixes errors like "unbound.queryXYZUV: Resolver error: out of memory"
# related: <https://issues.prosody.im/1737#comment-11>
lua.withPackages = selector: pkgs.lua.withPackages (p:
selector (p // { luaunbound = null; })
);
# withCommunityModules = [ "turncredentials" ];
};
admins = [ "colin@uninsane.org" ];
# allowRegistration = false; # defaults to false
muc = [
{
domain = "conference.xmpp.uninsane.org";
}
];
uploadHttp.domain = "upload.xmpp.uninsane.org";
virtualHosts = {
# "Prosody requires at least one enabled VirtualHost to function. You can
# safely remove or disable 'localhost' once you have added another."
# localhost = {
# domain = "localhost";
# enabled = true;
# };
"xmpp.uninsane.org" = {
domain = "uninsane.org";
enabled = true;
};
};
## modules:
# these are enabled by default, via <repo:nixos/nixpkgs:/pkgs/servers/xmpp/prosody/default.nix>
# - cloud_notify
# - http_upload
# - vcard_muc
# these are enabled by the module defaults (services.prosody.modules.<foo>)
# - admin_adhoc
# - blocklist
# - bookmarks
# - carbons
# - cloud_notify
# - csi
# - dialback
# - disco
# - http_files
# - mam
# - pep
# - ping
# - private
# - XEP-0049: let clients store arbitrary (private) data on the server
# - proxy65
# - XEP-0065: allow server to proxy file transfers between two clients who are behind NAT
# - register
# - roster
# - saslauth
# - smacks
# - time
# - tls
# - uptime
# - vcard_legacy
# - version
extraPluginPaths = [ ./modules ];
extraModules = [
# admin_shell: allows `prosodyctl shell` to work
# see: <https://prosody.im/doc/modules/mod_admin_shell>
# see: <https://prosody.im/doc/console>
"admin_shell"
"admin_telnet" #< needed by admin_shell
# lastactivity: XEP-0012: allow users to query how long another user has been idle for
# - not sure why i enabled this; think it was in someone's config i referenced
"lastactivity"
# allows prosody to share TURN/STUN secrets with XMPP clients to provide them access to the coturn server.
# see: <https://prosody.im/doc/coturn>
"turn_external"
# legacy coturn integration
# see: <https://modules.prosody.im/mod_turncredentials.html>
# "turncredentials"
"sane_ntfy"
] ++ lib.optionals enableDebug [
"stanza_debug" #< logs EVERY stanza as debug: <https://prosody.im/doc/modules/mod_stanza_debug>
];
extraConfig = ''
local function readAll(file)
local f = assert(io.open(file, "rb"))
local content = f:read("*all")
f:close()
-- remove trailing newline
return string.gsub(content, "%s+", "")
end
-- logging docs:
-- - <https://prosody.im/doc/logging>
-- - <https://prosody.im/doc/advanced_logging>
-- levels: debug, info, warn, error
log = {
${if enableDebug then "debug" else "info"} = "*syslog";
}
-- see: <https://prosody.im/doc/certificates#automatic_location>
-- try to solve: "certmanager: Error indexing certificate directory /etc/prosody/certs: cannot open /etc/prosody/certs: No such file or directory"
-- only, this doesn't work because prosody doesn't like acme's naming scheme
-- certificates = "/var/lib/acme"
c2s_direct_tls_ports = { 5223 }
s2s_direct_tls_ports = { 5270 }
turn_external_host = "turn.uninsane.org"
turn_external_secret = readAll("/var/lib/coturn/shared_secret.bin")
-- turn_external_user = "prosody"
-- legacy mod_turncredentials integration
-- turncredentials_host = "turn.uninsane.org"
-- turncredentials_secret = readAll("/var/lib/coturn/shared_secret.bin")
ntfy_binary = "${pkgs.ntfy-sh}/bin/ntfy"
ntfy_topic = readAll("/run/secrets/ntfy-sh-topic")
-- s2s_require_encryption = true
-- c2s_require_encryption = true
'';
};
}

View File

@@ -0,0 +1,52 @@
-- simple proof-of-concept Prosody module
-- module development guide: <https://prosody.im/doc/developers/modules>
-- module API docs: <https://prosody.im/doc/developers/moduleapi>
--
-- much of this code is lifted from Prosody's own `mod_cloud_notify`
local jid = require"util.jid";
local ntfy = module:get_option_string("ntfy_binary", "ntfy");
local ntfy_topic = module:get_option_string("ntfy_topic", "xmpp");
module:log("info", "initialized");
local function is_urgent(stanza)
if stanza.name == "message" then
if stanza:get_child("propose", "urn:xmpp:jingle-message:0") then
return true, "jingle call";
end
end
end
local function publish_ntfy(message)
-- message should be the message to publish
local ntfy_url = string.format("https://ntfy.uninsane.org/%s", ntfy_topic)
local cmd = string.format("%s pub %q %q", ntfy, ntfy_url, message)
module.log("debug", "invoking ntfy: %s", cmd)
local success, reason, code = os.execute(cmd)
if not success then
module:log("warn", "ntfy failed: %s => %s %d", cmd, reason, code)
end
end
local function archive_message_added(event)
-- event is: { origin = origin, stanza = stanza, for_user = store_user, id = id }
local stanza = event.stanza;
local to = stanza.attr.to;
to = to and jid.split(to) or event.origin.username;
-- only notify if the stanza destination is the mam user we store it for
if event.for_user == to then
local is_urgent_stanza, urgent_reason = is_urgent(event.stanza);
if is_urgent_stanza then
module:log("info", "urgent push for %s (%s)", to, urgent_reason);
publish_ntfy(urgent_reason)
end
end
end
module:hook("archive-message-added", archive_message_added);

View File

@@ -1,7 +1,7 @@
{ config, pkgs, ... }:
{
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: mode? we need this specifically for the stats tracking in .config/
{ user = "transmission"; group = config.users.users.transmission.group; path = "/var/lib/transmission"; }
];

View File

@@ -17,6 +17,7 @@ in lib.mkMerge [
protocol = [ "udp" "tcp" ];
visibleTo.lan = true;
visibleTo.wan = true;
visibleTo.ovpn = true;
description = "colin-dns-hosting";
};
@@ -145,11 +146,12 @@ in lib.mkMerge [
-e s/%CNAMENATIVE%/servo.${flavor}/ \
-e s/%ANATIVE%/${anative}/ \
-e s/%AWAN%/$wan/ \
-e s/%AOVPNS%/185.157.162.178/ \
${zoneTemplate} > ${zoneFor flavor}
'';
serviceConfig = config.systemd.services.trust-dns.serviceConfig // {
ExecStart = ''
${pkgs.trust-dns}/bin/trust-dns \
${pkgs.trust-dns}/bin/${pkgs.trust-dns.meta.mainProgram} \
--port ${builtins.toString port} \
--zonedir ${zoneDirFor flavor}/ \
--config ${configFile} ${flagsStr}

View File

@@ -41,6 +41,14 @@
# does the builder use some content-addressed db to efficiently dedupe?
nix.settings.auto-optimise-store = true;
services.journald.extraConfig = ''
# docs: `man journald.conf`
# merged journald config is deployed to /etc/systemd/journald.conf
[Journal]
# disable journal compression because the underlying fs is compressed
Compress=no
'';
systemd.services.nix-daemon.serviceConfig = {
# the nix-daemon manages nix builders
# kill nix-daemon subprocesses when systemd-oomd detects an out-of-memory condition

View File

@@ -57,84 +57,56 @@ let
};
podcasts = [
(fromDb "lexfridman.com/podcast" // rat)
## Astral Codex Ten
(fromDb "sscpodcast.libsyn.com" // rat)
## Less Wrong Curated
(fromDb "feeds.libsyn.com/421877" // rat)
## Econ Talk
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat)
## Cory Doctorow -- both podcast & text entries
(fromDb "craphound.com" // pol)
## Maggie Killjoy -- referenced by Cory Doctorow
(fromDb "omny.fm/shows/cool-people-who-did-cool-stuff" // pol)
## also Maggie Killjoy
(fromDb "feeds.megaphone.fm/behindthebastards" // pol)
## Jennifer Briney
(fromDb "congressionaldish.libsyn.com" // pol)
(fromDb "werenotwrong.fireside.fm" // pol)
(fromDb "politicalorphanage.libsyn.com" // pol)
# (mkPod "https://podcasts.la.utexas.edu/this-is-democracy/feed/podcast/" // pol // weekly)
## Civboot -- https://anchor.fm/civboot
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech)
## Emerge: making sense of what's next -- <https://www.whatisemerging.com/emergepodcast>
(mkPod "https://anchor.fm/s/21bc734/podcast/rss" // pol // infrequent)
(fromDb "feeds.feedburner.com/80000HoursPodcast" // rat)
## Daniel Huberman on sleep
(fromDb "feeds.megaphone.fm/hubermanlab" // uncat)
## Multidisciplinary Association for Psychedelic Studies
(fromDb "mapspodcast.libsyn.com" // uncat)
(fromDb "acquiredlpbonussecretsecret.libsyn.com" // tech) # ACQ2 - more "Acquired" episodes
(fromDb "allinchamathjason.libsyn.com" // pol)
(fromDb "feeds.transistor.fm/acquired" // tech)
## ACQ2 - more "Acquired" episodes
(fromDb "acquiredlpbonussecretsecret.libsyn.com" // tech)
# The Intercept - Deconstructed
(fromDb "rss.acast.com/deconstructed")
# (fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol) #< possible URL rot
## The Daily
(mkPod "https://feeds.simplecast.com/54nAGcIl" // pol // daily)
# The Intercept - Intercepted
(fromDb "rss.acast.com/intercepted-with-jeremy-scahill")
# (fromDb "rss.prod.firstlook.media/intercepted/podcast.rss" // pol) #< possible URL rot
(fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
## Eric Weinstein
(fromDb "rss.art19.com/the-portal" // rat)
(fromDb "darknetdiaries.com" // tech)
## Radiolab -- also available here, but ONLY OVER HTTP: <http://feeds.wnyc.org/radiolab>
(fromDb "feeds.feedburner.com/radiolab" // pol)
## Sam Harris
(fromDb "wakingup.libsyn.com" // pol)
## 99% Invisible -- also available here: <https://feeds.simplecast.com/BqbsxVfO>
(fromDb "feeds.99percentinvisible.org/99percentinvisible" // pol)
(fromDb "rss.acast.com/ft-tech-tonic" // tech)
(fromDb "feeds.feedburner.com/dancarlin/history" // rat)
(fromDb "rss.art19.com/60-minutes" // pol)
## The Verge - Decoder
(fromDb "feeds.megaphone.fm/recodedecode" // tech)
## Matrix (chat) Live
(fromDb "feed.podbean.com/matrixlive/feed.xml" // tech)
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech) # Civboot -- https://anchor.fm/civboot
(fromDb "cast.postmarketos.org" // tech)
(fromDb "congressionaldish.libsyn.com" // pol) # Jennifer Briney
(fromDb "craphound.com" // pol) # Cory Doctorow -- both podcast & text entries
(fromDb "darknetdiaries.com" // tech)
(fromDb "feed.podbean.com/matrixlive/feed.xml" // tech) # Matrix (chat) Live
(fromDb "feeds.99percentinvisible.org/99percentinvisible" // pol) # 99% Invisible -- also available here: <https://feeds.simplecast.com/BqbsxVfO>
(fromDb "feeds.feedburner.com/80000HoursPodcast" // rat)
(fromDb "feeds.feedburner.com/dancarlin/history" // rat)
(fromDb "feeds.feedburner.com/radiolab" // pol) # Radiolab -- also available here, but ONLY OVER HTTP: <http://feeds.wnyc.org/radiolab>
(fromDb "feeds.libsyn.com/421877" // rat) # Less Wrong Curated
(fromDb "feeds.megaphone.fm/behindthebastards" // pol) # also Maggie Killjoy
(fromDb "feeds.megaphone.fm/hubermanlab" // uncat) # Daniel Huberman on sleep
(fromDb "feeds.megaphone.fm/recodedecode" // tech) # The Verge - Decoder
(fromDb "feeds.simplecast.com/54nAGcIl" // pol) # The Daily
(fromDb "feeds.simplecast.com/82FI35Px" // pol) # Ezra Klein Show
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat) # Econ Talk
(fromDb "feeds.simplecast.com/xKJ93w_w" // uncat) # Atlas Obscura
(fromDb "feeds.transistor.fm/acquired" // tech)
(fromDb "lexfridman.com/podcast" // rat)
(fromDb "mapspodcast.libsyn.com" // uncat) # Multidisciplinary Association for Psychedelic Studies
(fromDb "omegataupodcast.net" // tech) # 3/4 German; 1/4 eps are English
(fromDb "omny.fm/shows/cool-people-who-did-cool-stuff" // pol) # Maggie Killjoy -- referenced by Cory Doctorow
(fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
(fromDb "podcast.thelinuxexp.com" // tech)
## Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232>
# (fromDb "rss.art19.com/your-welcome" // pol)
(fromDb "politicalorphanage.libsyn.com" // pol)
(fromDb "reverseengineering.libsyn.com/rss" // tech) # UnNamed Reverse Engineering Podcast
(fromDb "rss.acast.com/deconstructed") # The Intercept - Deconstructed
(fromDb "rss.acast.com/ft-tech-tonic" // tech)
(fromDb "rss.acast.com/intercepted-with-jeremy-scahill") # The Intercept - Intercepted
(fromDb "rss.art19.com/60-minutes" // pol)
(fromDb "rss.art19.com/the-portal" // rat) # Eric Weinstein
(fromDb "seattlenice.buzzsprout.com" // pol)
## Sci-Fi? has Peter Watts; author of No Moods, Ads or Cutesy Fucking Icons (rifters.com)
(fromDb "talesfromthebridge.buzzsprout.com" // tech)
## UnNamed Reverse Engineering Podcast
(fromDb "reverseengineering.libsyn.com/rss" // tech)
## The Witch Trials of J.K. Rowling
## - <https://www.thefp.com/witchtrials>
(mkPod "https://feeds.megaphone.fm/RUNMED9919162779" // pol // infrequent)
## Atlas Obscura
(fromDb "feeds.simplecast.com/xKJ93w_w" // uncat)
## Ezra Klein Show
(fromDb "feeds.simplecast.com/82FI35Px" // pol)
## Wireshark Podcast o_0
(fromDb "sharkbytes.transistor.fm" // tech)
## 3/4 German; 1/4 eps are English
(fromDb "omegataupodcast.net" // tech)
## Lateral with Tom Scott
(mkPod "https://audioboom.com/channels/5097784.rss" // tech)
(fromDb "sharkbytes.transistor.fm" // tech) # Wireshark Podcast o_0
(fromDb "sscpodcast.libsyn.com" // rat) # Astral Codex Ten
(fromDb "talesfromthebridge.buzzsprout.com" // tech) # Sci-Fi? has Peter Watts; author of No Moods, Ads or Cutesy Fucking Icons (rifters.com)
(fromDb "techwontsave.us" // pol) # rec by Cory Doctorow
# (fromDb "trashfuturepodcast.podbean.com" // pol) # rec by Cory Doctorow, but way rambly
(fromDb "wakingup.libsyn.com" // pol) # Sam Harris
(fromDb "werenotwrong.fireside.fm" // pol)
# (fromDb "rss.art19.com/your-welcome" // pol) # Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232>
# (fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol) #< possible URL rot
# (fromDb "rss.prod.firstlook.media/intercepted/podcast.rss" // pol) #< possible URL rot
# (mkPod "https://anchor.fm/s/21bc734/podcast/rss" // pol // infrequent) # Emerge: making sense of what's next -- <https://www.whatisemerging.com/emergepodcast>
# (mkPod "https://audioboom.com/channels/5097784.rss" // tech) # Lateral with Tom Scott
# (mkPod "https://feeds.megaphone.fm/RUNMED9919162779" // pol // infrequent) # The Witch Trials of J.K. Rowling: <https://www.thefp.com/witchtrials>
# (mkPod "https://podcasts.la.utexas.edu/this-is-democracy/feed/podcast/" // pol // weekly)
];
texts = [
@@ -178,6 +150,7 @@ let
(fromDb "vitalik.ca" // tech)
## ian (Sanctuary)
(fromDb "sagacioussuricata.com" // tech)
(fromDb "artemis.sh" // tech)
## Bunnie Juang
(fromDb "bunniestudios.com" // tech)
(fromDb "blog.danieljanus.pl" // tech)
@@ -188,6 +161,8 @@ let
(mkText "https://anish.lakhwara.com/home.html" // tech // weekly)
(fromDb "jefftk.com" // tech)
(fromDb "pomeroyb.com" // tech)
(fromDb "harihareswara.net" // tech // pol) # rec by Cory Doctorow
(fromDb "mako.cc/copyrighteous" // tech // pol) # rec by Cory Doctorow
# (mkText "https://til.simonwillison.net/tils/feed.atom" // tech // weekly)
# TECH PROJECTS

View File

@@ -9,8 +9,19 @@
# useful emergency utils
boot.initrd.extraUtilsCommands = ''
copy_bin_and_libs ${pkgs.btrfs-progs}/bin/btrfstune
copy_bin_and_libs ${pkgs.util-linux}/bin/{cfdisk,lsblk,lscpu}
copy_bin_and_libs ${pkgs.gptfdisk}/bin/{cgdisk,gdisk}
copy_bin_and_libs ${pkgs.smartmontools}/bin/smartctl
copy_bin_and_libs ${pkgs.nvme-cli}/bin/nvme
copy_bin_and_libs ${pkgs.e2fsprogs}/bin/resize2fs
'';
boot.kernelParams = [ "boot.shell_on_fail" ];
boot.kernelParams = [
"boot.shell_on_fail"
#v experimental full pre-emption for hopefully better call/audio latency on moby.
# also toggleable at runtime via /sys/kernel/debug/sched/preempt
# defaults to preempt=voluntary
# "preempt=full"
];
# other kernelParams:
# "boot.trace"
# "systemd.log_level=debug"

View File

@@ -7,7 +7,7 @@ let
};
in
{
sane.user.persist.private = [ ".local/share/keyrings" ];
sane.user.persist.byStore.private = [ ".local/share/keyrings" ];
sane.user.fs."private/.local/share/keyrings/default" = {
generated.command = [ "${init-keyring}/bin/init-keyring" ];

View File

@@ -13,7 +13,7 @@ let
in
{
# ssh key is stored in private storage
sane.user.persist.private = [
sane.user.persist.byStore.private = [
{ type = "file"; path = ".ssh/id_ed25519"; }
];
sane.user.fs.".ssh/id_ed25519.pub" = lib.mkIf (user-pubkey != null) {

View File

@@ -5,12 +5,12 @@
# store /home/colin/a/b in /home/private/a/b instead of /home/private/home/colin/a/b
sane.persist.stores.private.prefix = "/home/colin";
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# TODO: these should be private.. somehow
"/var/log"
"/var/backup" # for e.g. postgres dumps
];
sane.persist.sys.cryptClearOnBoot = [
sane.persist.sys.byStore.cryptClearOnBoot = [
"/var/lib/systemd/coredump"
];
}

View File

@@ -47,6 +47,8 @@ in
"sane-scripts.vpn"
"sane-scripts.which"
"sane-scripts.wipe-browser"
"sane-scripts.wipe-flare"
"sane-scripts.wipe-fractal"
];
"sane-scripts.sys-utils" = declPackageSet [
"sane-scripts.ip-port-forward"
@@ -58,8 +60,10 @@ in
"btrfs-progs"
"cacert.unbundled" # some services require unbundled /etc/ssl/certs
"cryptsetup"
"ddrescue"
"dig"
"dtc" # device tree [de]compiler
"e2fsprogs" # resize2fs
"efibootmgr"
"ethtool"
"fatresize"
@@ -67,8 +71,9 @@ in
"file"
# "fwupd"
"gawk"
"gdb" # to debug segfaults
"git"
"gptfdisk"
"gptfdisk" # gdisk
"hdparm"
"htop"
"iftop"
@@ -86,6 +91,7 @@ in
"netcat"
"nethogs"
"nmap"
"nvme-cli" # nvme
"openssl"
"parted"
"pciutils"
@@ -93,13 +99,14 @@ in
"pstree"
"ripgrep"
"screen"
"smartmontools"
"smartmontools" # smartctl
"socat"
"strace"
"subversion"
"tcpdump"
"tree"
"usbutils"
"util-linux" # lsblk, lscpu, etc
"wget"
"wirelesstools" # iwlist
];
@@ -117,12 +124,13 @@ in
# - debugging?
consoleUtils = declPackageSet [
"alsaUtils" # for aplay, speaker-test
"binutils" # for strings; though this brings 80MB of unrelated baggage too
"binutils-unwrapped" # for strings; though this brings 80MB of unrelated baggage too
# "cdrtools"
"clinfo"
"dmidecode"
"dtrx" # `unar` alternative, "Do The Right eXtraction"
"efivar"
"eza" # a better 'ls'
# "flashrom"
"git" # needed as a user package, for config.
# "gnupg"
@@ -134,6 +142,7 @@ in
"lm_sensors" # for sensors-detect. TODO: what needs this? lift into the consumer
"lshw"
# "memtester"
"mercurial" # hg
"neovim" # needed as a user package, for swap persistence
# "nettools"
# "networkmanager"
@@ -143,7 +152,7 @@ in
# "oathToolkit" # for oathtool
# "ponymix"
"pulsemixer"
"python3"
"python3-repl"
# "python3Packages.eyeD3" # music tagging
"ripgrep" # needed as a user package so that its user-level config file can be installed
"rsync"
@@ -158,7 +167,6 @@ in
# "unar"
"unzip"
"wireguard-tools"
"xdg-terminal-exec"
"xdg-utils" # for xdg-open
# "yarn"
"zsh"
@@ -198,7 +206,9 @@ in
devPkgs = declPackageSet [
"cargo"
"clang"
"lua"
"nodejs"
"patchelf"
"rustc"
"tree-sitter"
];
@@ -206,17 +216,17 @@ in
# INDIVIDUAL PACKAGE DEFINITIONS
cargo.persist.plaintext = [ ".cargo" ];
cargo.persist.byStore.plaintext = [ ".cargo" ];
# creds, but also 200 MB of node modules, etc
discord.persist.private = [ ".config/discord" ];
discord.persist.byStore.private = [ ".config/discord" ];
# `emote` will show a first-run dialog based on what's in this directory.
# mostly, it just keeps a LRU of previously-used emotes to optimize display order.
# TODO: package [smile](https://github.com/mijorus/smile) for probably a better mobile experience.
emote.persist.plaintext = [ ".local/share/Emote" ];
emote.persist.byStore.plaintext = [ ".local/share/Emote" ];
fluffychat-moby.persist.plaintext = [ ".local/share/chat.fluffy.fluffychat" ];
fluffychat-moby.persist.byStore.plaintext = [ ".local/share/chat.fluffy.fluffychat" ];
font-manager.package = pkgs.font-manager.override {
# build without the "Google Fonts" integration feature, to save closure / avoid webkitgtk_4_0
@@ -225,45 +235,40 @@ in
# MS GitHub stores auth token in .config
# TODO: we can populate gh's stuff statically; it even lets us use the same oauth across machines
gh.persist.private = [ ".config/gh" ];
gh.persist.byStore.private = [ ".config/gh" ];
"gnome.gnome-maps".persist.plaintext = [ ".cache/shumate" ];
"gnome.gnome-maps".persist.private = [ ".local/share/maps-places.json" ];
"gnome.gnome-maps".persist.byStore.plaintext = [ ".cache/shumate" ];
"gnome.gnome-maps".persist.byStore.private = [ ".local/share/maps-places.json" ];
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
# XXX: is it really safe to persist this? it doesn't have info that could de-anonymize if captured?
monero-gui.persist.plaintext = [ ".bitmonero" ];
monero-gui.persist.byStore.plaintext = [ ".bitmonero" ];
mumble.persist.private = [ ".local/share/Mumble" ];
mumble.persist.byStore.private = [ ".local/share/Mumble" ];
# settings (electron app)
obsidian.persist.plaintext = [ ".config/obsidian" ];
obsidian.persist.byStore.plaintext = [ ".config/obsidian" ];
python3-repl.package = pkgs.python3.withPackages (ps: with ps; [
requests
]);
# creds, media
signal-desktop.persist.private = [ ".config/Signal" ];
signal-desktop.persist.byStore.private = [ ".config/Signal" ];
# printer/filament settings
slic3r.persist.plaintext = [ ".Slic3r" ];
slic3r.persist.byStore.plaintext = [ ".Slic3r" ];
# creds, widevine .so download. TODO: could easily manage these statically.
spotify.persist.plaintext = [ ".config/spotify" ];
tdesktop.persist.byStore.private = [ ".local/share/TelegramDesktop" ];
tdesktop.persist.private = [ ".local/share/TelegramDesktop" ];
tokodon.persist.byStore.private = [ ".cache/KDE/tokodon" ];
tokodon.persist.private = [ ".cache/KDE/tokodon" ];
whalebird.persist.byStore.private = [ ".config/Whalebird" ];
# hardenedMalloc solves an "unable to connect to Tor" error when pressing the "connect" button
# - still required as of 2023/07/14
tor-browser-bundle-bin.package = pkgs.tor-browser-bundle-bin.override {
useHardenedMalloc = false;
};
whalebird.persist.private = [ ".config/Whalebird" ];
yarn.persist.plaintext = [ ".cache/yarn" ];
yarn.persist.byStore.plaintext = [ ".cache/yarn" ];
# zcash coins. safe to delete, just slow to regenerate (10-60 minutes)
zecwallet-lite.persist.private = [ ".zcash" ];
zecwallet-lite.persist.byStore.private = [ ".zcash" ];
};
programs.feedbackd = lib.mkIf config.sane.programs.feedbackd.enabled {

View File

@@ -0,0 +1,103 @@
{ lib, pkgs, ... }:
# notable bemenu options:
# - see `bemenu --help` for all
# -P, --prefix text to show before highlighted item.
# --scrollbar display scrollbar. (none (default), always, autohide)
# -H, --line-height defines the height to make each menu line (0 = default height). (wx)
# -M, --margin defines the empty space on either side of the menu. (wx)
# -W, --width-factor defines the relative width factor of the menu (from 0 to 1). (wx)
# -B, --border defines the width of the border in pixels around the menu. (wx)
# -R --border-radius defines the radius of the border around the menu (0 = no curved borders).
# --ch defines the height of the cursor (0 = scales with line height). (wx)
# --cw defines the width of the cursor. (wx)
# --hp defines the horizontal padding for the entries in single line mode. (wx)
# --fn defines the font to be used ('name [size]'). (wx)
# --tb defines the title background color. (wx)
# --tf defines the title foreground color. (wx)
# --fb defines the filter background color. (wx)
# --ff defines the filter foreground color. (wx)
# --nb defines the normal background color. (wx)
# --nf defines the normal foreground color. (wx)
# --hb defines the highlighted background color. (wx)
# --hf defines the highlighted foreground color. (wx)
# --fbb defines the feedback background color. (wx)
# --fbf defines the feedback foreground color. (wx)
# --sb defines the selected background color. (wx)
# --sf defines the selected foreground color. (wx)
# --ab defines the alternating background color. (wx)
# --af defines the alternating foreground color. (wx)
# --scb defines the scrollbar background color. (wx)
# --scf defines the scrollbar foreground color. (wx)
# --bdr defines the border color. (wx)
#
# colors are specified as `#RRGGBB`
# defaults:
# --ab "#222222"
# --af "#bbbbbb"
# --bdr "#005577"
# --border 3
# --cb "#222222"
# --center
# --cf "#bbbbbb"
# --fb "#222222"
# --fbb "#eeeeee"
# --fbf "#222222"
# --ff "#bbbbbb"
# --fixed-height
# --fn 'Sxmo 14'
# --hb "#005577"
# --hf "#eeeeee"
# --line-height 20
# --list 16
# --margin 40
# --nb "#222222"
# --nf "#bbbbbb"
# --no-overlap
# --no-spacing
# --sb "#323232"
# --scb "#005577"
# --scf "#eeeeee"
# --scrollbar autohide
# --tb "#005577"
# --tf "#eeeeee"
# --wrap
let
bg = "#1d1721"; # slight purple
fg0 = "#d8d8d8"; # inactive text (light grey)
fg1 = "#ffffff"; # active text (white)
accent0 = "#1f5e54"; # darker but saturated teal
accent1 = "#418379"; # teal (matches nixos-bg)
accent2 = "#5b938a"; # brighter but muted teal
bemenuArgs = [
"--wrap --scrollbar autohide --fixed-height"
"--center --margin 45"
"--no-spacing"
# XXX: font size doesn't seem to take effect (would prefer larger)
"--fn 'monospace 14' --line-height 22 --border 3"
"--bdr '${accent0}'" # border
"--scf '${accent2}' --scb '${accent0}'" # scrollbar
"--tb '${accent0}' --tf '${fg0}'" # title
"--fb '${accent0}' --ff '${fg1}'" # filter (i.e. text that's been entered)
"--hb '${accent1}' --hf '${fg1}'" # selected item
"--nb '${bg}' --nf '${fg0}'" # normal lines (even)
"--ab '${bg}' --af '${fg0}'" # alternated lines (odd)
"--cf '${accent0}' --cb '${accent0}'" # cursor (not very useful)
];
bemenuOpts = lib.concatStringsSep " " bemenuArgs;
in
{
sane.programs.bemenu = {
package = pkgs.bemenu.overrideAttrs (upstream: {
nativeBuildInputs = (upstream.nativeBuildInputs or []) ++ [
pkgs.makeWrapper
];
# can alternatively be specified as CLI flags
postInstall = (upstream.postInstall or "") + ''
wrapProgram $out/bin/bemenu \
--set BEMENU_OPTS "${bemenuOpts}"
wrapProgram $out/bin/bemenu-run \
--set BEMENU_OPTS "${bemenuOpts}"
'';
});
};
}

View File

@@ -0,0 +1,9 @@
{ ... }:
{
sane.programs.brave = {
persist.byStore.cryptClearOnBoot = [
".cache/BraveSoftware"
".config/BraveSoftware"
];
};
}

View File

@@ -30,7 +30,7 @@ in
};
};
persist.private = [
persist.byStore.private = [
# ".cache/folks" # contact avatars?
# ".config/calls"
".local/share/calls" # call "records"

View File

@@ -4,7 +4,7 @@
{ ... }:
{
sane.programs.cantata = {
persist.plaintext = [
persist.byStore.plaintext = [
".cache/cantata" # album art
".local/share/cantata/library" # library index (?)
];

View File

@@ -36,7 +36,7 @@ in
# package = chattyNoOauth;
package = chatty-latest;
suggestedPrograms = [ "gnome-keyring" ];
persist.private = [
persist.byStore.private = [
".local/share/chatty" # matrix avatars and files
# not just XMPP; without this Chatty will regenerate its device-id every boot.
# .purple/ contains XMPP *and* Matrix auth, logs, avatar cache, and a bit more

View File

@@ -3,7 +3,7 @@
{
sane.programs.cozy = {
# cozy uses a sqlite db for its config and exposes no CLI options other than --help and --debug
persist.plaintext = [
persist.byStore.plaintext = [
".local/share/cozy" # sqlite db (config & index?)
".cache/cozy" # offline cache
];

View File

@@ -5,6 +5,8 @@
./aerc.nix
./alacritty.nix
./assorted.nix
./bemenu.nix
./brave.nix
./calls.nix
./cantata.nix
./chatty.nix
@@ -16,11 +18,13 @@
./evince.nix
./feedbackd.nix
./firefox.nix
./flare-signal.nix
./fontconfig.nix
./fractal.nix
./fwupd.nix
./g4music.nix
./gajim.nix
./geary.nix
./git.nix
./gnome-feeds.nix
./gnome-keyring.nix
@@ -52,11 +56,13 @@
./ripgrep.nix
./sfeed.nix
./splatmoji.nix
./spotify.nix
./steam.nix
./stepmania.nix
./sublime-music.nix
./swaynotificationcenter.nix
./tangram.nix
./tor-browser-bundle-bin.nix
./tuba.nix
./vlc.nix
./wireshark.nix

View File

@@ -18,6 +18,8 @@
# - fix is to toggle it off -> on in the Dino UI
# - default mic gain is WAY TOO MUCH (heavily distorted)
# - TODO: dino should have more optimal niceness/priority to ensure it can process its buffers
# - possibly this is solved by enabling RealtimeKit (rtkit)
# - TODO: see if Dino calls work better with `echo full > /sys/kernel/debug/sched/preempt`
#
# probably fixed:
# - once per 1-2 minutes dino will temporarily drop mic input:
@@ -43,7 +45,7 @@ in
};
};
persist.private = [ ".local/share/dino" ];
persist.byStore.private = [ ".local/share/dino" ];
services.dino = {
description = "auto-start and maintain dino XMPP connection";

View File

@@ -8,7 +8,7 @@
{
sane.programs.element-desktop = {
# creds/session keys, etc
persist.private = [ ".config/Element" ];
persist.byStore.private = [ ".config/Element" ];
suggestedPrograms = [ "gnome-keyring" ];
};

View File

@@ -8,7 +8,7 @@
{ pkgs, ... }:
{
sane.programs.epiphany = {
# XXX(2023/07/08): running on moby without this hack fails, with:
# XXX(2023/07/08): running on moby without `WEBKIT_DISABLE_SANDBOX...` fails, with:
# - `bwrap: Can't make symlink at /var/run: File exists`
# this could be due to:
# - epiphany is somewhere following a symlink into /var/run instead of /run
@@ -19,6 +19,9 @@
# - <https://gitlab.gnome.org/GNOME/gnome-builder/-/issues/1164>
# - <https://github.com/flatpak/flatpak/issues/3477>
# - <https://github.com/NixOS/nixpkgs/issues/197085>
#
# TODO: consider `WEBKIT_USE_SINGLE_WEB_PROCESS=1` for better perf
# - this runs all tabs in 1 process. which is fine, if i'm not a heavy multi-tabber
package = pkgs.epiphany.overrideAttrs (upstream: {
preFixup = ''
gappsWrapperArgs+=(
@@ -26,7 +29,7 @@
);
'' + (upstream.preFixup or "");
});
persist.private = [
persist.byStore.private = [
".cache/epiphany"
".local/share/epiphany"
# also .config/epiphany, but appears empty

View File

@@ -225,6 +225,12 @@ in
// treat it as unrevoked.
// see: <https://librewolf.net/docs/faq/#im-getting-sec_error_ocsp_server_error-what-can-i-do>
defaultPref("security.OCSP.require", false);
// scrollbar configuration, see: <https://artemis.sh/2023/10/12/scrollbars.html>
// style=4 gives rectangular scrollbars
// could also enable "always show scrollbars" in about:preferences -- not sure what the actual pref name for that is
defaultPref("widget.non-native-theme.scrollbar.size.override", 50);
defaultPref("widget.non-native-theme.scrollbar.style", 4);
'';
fs."${cfg.browser.dotDir}/default".dir = {};
# instruct Firefox to put the profile in a predictable directory (so we can do things like persist just it).

View File

@@ -0,0 +1,47 @@
# Flare is a 3rd-party GTK4 Signal app.
# UI is effectively a clone of Fractal.
#
# compatibility:
# - desko: works fine. pairs, and exchanges contact list (but not message history) with the paired device. exchanges future messages fine.
# - moby (cross compiled flare-signal-nixified): nope. it pairs, but can only *receive* messages and never *send* them.
# - even `rsync`ing the data and keyrings from desko -> moby, still fails in that same manner.
# - console shows error messages. quite possibly an endianness mismatch somewhere
# - moby (partially-emulated flare-signal): works! pairs and can send/receive messages, same as desko.
#
# error signatures (to reset, run `sane-wipe-fractal`):
# - upon sending a message, the other side receives it, but Signal desktop gets "A message from Colin could not be delivered" and the local CLI shows:
# ```
# ERROR libsignal_service::websocket] SignalWebSocket: Websocket error: SignalWebSocket: end of application request stream; socket closing
# ERROR presage::manager] Error opening envelope: ProtobufDecodeError(DecodeError { description: "invalid tag value: 0", stack: [("Content", "data_message")] }), message will be skipped!
# ERROR presage::manager] Error opening envelope: ProtobufDecodeError(DecodeError { description: "invalid tag value: 0", stack: [("Content", "data_message")] }), message will be skipped!
# ```
# - this occurs on moby, desko, `flare-signal` and `flare-signal-nixified`
# - the Websocket error seems to be unrelated, occurs during normal/good operation
# - related issues: <https://github.com/whisperfish/presage/issues/152>
# error when sending from Flare to other Flare device:
# - ```
# ERROR libsignal_protocol::session_cipher] Message from <UUID>.3 failed to decrypt; sender ratchet public key <key> message counter 1
# No current session
# ERROR presage::manager] Error opening envelope: SignalProtocolError(InvalidKyberPreKeyId), message will be skipped!
# ```
# - but signal iOS will still read it.
#
# well, seems to have unpredictable errors particularly when being used on multiple devices.
# desktop _seems_ more reliable than on mobile, but not confident.
{ pkgs, ... }:
{
sane.programs.flare-signal = {
package = pkgs.flare-signal-nixified;
# package = pkgs.flare-signal;
persist.byStore.private = [
# everything: conf, state, files, all opaque
".local/share/flare"
# also persists a secret in ~/.local/share/keyrings. reset with:
# - `secret-tool search --all --unlock 'xdg:schema' 'de.schmidhuberj.Flare'`
# - `secret-tool clear 'xdg:schema' 'de.schmidhuberj.Flare'`
# and it persists some dconf settings (e.g. device name). reset with:
# - `dconf reset -f /de/schmidhuberj/Flare/`.
];
};
}

View File

@@ -1,3 +1,22 @@
# Fractal: GTK4 instant messenger client for the Matrix protocol
#
# very susceptible to state corruption during hard power-cycles.
# if it stalls while launching, especially with a brief message at bottom
# "unable to open store"
# then:
# - remove ~/.local/share/stable/*
# - this might give I/O error, in which case remove the corresponding path under
# /nix/persist/home/colin/private (which can be found by correlating timestamps/sizes with that in ~/private/.local/share/stable).
# - reboot (maybe necessary).
# - now you can send messages, and read messages in unencrypted rooms, but not read messages from encrypted rooms.
# to fix encrypted message receipt:
# - start from above (fractal closed, no ~/.local/share/stable/*)
# - in ~/.local/share/keyrings/Default_keyring.keyring:
# - find the entry that says "display-name=Fractal: Matrix credentials for <mxid>"
# - remove that entry and all associated entries (i.e. ones with same number but different :attributeN)
# - REBOOT. otherwise keyring stuff seems to stay cached in RAM
# - login to Fractal. give an hour to sync.
# - it'll kick you back to a page asking you to cross-sign. open FluffyChat and do the emoji compare. success!
{ config, lib, pkgs, ... }:
let
cfg = config.sane.programs.fractal;
@@ -18,7 +37,7 @@ in
};
};
persist.private = [
persist.byStore.private = [
# XXX by default fractal stores its state in ~/.local/share/<build-profile>/<UUID>.
".local/share/hack" # for debug-like builds
".local/share/stable" # for normal releases

View File

@@ -8,7 +8,7 @@
{ ... }:
{
sane.programs.g4music = {
persist.plaintext = [
persist.byStore.plaintext = [
# index?
".cache/com.github.neithern.g4music"
];

View File

@@ -1,7 +1,7 @@
{ ... }:
{
sane.programs.gajim = {
persist.private = [
persist.byStore.private = [
# avatars, thumbnails...
".cache/gajim"
# sqlite database labeled "settings". definitely includes UI theming

View File

@@ -0,0 +1,55 @@
# geary is a gtk3 email client.
# outstanding issues:
# - it uses webkitgtk_4_1, which is expensive to build.
# could be upgraded to webkitgtk latest if upgraded to gtk4
# <https://gitlab.gnome.org/GNOME/geary/-/issues/1212>
{ ... }:
{
sane.programs."gnome.geary" = {
persist.byStore.private = [
# attachments, and email -- contained in a sqlite db
".local/share/geary"
# also `.cache/geary/web-resources`, which tends to stay << 1 MiB
];
fs.".config/geary/account_01/geary.ini".symlink.text = ''
[Metadata]
version=1
status=enabled
[Account]
ordinal=2
label=
# 14 = "fetch last 14d of mail every time i connect"
# -1 = "fetch *all* mail"
prefetch_days=-1
save_drafts=true
save_sent=true
use_signature=false
signature=
sender_mailboxes=colin@uninsane.org;
service_provider=other
[Folders]
archive_folder=Archive;
drafts_folder=
sent_folder=
junk_folder=
trash_folder=
[Incoming]
login=colin
remember_password=true
host=imap.uninsane.org
port=993
transport_security=transport
credentials=custom
[Outgoing]
remember_password=true
host=mx.uninsane.org
port=465
transport_security=transport
credentials=use-incoming
'';
};
}

View File

@@ -3,7 +3,7 @@
{ ... }:
{
sane.programs.gnome-weather = {
persist.plaintext = [
persist.byStore.plaintext = [
".cache/libgweather"
];
};

View File

@@ -1,4 +1,5 @@
# gnome feeds RSS viewer
# help:
# - #gpodder on irc.libera.chat
{ config, pkgs, sane-lib, ... }:
let
@@ -7,12 +8,22 @@ let
wanted-feeds = feeds.filterByFormat ["podcast"] all-feeds;
in {
sane.programs.gpodder = {
package = pkgs.gpodder-adaptive-configured;
package = pkgs.gpodder-adaptive-configured.overrideAttrs (base: {
# environment variables:
# - GPODDER_HOME (defaults to "~/gPodder")
# - GPODDER_DOWNLOAD_DIR (defaults to "$GPODDER_HOME/Downloads")
# - GPODDER_WRITE_LOGS ("yes" or "no")
# - GPODDER_EXTENSIONS
# - GPODDER_DISABLE_EXTENSIONS ("yes" or "no")
extraMakeWrapperArgs = (base.extraMakeWrapperArgs or []) ++ [
"--set" "GPODDER_HOME" "~/.local/share/gPodder"
];
});
# package = pkgs.gpodder-configured;
fs.".config/gpodderFeeds.opml".symlink.text = feeds.feedsToOpml wanted-feeds;
# XXX: we preserve the whole thing because if we only preserve gPodder/Downloads
# then startup is SLOW during feed import, and we might end up with zombie eps in the dl dir.
persist.plaintext = [ "gPodder" ];
persist.byStore.plaintext = [ ".local/share/gPodder" ];
};
}

View File

@@ -7,7 +7,7 @@
# grammars need to be persisted when developing them
# - `hx --grammar fetch` and `hx --grammar build`
# but otherwise, they ship as part of HELIX_RUNTIME, in the nix store
# persist.plaintext = [ ".config/helix/runtime/grammars" ];
# persist.byStore.plaintext = [ ".config/helix/runtime/grammars" ];
fs.".config/helix/config.toml".symlink.text = ''
# docs: <https://docs.helix-editor.com/configuration.html>
[editor.soft-wrap]

View File

@@ -10,6 +10,6 @@
# jellyfin stores things in a bunch of directories: this one persists auth info.
# it *might* be possible to populate this externally (it's Qt stuff), but likely to
# be fragile and take an hour+ to figure out.
persist.plaintext = [ ".local/share/Jellyfin Media Player" ];
persist.byStore.plaintext = [ ".local/share/Jellyfin Media Player" ];
};
}

View File

@@ -3,6 +3,6 @@
sane.programs.komikku = {
secrets.".local/share/komikku/keyrings/plaintext.keyring" = ../../../secrets/common/komikku_accounts.json.bin;
# downloads end up here, and without the toplevel database komikku doesn't know they exist.
persist.plaintext = [ ".local/share/komikku" ];
persist.byStore.plaintext = [ ".local/share/komikku" ];
};
}

View File

@@ -26,9 +26,8 @@ in {
package = pkgs.koreader-from-src;
# koreader applies these lua "patches" at boot:
# - <https://github.com/koreader/koreader/wiki/User-patches>
# - TODO: upstream this patch to koreader
# fs.".config/koreader/patches".symlink.target = "${./.}";
fs.".config/koreader/patches/2-colin-NetworkManager-isConnected.lua".symlink.target = "${./2-colin-NetworkManager-isConnected.lua}";
# - 2023/10/29: koreader code hasn't changed, but somehow FTP browser seems usable even without the isConnected patch now.
# fs.".config/koreader/patches/2-colin-NetworkManager-isConnected.lua".symlink.target = "${./2-colin-NetworkManager-isConnected.lua}";
# koreader news plugin, enabled by default. file format described here:
# - <repo:koreader/koreader:plugins/newsdownloader.koplugin/feed_config.lua>
@@ -37,12 +36,14 @@ in {
${lib.concatStringsSep ",\n " koreaderRssEntries}
}--do NOT change this line
'';
# easier to navigate via filebrowser than finding the news menu entry
fs."Books/rss-koreader".symlink.target = "../.config/koreader/news";
# koreader on aarch64 errors if there's no fonts directory (sandboxing thing, i guess)
fs.".local/share/fonts".dir = {};
# history, cache, dictionaries...
# could be more explicit if i symlinked the history.lua file to somewhere it can persist better.
persist.plaintext = [ ".config/koreader" ];
persist.byStore.plaintext = [ ".config/koreader" ];
};
}

View File

@@ -2,6 +2,6 @@
{
sane.programs.lemoa = {
# creds
persist.private = [ ".local/share/io.github.lemmygtk.lemoa" ];
persist.byStore.private = [ ".local/share/io.github.lemmygtk.lemoa" ];
};
}

View File

@@ -4,9 +4,9 @@
{
sane.programs.mepo = {
persist.plaintext = [ ".cache/mepo/tiles" ];
persist.byStore.plaintext = [ ".cache/mepo/tiles" ];
# ~/.cache/mepo/savestate has precise coordinates and pins: keep those private
persist.private = [
persist.byStore.private = [
{ type = "file"; path = ".cache/mepo/savestate"; }
];

View File

@@ -42,10 +42,10 @@ in
# mopidy-moped: <https://github.com/martijnboland/moped>
# mopidy-muse: <https://github.com/cristianpb/muse>
]);
persist.plaintext = [
persist.byStore.plaintext = [
".local/share/mopidy/local" # thumbs, library db
];
persist.private = [
persist.byStore.private = [
".local/share/mopidy/http" # cookie
];
secrets.".config/mopidy/mopidy.conf" = ../../../secrets/common/mopidy.conf.bin;

View File

@@ -3,41 +3,57 @@
# - <https://github.com/mpv-player/mpv/wiki>
# curated mpv mods/scripts/users:
# - <https://github.com/stax76/awesome-mpv>
{ pkgs, ... }:
{ config, lib, pkgs, ... }:
let
cfg = config.sane.programs.mpv;
in
{
sane.programs.mpv = {
configOption = with lib; mkOption {
default = {};
type = types.submodule {
options.vo = mkOption {
type = types.nullOr types.str;
default = null;
description = "--vo=FOO flag to pass to mpv";
};
};
};
package = pkgs.wrapMpv pkgs.mpv-unwrapped {
scripts = with pkgs.mpvScripts; [
mpris
# uosc
pkgs.mpv-uosc-latest
];
extraMakeWrapperArgs = [
extraMakeWrapperArgs = lib.optionals (cfg.config.vo != null) [
# 2023/08/29: fixes an error where mpv on moby launches with the message
# "DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory"
# audio still works, and controls, screenshotting, etc -- just not the actual rendering
# this is likely a regression for mpv 0.36.0.
# the actual error message *appears* to come from the mesa library, but it's tough to trace.
#
# backend compatibility (2023/10/22):
# run with `--vo=help` to see a list of all output options.
# non-exhaustive (F=fails, W=works)
# ? libmpv render API for libmpv
# ? gpu Shader-based GPU Renderer
# ? gpu-next Video output based on libplacebo
# ? vdpau VDPAU with X11
# ? wlshm Wayland SHM video output (software scaling)
# ? xv X11/Xv
# W sdl SDL 2.0 Renderer
# F dmabuf-wayland Wayland dmabuf video output
# ? vaapi VA API with X11
# ? x11 X11 (software scaling)
# non-exhaustive (W=works, F=fails, A=audio-only, U=audio+ui only (no video))
# ? null Null video output
# ? caca libcaca
# A (default)
# A dmabuf-wayland Wayland dmabuf video output
# A libmpv render API for libmpv (mpv plays the audio, but doesn't even render a window)
# A vdpau VDPAU with X11
# F drm Direct Rendering Manager (software scaling)
"--add-flags" "--vo=sdl"
# F gpu-next Video output based on libplacebo
# F vaapi VA API with X11
# F x11 X11 (software scaling)
# F xv X11/Xv
# U gpu Shader-based GPU Renderer
# W caca libcaca (terminal rendering)
# W sdl SDL 2.0 Renderer
# W wlshm Wayland SHM video output (software scaling)
"--add-flags" "--vo=${cfg.config.vo}"
];
};
persist.plaintext = [ ".local/state/mpv/watch_later" ];
persist.byStore.plaintext = [ ".local/state/mpv/watch_later" ];
fs.".config/mpv/input.conf".symlink.text = ''
# let volume/power keys be interpreted by the system.
# this is important for sxmo.

View File

@@ -87,7 +87,7 @@ in
{
# private because there could be sensitive things in the swap
sane.programs.neovim = {
persist.private = [ ".cache/vim-swap" ];
persist.byStore.private = [ ".cache/vim-swap" ];
env.EDITOR = "vim";
# git claims it should use EDITOR, but it doesn't!
env.GIT_EDITOR = "vim";

View File

@@ -7,7 +7,7 @@ let
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
in {
sane.programs.newsflash = {
persist.plaintext = [ ".local/share/news-flash" ];
persist.byStore.plaintext = [ ".local/share/news-flash" ];
fs.".config/newsflashFeeds.opml".symlink.text =
feeds.feedsToOpml wanted-feeds
;

View File

@@ -1,9 +1,11 @@
{ ... }:
{
# not strictly necessary, but allows caching articles; offline use, etc.
sane.programs.nheko.persist.private = [
".config/nheko" # config file (including client token)
".cache/nheko" # media cache
".local/share/nheko" # per-account state database
];
sane.programs.nheko = {
# not strictly necessary, but allows caching articles; offline use, etc.
persist.byStore.private = [
".config/nheko" # config file (including client token)
".cache/nheko" # media cache
".local/share/nheko" # per-account state database
];
};
}

View File

@@ -2,6 +2,6 @@
{
# provides `nix-locate`, backed by the manually run `nix-index`
sane.programs.nix-index = {
persist.plaintext = [ ".cache/nix-index" ];
persist.byStore.plaintext = [ ".cache/nix-index" ];
};
}

View File

@@ -1,7 +1,7 @@
{ ... }:
{
sane.programs.rhythmbox = {
persist.plaintext = [
persist.byStore.plaintext = [
# playlists; index
".local/share/rhythmbox"
# album art

View File

@@ -23,6 +23,6 @@ in {
'';
# this is where the parsed feed items go
persist.plaintext = [ ".sfeed/feeds" ];
persist.byStore.plaintext = [ ".sfeed/feeds" ];
};
}

View File

@@ -5,7 +5,7 @@
{
sane.programs.splatmoji = {
persist.plaintext = [ ".local/state/splatmoji" ];
persist.byStore.plaintext = [ ".local/state/splatmoji" ];
fs.".config/splatmoji/splatmoji.config".symlink.text = ''
# XXX doesn't seem to understand ~ as shorthand for `$HOME`
history_file=/home/colin/.local/state/splatmoji/history

View File

@@ -0,0 +1,14 @@
{ ... }:
{
sane.programs.spotify = {
persist.byStore.plaintext = [
# probably just songs and such (haven't checked)
".cache/spotify"
];
persist.byStore.private = [
# creds, widevine .so download. TODO: could easily manage these statically.
".config/spotify"
];
};
}

View File

@@ -1,7 +1,7 @@
{ config, lib, ...}:
{
sane.programs.steam = {
persist.plaintext = [
persist.byStore.plaintext = [
".steam"
".local/share/Steam"
];

View File

@@ -16,12 +16,13 @@
{ ... }:
{
sane.programs.stepmania = {
persist.plaintext = [
persist.byStore.plaintext = [
".stepmania-5.1/Cache" #< otherwise gotta index all the songs every launch
".stepmania-5.1/Save"
];
fs.".stepmania-5.1/Courses".symlink.target = "/mnt/servo-media/games/stepmania/Courses";
fs.".stepmania-5.1/Songs".symlink.target = "/mnt/servo-media/games/stepmania/Songs";
fs.".stepmania-5.1/stepmania.nix".symlink.target = "../nixos/hosts/common/programs/stepmania.nix";
# TODO: setup ~/.stepmania-5.1/Themes
};
}

View File

@@ -7,7 +7,7 @@
# it doesn't obey a conventional ~/Music/{Artist}/{Album}/{Track} notation, so no symlinking
# config (e.g. server connection details) is persisted in ~/.config/sublime-music/config.json
# possible to pass config as a CLI arg (sublime-music -c config.json)
persist.plaintext = [ ".local/share/sublime-music" ];
persist.byStore.plaintext = [ ".local/share/sublime-music" ];
secrets.".config/sublime-music/config.json" = ../../../secrets/common/sublime_music_config.json.bin;
};

View File

@@ -88,13 +88,28 @@ let
pkgs.systemd
];
text = ''
if systemctl is-active "$@"; then
echo "SWAYNC_TOGGLE_STATE: $SWAYNC_TOGGLE_STATE" | ${pkgs.systemd}/bin/systemd-cat --identifier=swaync
if systemctl is-active --quiet "$@"; then
systemctl stop "$@"
else
systemctl start "$@"
fi
'';
};
systemctl-is-active = pkgs.writeShellApplication {
name = "systemctl-is-active";
runtimeInputs = [
pkgs.systemd
];
text = ''
if systemctl is-active "$@"; then
echo true
else
echo false
fi
'';
};
in
{
sane.programs.swaynotificationcenter = {
@@ -114,31 +129,62 @@ in
};
# prevent dbus from automatically activating swaync so i can manage it as a systemd service instead
package = pkgs.rmDbusServices (pkgs.swaynotificationcenter.overrideAttrs (upstream: {
# use swaync with PR 304 applied.
# i can't just `fetchpatch` the PR, nor even a subset of its individual commits,
# because the author does a `merge master` in the middle of it.
# <https://github.com/ErikReider/SwayNotificationCenter/pull/304>
version = "unstable-2023-07-08";
src = pkgs.fetchFromGitHub {
# owner = "ErikReider";
owner = "JannisPetschenka";
repo = "SwayNotificationCenter";
# rev = "90688d0fe916b3e0f764883bce7f19ded82f1476";
# hash = "sha256-Ycc3ja6bcqbVPxwKCPivamQsNRwFrKwIWpHTFmJ5S5g=";
# rev = "f1821a59223010b9c0719d4125bc013b91267800";
# hash = "sha256-ea3owxvvz79uTD7pzBgAL/BYhkyECdN/6qr8wH44DL4=";
# rev = "90cde83bde93bf5d2c14d26345ffbb75963da70c";
# hash = "sha256-cpR0bNG0xlzdg9Jj5O4gTqa/wPyB5nu1SgEGlSQkK4I=";
rev = "6dafd54929ad5fc0078458541c0e4437e5b8a4a9";
hash = "sha256-1mfy7Yzg8Mpbu7R/np15qTz0x2oZvNCZ4Y/9ll+CXv0=";
};
# allow toggle buttons:
patches = (upstream.patches or []) ++ [
(pkgs.fetchpatch {
url = "https://github.com/ErikReider/SwayNotificationCenter/pull/304.patch";
name = "Add toggle button";
hash = "sha256-bove2EXc5FZ5nN1X1FYOn3czCgHG03ibIAupJNoctiM=";
})
(pkgs.fetchpatch {
url = "https://git.uninsane.org/colin/SwayNotificationCenter/commit/f5d9405e040fc42ea98dc4d37202c85728d0d4fd.patch";
name = "toggleButton: change active field to be a command";
hash = "sha256-Y8fiZbAP9yGOVU3rOkZKO8TnPPlrGpINWYGaqeeNzF0=";
})
patches = [
# (pkgs.fetchpatch {
# url = "https://github.com/ErikReider/SwayNotificationCenter/pull/304.patch";
# name = "Add toggle button";
# hash = "sha256-zD1EUnMMSIlLS8uFS0YcwmbrHuntsKw5Y9fF0N1beIU=";
# })
# (pkgs.fetchpatch {
# url = "https://git.uninsane.org/colin/SwayNotificationCenter/commit/f5d9405e040fc42ea98dc4d37202c85728d0d4fd.patch";
# name = "toggleButton: change active field to be a command";
# hash = "sha256-Y8fiZbAP9yGOVU3rOkZKO8TnPPlrGpINWYGaqeeNzF0=";
# })
];
}));
suggestedPrograms = [ "feedbackd" ];
fs.".config/swaync/style.css".symlink.text = ''
/* these color definitions are used by the built-in style */
/* noti-bg defaults `rgb(48, 48, 48)` and is the default button/slider/grid background */
@define-color noti-bg rgb(36, 36, 36);
@define-color noti-bg-darker rgb(24, 24, 24);
/* used for button.active background color, and also when dismissing notifs with keyboard? */
/* @define-color noti-bg-focus rgb(0, 110, 190); */
/* avoid black-on-black text that the default style ships */
window {
color: rgb(255, 255, 255);
}
button {
color: rgb(128, 128, 128);
/* window behind entire control center. defaults to 25% opacity. */
.blank-window {
background: rgba(0, 0, 0, 0.5);
}
button.active {
.widget-buttons-grid>flowbox>flowboxchild>button {
/* text color for inactive buttons, and "Clear All" button.*/
color: rgb(172, 172, 172);
}
.widget-buttons-grid>flowbox>flowboxchild>button.toggle:checked {
color: rgb(255, 255, 255);
background-color: rgb(0, 110, 190);
}
@@ -164,7 +210,11 @@ in
timeout-low = 5;
timeout-critical = 0;
fit-to-screen = true; #< have notification center take full vertical screen space
control-center-width = 400;
# control-center-width:
# - for SXMO_SWAY_SCALE=1.8 => 400
# - for SXMO_SWAY_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 = 450;
control-center-height = 600;
notification-window-width = 400;
keyboard-shortcuts = true;
@@ -298,42 +348,51 @@ in
# type = "toggle";
# label = "feedbackd";
# command = "${systemctl-toggle}/bin/systemctl-toggle --user feedbackd";
# active = "${pkgs.systemd}/bin/systemctl is-active --user feedbackd.service";
# update-command = "${pkgs.systemd}/bin/systemctl is-active --user feedbackd.service && echo true || echo false";
# active = false;
# }
lib.optionals config.sane.programs.eg25-control.enabled [
{
type = "toggle";
label = "gps";
command = "/run/wrappers/bin/sudo ${systemctl-toggle}/bin/systemctl-toggle eg25-control-gps";
active = "${pkgs.systemd}/bin/systemctl is-active eg25-control-gps.service";
update-command = "${systemctl-is-active}/bin/systemctl-is-active eg25-control-gps";
}
{
type = "toggle";
label = "5g";
# modem and NetworkManager auto-establishes a connection when powered.
# though some things like `wg-home` VPN tunnel will remain routed over the old interface.
command = "/run/wrappers/bin/sudo ${systemctl-toggle}/bin/systemctl-toggle eg25-control-powered";
update-command = "${systemctl-is-active}/bin/systemctl-is-active eg25-control-powered";
}
] ++ [
{
type = "toggle";
label = "vpn::hn";
command = "/run/wrappers/bin/sudo ${systemctl-toggle}/bin/systemctl-toggle wg-quick-vpn-servo";
active = "${pkgs.systemd}/bin/systemctl is-active wg-quick-vpn-servo.service";
update-command = "${systemctl-is-active}/bin/systemctl-is-active wg-quick-vpn-servo";
}
] ++ lib.optionals config.sane.programs.calls.config.autostart [
{
type = "toggle";
label = "SIP";
command = "${systemctl-toggle}/bin/systemctl-toggle --user gnome-calls";
active = "${pkgs.systemd}/bin/systemctl is-active --user gnome-calls";
update-command = "${systemctl-is-active}/bin/systemctl-is-active --user gnome-calls";
}
] ++ lib.optionals config.sane.programs.dino.enabled [
{
type = "toggle";
label = "XMPP"; # XMPP calls (jingle)
command = "${systemctl-toggle}/bin/systemctl-toggle --user dino";
active = "${pkgs.systemd}/bin/systemctl is-active --user dino";
update-command = "${systemctl-is-active}/bin/systemctl-is-active --user dino";
}
] ++ lib.optionals config.sane.programs.fractal.enabled [
{
type = "toggle";
label = "Matrix"; # Matrix messages
label = "[m]"; # Matrix messages
command = "${systemctl-toggle}/bin/systemctl-toggle --user fractal";
active = "${pkgs.systemd}/bin/systemctl is-active --user fractal";
update-command = "${systemctl-is-active}/bin/systemctl-is-active --user fractal";
}
];
};

View File

@@ -27,7 +27,7 @@ in
'' + (upstream.preFixup or "");
});
persist.private = [
persist.byStore.private = [
".cache/Tangram"
".local/share/Tangram"
# dconf achieves atomic writes via `mv`, so a symlink doesn't work

View File

@@ -0,0 +1,13 @@
{ pkgs, ... }:
{
sane.programs.tor-browser-bundle-bin = {
package = pkgs.tor-browser-bundle-bin.override {
# hardenedMalloc solves an "unable to connect to Tor" error when pressing the "connect" button
# - still required as of 2023/07/14
useHardenedMalloc = false;
};
persist.byStore.cryptClearOnBoot = [
".local/share/tor-browser"
];
};
}

View File

@@ -10,7 +10,7 @@ let
in
{
sane.programs.vlc = {
persist.private = [
persist.byStore.private = [
# vlc remembers play position in ~/.config/vlc/vlc-qt-interface.conf
# filenames are stored in plaintext (unlike mpv, which i think hashes them)
".config/vlc"

View File

@@ -15,7 +15,7 @@ in {
sane.programs.zeal = {
# package = pkgs.zeal-qt6; #< TODO: upgrade system to qt6 versions of everything (i.e. jellyfin-media-player, nheko)
package = pkgs.zeal-qt5;
persist.plaintext = [
persist.byStore.plaintext = [
".cache/Zeal"
".local/share/Zeal"
];

View File

@@ -27,6 +27,7 @@ in
./starship.nix
];
options = {
# TODO: port to sane.programs options
sane.zsh = {
showDeadlines = mkOption {
type = types.bool;
@@ -38,13 +39,21 @@ in
default = true;
description = "enable starship prompt";
};
guiIntegrations = mkOption {
type = types.bool;
default = config.sane.programs.guiApps.enabled;
description = ''
integrate with things like VTE, so that windowing systems can show the PWD in the title.
drags in gtk+3.
'';
};
};
};
config = mkMerge [
({
sane.programs.zsh = {
persist.private = [
persist.byStore.private = [
# we don't need to full zsh dir -- just the history file --
# but zsh will sometimes backup the history file and symlinking just the file messes things up
".local/share/zsh"
@@ -99,6 +108,9 @@ in
# overcome poor defaults
"lsof" = "lsof -P"; #< lsof: use port *numbers*, not names
"tcpdump" = "tcpdump -n"; #< tcpdump: use port *numbers*, not names
# ls helpers (eza is a nicer `ls`
"l" = "eza --oneline"; # show one entry per line
"ll" = "eza --long --time-style=long-iso";
};
setOptions = [
# docs: `man zshoptions`
@@ -142,7 +154,7 @@ in
'';
syntaxHighlighting.enable = true;
vteIntegration = true;
vteIntegration = cfg.guiIntegrations;
};
# enable a command-not-found hook to show nix packages that might provide the binary typed.

View File

@@ -42,8 +42,9 @@
# - <https://github.com/lourkeur/distro/blob/11173454c6bb50f7ccab28cc2c757dca21446d1d/nixos/profiles/users/louis-full.nix>
# - <https://github.com/dnr/sample-nix-code/blob/03494480c1fae550c033aa54fd96aeb3827761c5/nixos/laptop.nix>
pamMount = let
hasPrivate = config.fileSystems ? "/home/colin/private";
priv = config.fileSystems."/home/colin/private";
in {
in lib.mkIf hasPrivate {
fstype = priv.fsType;
path = priv.device;
mountpoint = priv.mountPoint;
@@ -56,7 +57,7 @@
sane.users.colin = {
default = true;
persist.plaintext = [
persist.byStore.plaintext = [
"archive"
"dev"
# TODO: records should be private

View File

@@ -25,7 +25,7 @@ in
sane.users.guest.fs.".ssh/authorized_keys".symlink.target = config.sops.secrets."guest/authorized_keys".path or "/dev/null";
sane.persist.sys.plaintext = lib.mkIf cfg.enable [
sane.persist.sys.byStore.plaintext = lib.mkIf cfg.enable [
# intentionally allow other users to write to the guest folder
{ path = "/home/guest"; user = "guest"; group = "users"; mode = "0775"; }
];

View File

@@ -1,6 +1,6 @@
{ ... }:
{
sane.persist.sys.cryptClearOnBoot = [
sane.persist.sys.byStore.cryptClearOnBoot = [
# when running commands as root, some things may create ~/.cache entries.
# notably:
# - `/root/.cache/nix/` takes up ~10 MB on lappy/desko/servo

View File

@@ -32,26 +32,7 @@ let
"192.165.9.158"
];
};
# TODO: this should live in the same file as hosts/modules/wg-home.nix...
def-servo = def-wg-vpn "vpn-servo" {
endpoint = config.sane.hosts.by-name."servo".wg-home.endpoint;
publicKey = config.sane.hosts.by-name."servo".wg-home.pubkey;
address = [ config.sane.services.wg-home.ip ];
dns = [
config.sane.hosts.by-name."servo".wg-home.ip
];
privateKeyFile = config.networking.wireguard.interfaces.wg-home.privateKeyFile;
extraOptions = {
# wg-home and vpn-servo interfaces interfere with the result that when connected to both,
# other wg-home users (lappy-hn, ...) aren't visible. disabling wg-home while the full
# vpn-servo is active allows wg-home users to be reachable again
preUp = "${pkgs.iproute2}/bin/ip link set wg-home down";
postDown = "${pkgs.iproute2}/bin/ip link set wg-home up";
};
};
in lib.mkMerge [
(def-servo)
(def-ovpn "us" {
endpoint = "vpn31.prd.losangeles.ovpn.com:9929";
publicKey = "VW6bEWMOlOneta1bf6YFE25N/oMGh1E1UFBCfyggd0k=";

View File

@@ -12,10 +12,19 @@ let
options = {
len = mkOption {
type = types.int;
description = ''
how many bytes of entropy to use; not necessarily the encoded length of the secret.
e.g. if using base16, the length of the encoded secret will be twice this value.
'';
default = 32; # 256b security
};
encoding = mkOption {
type = types.enum [ "base64" ];
};
acl.mode = mkOption {
type = types.str;
default = "0600";
};
};
};
in
@@ -41,7 +50,7 @@ in
c.encoding
(builtins.toString (c.len * 2))
];
generated.acl.mode = "0600";
generated.acl.mode = c.acl.mode;
}) cfg;
};
}

View File

@@ -28,12 +28,14 @@
"epiphany" # gnome's web browser
"evince" # works on phosh
"firefox"
# "flare-signal" # gtk4 signal client
# "foliate" # e-book reader
"fractal" # matrix client
"g4music" # local music player
# "gnome.cheese"
# "gnome-feeds" # RSS reader (with claimed mobile support)
# "gnome.file-roller"
"gnome.geary" # adaptive e-mail client
"gnome.gnome-maps"
# "gnome-podcasts"
# "gnome.gnome-system-monitor"
@@ -61,6 +63,7 @@
# "tokodon"
"tuba" # mastodon/pleroma client (stores pw in keyring)
# "whalebird" # pleroma client (Electron). input is broken on phosh.
"xdg-terminal-exec"
"xterm" # broken on phosh
];
};
@@ -129,7 +132,7 @@
];
};
sane.persist.sys.plaintext = lib.mkIf config.sane.programs.guiApps.enabled [
sane.persist.sys.byStore.plaintext = lib.mkIf config.sane.programs.guiApps.enabled [
"/var/lib/alsa" # preserve output levels, default devices
"/var/lib/colord" # preserve color calibrations (?)
"/var/lib/systemd/backlight" # backlight brightness

View File

@@ -119,7 +119,7 @@ in
# persisting fontconfig & mesa_shader_cache improves start time by ~5x
users.users.greeter.home = "/var/lib/greeter";
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
{ user = "greeter"; group = "greeter"; path = "/var/lib/greeter/.cache/fontconfig"; }
{ user = "greeter"; group = "greeter"; path = "/var/lib/greeter/.cache/mesa_shader_cache"; }
];

View File

@@ -230,8 +230,13 @@ in
# emulate pulseaudio for legacy apps (e.g. sxmo-utils)
pulse.enable = true;
};
# rtkit/RealtimeKit: allow applications which want realtime audio (e.g. Dino? Pulseaudio server?) to request it.
# this might require more configuration (e.g. polkit-related) to work exactly as desired.
# - readme outlines requirements: <https://github.com/heftig/rtkit>
# XXX(2023/10/12): rtkit does not play well on moby. any application sending audio out dies after 10s.
# security.rtkit.enable = true;
# persist per-device volume levels
sane.user.persist.plaintext = [ ".local/state/wireplumber" ];
sane.user.persist.byStore.plaintext = [ ".local/state/wireplumber" ];
# persist per-device volume settings across power cycles.
# pipewire sits atop the kernel ALSA API, so alsa-utils knows about device volumes.
@@ -247,7 +252,7 @@ in
# ExecStop = "${pkgs.alsa-utils}/sbin/alsactl store --ignore";
# };
# };
# sane.persist.sys.plaintext = [ "/var/lib/alsa" ];
# sane.persist.sys.byStore.plaintext = [ "/var/lib/alsa" ];
networking.useDHCP = false;
networking.networkmanager.enable = true;
@@ -275,7 +280,13 @@ in
extraPackages = []; # nixos adds swaylock, swayidle, foot, dmenu by default
# extraOptions = [ "--debug" ];
# "wrapGAppsHook wrapper to execute sway with required environment variables for GTK applications."
wrapperFeatures.gtk = true;
# this literally just sets XDG_DATA_DIRS to the gtk3 gsettings-schemas before launching sway.
# notably, this pulls in the *build* gtk3 -- probably not in an incompatible way
# but still as a mistake, and wasteful for cross compilation
wrapperFeatures.gtk = false;
# this sets XDG_CURRENT_DESKTOP=sway
# and makes sure that sway is launched dbus-run-session.
wrapperFeatures.base = true;
package = cfg.package;
};
programs.xwayland.enable = cfg.config.xwayland;

View File

@@ -11,6 +11,8 @@
# - implements sxmo as a direct systemd service -- apparently no DM
# - packages sxmo-utils
# - injects PATH into each script
# other OS works:
# - <https://git.sr.ht/~aren/sxmo-utils> (arch)
# - perhaps sxmo-utils is best packaged via the `resholve` shell solver?
#
# sxmo upstream links:
@@ -20,7 +22,8 @@
#
# sxmo technical overview:
# - inputs
# - dwm: handles vol/power buttons; hardcoded in config.h
# - bonsaid: handles vol/power buttons
# - it receives those buttons from dwm (if x11) harcoded in config.h or sway (if wayland)
# - lisgd: handles gestures
# - startup
# - daemon based (lisgsd, idle_locker, statusbar_periodics)
@@ -44,9 +47,6 @@
# - menus: bemenu (if wayland), dmenu (if X)
# - gestures: lisgd
# - on-screen keyboard: wvkbd (if wayland), svkbd (if X)
#
# TODO:
# - theme `mako` notifications
{ config, lib, pkgs, ... }:
let
@@ -70,22 +70,34 @@ let
hookPkgs = {
inputhandler = pkgs.static-nix-shell.mkBash {
pname = "sxmo_hook_inputhandler.sh";
src = ./hooks;
pkgs = [ "coreutils" ];
src = ./hooks;
};
postwake = pkgs.static-nix-shell.mkBash {
pname = "sxmo_hook_postwake.sh";
pkgs = [ "coreutils" ];
src = ./hooks;
};
rotate = pkgs.static-nix-shell.mkBash {
pname = "sxmo_hook_rotate.sh";
src = ./hooks;
pkgs = [ "sway" ];
src = ./hooks;
};
screenoff = pkgs.static-nix-shell.mkBash {
pname = "sxmo_hook_screenoff.sh";
pkgs = [ "sway" ];
src = ./hooks;
};
start = pkgs.static-nix-shell.mkBash {
pname = "sxmo_hook_start.sh";
pkgs = [ "systemd" "xdg-user-dirs" ];
src = ./hooks;
pkgs = [ "superd" "xdg-user-dirs" ];
};
suspend = pkgs.static-nix-shell.mkPython3Bin {
pname = "sxmo_suspend.sh";
pkgs = [ "rtl8723cs-wowlan" "util-linux" ];
src = ./hooks;
extraMakeWrapperArgs = [ "--add-flags" "--verbose" ];
};
};
in
@@ -118,7 +130,7 @@ in
};
sane.gui.sxmo.package = mkOption {
type = types.package;
default = pkgs.sxmo-utils-latest;
default = pkgs.sxmo-utils-latest.override { preferSystemd = true; };
description = ''
sxmo base scripts and hooks collection.
consider overriding the outputs under /share/sxmo/default_hooks
@@ -159,6 +171,8 @@ in
"sxmo_hook_notification.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_notification.sh";
"sxmo_hook_notifications.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_notifications.sh";
"sxmo_hook_pickup.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_pickup.sh";
"sxmo_hook_poweroff.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_poweroff.sh";
"sxmo_hook_reboot.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_reboot.sh";
"sxmo_hook_restart_modem_daemons.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_restart_modem_daemons.sh";
"sxmo_hook_ring.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_ring.sh";
"sxmo_hook_rotate.sh" = "${package}/share/sxmo/default_hooks/sxmo_hook_rotate.sh";
@@ -175,7 +189,9 @@ in
"sxmo_hook_inputhandler.sh" = "${hookPkgs.inputhandler}/bin/sxmo_hook_inputhandler.sh";
"sxmo_hook_postwake.sh" = "${hookPkgs.postwake}/bin/sxmo_hook_postwake.sh";
"sxmo_hook_rotate.sh" = "${hookPkgs.rotate}/bin/sxmo_hook_rotate.sh";
"sxmo_hook_screenoff.sh" = "${hookPkgs.screenoff}/bin/sxmo_hook_screenoff.sh";
"sxmo_hook_start.sh" = "${hookPkgs.start}/bin/sxmo_hook_start.sh";
"sxmo_suspend.sh" = "${hookPkgs.suspend}/bin/sxmo_suspend.sh";
};
description = ''
extra hooks to add with higher priority than the builtins
@@ -240,13 +256,14 @@ in
package = null;
suggestedPrograms = [
"guiApps"
"bemenu" # specifically to import its theming
"sfeed" # want this here so that the user's ~/.sfeed/sfeedrc gets created
"superd" # make superctl (used by sxmo) be on PATH
# "superd" # make superctl (used by sxmo) be on PATH
];
persist.cryptClearOnBoot = [
persist.byStore.cryptClearOnBoot = [
# builds to be 10's of MB per day
".local/state/superd/logs"
# ".local/state/superd/logs"
];
};
}
@@ -408,28 +425,55 @@ in
# start the service many times.
# see <repo:craftyguy/superd:internal/cmd/cmd.go>
# TODO: better fix may be to patch `sxmo_hook_lisgdstart.sh` and force it to behave as a singleton
systemd.services."dedupe-sxmo-lisgd" = {
description = "kill duplicate lisgd processes started by superd";
serviceConfig = {
Type = "oneshot";
};
script = ''
if [ "$(${pkgs.procps}/bin/pgrep -c lisgd)" -gt 1 ]; then
echo 'killing duplicated lisgd daemons'
${pkgs.psmisc}/bin/killall lisgd # let superd restart it
fi
'';
wantedBy = [ "multi-user.target" ];
};
systemd.timers."dedupe-sxmo-lisgd" = {
wantedBy = [ "dedupe-sxmo-lisgd.service" ];
timerConfig = {
OnUnitActiveSec = "2min";
};
};
# systemd.services."dedupe-sxmo-lisgd" = {
# description = "kill duplicate lisgd processes started by superd";
# serviceConfig = {
# Type = "oneshot";
# };
# script = ''
# if [ "$(${pkgs.procps}/bin/pgrep -c lisgd)" -gt 1 ]; then
# echo 'killing duplicated lisgd daemons'
# ${pkgs.psmisc}/bin/killall lisgd # let superd restart it
# fi
# '';
# wantedBy = [ "multi-user.target" ];
# };
# systemd.timers."dedupe-sxmo-lisgd" = {
# wantedBy = [ "dedupe-sxmo-lisgd.service" ];
# timerConfig = {
# OnUnitActiveSec = "2min";
# };
# };
sane.user.fs = lib.mkMerge [
{
# link the superd services into a place where systemd can find them.
# the unit files should be compatible, except maybe for PATH handling
# ".config/systemd/user/autocutsel-primary.service".symlink.target = "${package}/share/superd/services/autocutsel-primary.service";
# ".config/systemd/user/autocutsel.service".symlink.target = "${package}/share/superd/services/autocutsel.service";
# ".config/systemd/user/bonsaid.service".symlink.target = "${package}/share/superd/services/bonsaid.service";
# # ".config/systemd/user/dunst.service".symlink.target = "${package}/share/superd/services/dunst.service";
# # ".config/systemd/user/mako.service".symlink.target = "${package}/share/superd/services/mako.service";
# ".config/systemd/user/mmsd-tng.service".symlink.target = "${package}/share/superd/services/mmsd-tng.service";
# ".config/systemd/user/sxmo_autosuspend.service".symlink.target = "${package}/share/superd/services/sxmo_autosuspend.service";
# ".config/systemd/user/sxmo_battery_monitor.service".symlink.target = "${package}/share/superd/services/sxmo_battery_monitor.service";
# ".config/systemd/user/sxmo_conky.service".symlink.target = "${package}/share/superd/services/sxmo_conky.service";
# ".config/systemd/user/sxmo_desktop_widget.service".symlink.target = "${package}/share/superd/services/sxmo_desktop_widget.service";
# ".config/systemd/user/sxmo_hook_lisgd.service".symlink.target = "${package}/share/superd/services/sxmo_hook_lisgd.service";
# ".config/systemd/user/sxmo_menumode_toggler.service".symlink.target = "${package}/share/superd/services/sxmo_menumode_toggler.service";
# ".config/systemd/user/sxmo_modemmonitor.service".symlink.target = "${package}/share/superd/services/sxmo_modemmonitor.service";
# ".config/systemd/user/sxmo_networkmonitor.service".symlink.target = "${package}/share/superd/services/sxmo_networkmonitor.service";
# ".config/systemd/user/sxmo_notificationmonitor.service".symlink.target = "${package}/share/superd/services/sxmo_notificationmonitor.service";
# ".config/systemd/user/sxmo_soundmonitor.service".symlink.target = "${package}/share/superd/services/sxmo_soundmonitor.service";
# ".config/systemd/user/sxmo_wob.service".symlink.target = "${package}/share/superd/services/sxmo_wob.service";
# ".config/systemd/user/sxmo-x11-status.service".symlink.target = "${package}/share/superd/services/sxmo-x11-status.service";
# ".config/systemd/user/unclutter.service".symlink.target = "${package}/share/superd/services/unclutter.service";
# ".config/systemd/user/unclutter-xfixes.service".symlink.target = "${package}/share/superd/services/unclutter-xfixes.service";
# ".config/systemd/user/vvmd.service".symlink.target = "${package}/share/superd/services/vvmd.service";
# service code further below tells systemd to put ~/.config/sxmo/hooks on PATH, but it puts hooks/bin on PATH instead, so symlink that
".config/sxmo/hooks/bin".symlink.target = ".";
".cache/sxmo/sxmo.noidle" = lib.mkIf cfg.noidle {
symlink.text = "";
};
@@ -449,10 +493,64 @@ in
value.symlink.target = value;
}) cfg.hooks)
];
sane.user.services = let
sxmoPath = [
"/etc/profiles/per-user/colin" # so as to launch user-enabled applications (like g4music, etc)
"/run/wrappers" # for doas, and anything else suid
"/run/current-system/sw" # for things installed system-wide, especially flock
] ++ [ package ] ++ package.runtimeDeps;
sxmoEnvSetup = ''
# mimic my sxmo_init.sh a bit. refer to the actual sxmo_init.sh above for details.
# the specific ordering, and the duplicated profile sourcing, matters.
export HOME="''${HOME:-/home/colin}"
export XDG_CONFIG_HOME="''${XDG_CONFIG_HOME:-$HOME/.config}"
source "$XDG_CONFIG_HOME/sxmo/profile"
source ${package}/etc/profile.d/sxmo_init.sh
source "$XDG_CONFIG_HOME/sxmo/profile"
export PATH="$XDG_CONFIG_HOME/sxmo/hooks:$PATH"
'';
sxmoService = name: {
description = "sxmo ${name}";
path = sxmoPath;
script = ''
${sxmoEnvSetup}
exec sxmo_${name}.sh
'';
serviceConfig.Type = "simple";
serviceConfig.Restart = "always";
serviceConfig.RestartSec = "20s";
};
in {
sxmo_autosuspend = sxmoService "autosuspend";
sxmo_battery_monitor = sxmoService "battery_monitor";
sxmo_desktop_widget = sxmoService "hook_desktop_widget";
sxmo_hook_lisgd = sxmoService "hook_lisgdstart";
sxmo_menumode_toggler = sxmoService "menumode_toggler";
sxmo_modemmonitor = sxmoService "modemmonitor";
sxmo_networkmonitor = sxmoService "networkmonitor";
sxmo_notificationmonitor = sxmoService "notificationmonitor";
sxmo_soundmonitor = sxmoService "soundmonitor";
sxmo_wob = sxmoService "wob";
sxmo-x11-status = sxmoService "status_xsetroot";
bonsaid = {
description = "programmable input dispatcher";
path = sxmoPath;
script = ''
${sxmoEnvSetup}
${pkgs.coreutils}/bin/rm -f $XDG_RUNTIME_DIR/bonsai
exec ${pkgs.bonsai}/bin/bonsaid -t $XDG_CONFIG_HOME/sxmo/bonsai_tree.json
'';
serviceConfig.Type = "simple";
serviceConfig.Restart = "always";
serviceConfig.RestartSec = "5s";
};
};
}
(lib.mkIf (cfg.greeter == "lightdm-mobile") {
sane.persist.sys.plaintext = [
sane.persist.sys.byStore.plaintext = [
# this takes up 4-5 MB of fontconfig and mesa shader caches.
# it could optionally be cleared on boot.
{ path = "/var/lib/lightdm"; user = "lightdm"; group = "lightdm"; mode = "0770"; }

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