Compare commits
248 Commits
wip-swaync
...
wip-mootub
Author | SHA1 | Date | |
---|---|---|---|
371fc689f5 | |||
12daa9830e | |||
3e5e1477b9 | |||
c100f55f1c | |||
5a0c0dff41 | |||
8fc5e3611e | |||
3c3fe16569 | |||
8eb83bb283 | |||
e559f1b960 | |||
24a485c213 | |||
413669d118 | |||
1729f29374 | |||
e58833da3b | |||
e5d4b57d9e | |||
1d61834a95 | |||
b74f55cf54 | |||
eb07a416b4 | |||
ca277567f4 | |||
68c2f8f333 | |||
ae5dee394c | |||
a94c460a95 | |||
78bf5caf00 | |||
c5dbda67ad | |||
2260fbaec5 | |||
4d2fecec13 | |||
101677688e | |||
ca8fefe0c6 | |||
3e8d7ef8e3 | |||
71aed74e20 | |||
712e2c2d12 | |||
892ba7d63e | |||
96ca2a6585 | |||
3ebf6470c1 | |||
f8db994129 | |||
dcb74234a6 | |||
ac7c0709e8 | |||
7d8595233c | |||
5452286493 | |||
5528b6d87d | |||
6ae3e61d1d | |||
a9093a6a69 | |||
3dcf7a1204 | |||
c2c63d400f | |||
8f9c9efca1 | |||
1cb83032a1 | |||
eba9253efe | |||
9bd0537854 | |||
9491190ce4 | |||
9b70d8884d | |||
9824094fdc | |||
361be1e5d1 | |||
1d38aa62de | |||
d8a4702f1e | |||
75124f18c0 | |||
f54df71d2a | |||
b40b29350a | |||
6a9b8b558a | |||
58f17eac2d | |||
41709b6eac | |||
f9f247df39 | |||
4c4a8a0897 | |||
10aea555dd | |||
43f7f07d0e | |||
3bde4a70ca | |||
b9fefdab80 | |||
2ac2aa4e6c | |||
8f526cd2b5 | |||
6382ac22cb | |||
e1845d37da | |||
9ccbfd8bf0 | |||
37a95b97f6 | |||
4e0845eb9c | |||
dc8b79b721 | |||
dd0ab41396 | |||
c3c3cff6ca | |||
1f26b36fb8 | |||
e990d5a645 | |||
121e86013e | |||
e0a1dcd51f | |||
758281f772 | |||
fe19065a6a | |||
a9ba9b77ad | |||
23f4b2e2e4 | |||
2d65282643 | |||
0bd9125484 | |||
175144663d | |||
77a0a36bb8 | |||
f26b64c660 | |||
3ff9c0ad0c | |||
3eb6ce6ff6 | |||
845b4b219d | |||
ffe53086fb | |||
5c34c807c5 | |||
de2a33580a | |||
08a875d862 | |||
7eeebd632d | |||
a72e9b1a3e | |||
56808821da | |||
b53eca6323 | |||
5a1edb51ef | |||
b03328b54f | |||
4e2615f321 | |||
1e14654d95 | |||
0519db4d2c | |||
5b9e4df03b | |||
2dbde57f46 | |||
d51b7eb124 | |||
bfcc071d94 | |||
72e1ab6ad6 | |||
d54efbaacf | |||
7d2f166d67 | |||
aff3e1aee8 | |||
9343447c03 | |||
beb13b8f84 | |||
70b273a0d2 | |||
fc2bf35588 | |||
05893ad661 | |||
fdc9df6b91 | |||
c6d68e1450 | |||
d294be9f35 | |||
98ea4d2dfe | |||
6a950b4e97 | |||
70292e4f8e | |||
67f8b82740 | |||
e9eb139b80 | |||
61d5b9f048 | |||
c5c86c3964 | |||
0f233f3a22 | |||
166bd70a1f | |||
776b4a6c02 | |||
75dcc60be5 | |||
53034a6ff4 | |||
1ea6df9e6c | |||
a98a14da3d | |||
629cb8776e | |||
96a63d0e89 | |||
c7b065eed9 | |||
89b0b8884b | |||
644983d27a | |||
04d3ea97f3 | |||
11baf471a4 | |||
505c2d83f2 | |||
f84ab9a4d1 | |||
0127b61901 | |||
b7247f6082 | |||
9cc72c09dc | |||
d763f3b912 | |||
f8899aada0 | |||
2e983267d4 | |||
df0c63b300 | |||
1db2031b76 | |||
2720ccc1fc | |||
f2aea2c201 | |||
6b9c5f518e | |||
6d6d2320bd | |||
a1298d6cda | |||
52b59bcde8 | |||
256c85ba5c | |||
5e484719c2 | |||
6b88379b01 | |||
7b29624776 | |||
18f8825cd5 | |||
3d94d02960 | |||
1f8886684f | |||
29f1da873b | |||
97ec517a1e | |||
2fccaf684c | |||
008063e645 | |||
867c949604 | |||
7a1af6ee5c | |||
0893c90c51 | |||
3c7ebb5385 | |||
91c2f6fc95 | |||
ead08fbb5d | |||
3ad6a15f56 | |||
12adb9f10a | |||
7b2932b02b | |||
57a47da12c | |||
84a51faa70 | |||
ad495301c0 | |||
43bd745228 | |||
fea056d9be | |||
2f320db5e2 | |||
130268491c | |||
caf95675d6 | |||
b23281e9dc | |||
850354b7d7 | |||
5c7851e4d9 | |||
d85dbf1d33 | |||
93ea668db3 | |||
5f426b3efd | |||
4b6a18e4e7 | |||
35629a2a07 | |||
50651d1c03 | |||
412667dd0e | |||
c46a5089a6 | |||
1b3f902dc2 | |||
bfcb4f92e8 | |||
13dda2e533 | |||
29c5811b68 | |||
8111757357 | |||
93ff8f25a1 | |||
bb810ac75a | |||
87b78d1c89 | |||
bc56f78fd2 | |||
41ac63f445 | |||
b538044d9a | |||
02882dd781 | |||
a24d5581f1 | |||
3125acc95c | |||
d4c7cfcdf8 | |||
6ff01649d6 | |||
dfe724ff52 | |||
6c759c226a | |||
d22c2ea56a | |||
319bfe205d | |||
c4367644dd | |||
69464c2405 | |||
1da78d093f | |||
70ccbb3f59 | |||
214f24805e | |||
37f6c9c3bf | |||
c0ba6dc9f5 | |||
92159f2a3d | |||
3855fb5eb6 | |||
5b3a716819 | |||
48b6045ba3 | |||
fd965177ff | |||
b34d332a32 | |||
23db2bf1bf | |||
5996e1f301 | |||
70a61386b8 | |||
53df000ba6 | |||
802294ec9c | |||
ed4e289209 | |||
796977713d | |||
1f0f84f2f0 | |||
4e328ae0a3 | |||
b572d6d27b | |||
cd79be5414 | |||
28dbf10a30 | |||
96cabc30bc | |||
f5376f2dbb | |||
8b25bc96a4 | |||
6acd363f55 | |||
539ee010ab | |||
5202c572fb | |||
5630b6d8d7 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,5 +1,4 @@
|
|||||||
/keep
|
.working
|
||||||
result
|
result
|
||||||
result-*
|
result-*
|
||||||
/secrets/local.nix
|
/secrets/local.nix
|
||||||
/working
|
|
||||||
|
@@ -11,7 +11,7 @@ the only hard dependency for my exported pkgs/modules should be [nixpkgs][nixpkg
|
|||||||
building <./hosts/> will require [sops][sops].
|
building <./hosts/> will require [sops][sops].
|
||||||
|
|
||||||
you might specifically be interested in these files (elaborated further in #key-points-of-interest):
|
you might specifically be interested in these files (elaborated further in #key-points-of-interest):
|
||||||
- [`sxmo-utils-latest`](./pkgs/additional/sxmo-utils/default.nix)
|
- [`sxmo-utils`](./pkgs/additional/sxmo-utils/default.nix)
|
||||||
- [example SXMO deployment](./hosts/modules/gui/sxmo/default.nix)
|
- [example SXMO deployment](./hosts/modules/gui/sxmo/default.nix)
|
||||||
- [my implementation of impermanence](./modules/persist/default.nix)
|
- [my implementation of impermanence](./modules/persist/default.nix)
|
||||||
- my way of deploying dotfiles/configuring programs per-user:
|
- my way of deploying dotfiles/configuring programs per-user:
|
||||||
|
40
TODO.md
40
TODO.md
@@ -1,10 +1,14 @@
|
|||||||
## BUGS
|
## BUGS
|
||||||
- why i need to manually restart `wireguard-wg-ovpns` on servo periodically
|
|
||||||
- else DNS fails
|
|
||||||
- ringer (i.e. dino incoming call) doesn't prevent moby from sleeping
|
- ringer (i.e. dino incoming call) doesn't prevent moby from sleeping
|
||||||
|
- Fractal opens links with non-preferred web browser
|
||||||
|
- `nix` operations from lappy hang when `desko` is unreachable
|
||||||
|
- could at least direct the cache to `http://desko-hn:5001`
|
||||||
|
- waybar isn't visible on moby until after `swaymsg reload`
|
||||||
|
|
||||||
## REFACTORING:
|
## REFACTORING:
|
||||||
|
|
||||||
|
- fold hosts/common/home/ssh.nix -> hosts/common/users/colin.nix
|
||||||
|
|
||||||
### sops/secrets
|
### sops/secrets
|
||||||
- attach secrets to the thing they're used by (sane.programs)
|
- attach secrets to the thing they're used by (sane.programs)
|
||||||
- rework secrets to leverage `sane.fs`
|
- rework secrets to leverage `sane.fs`
|
||||||
@@ -21,7 +25,6 @@
|
|||||||
- fix lightdm-mobile-greeter for newer libhandy
|
- fix lightdm-mobile-greeter for newer libhandy
|
||||||
- port zecwallet-lite to a from-source build
|
- port zecwallet-lite to a from-source build
|
||||||
- REVIEW/integrate jellyfin dataDir config: <https://github.com/NixOS/nixpkgs/pull/233617>
|
- REVIEW/integrate jellyfin dataDir config: <https://github.com/NixOS/nixpkgs/pull/233617>
|
||||||
- remove `libsForQt5.callPackage` broadly: <https://github.com/NixOS/nixpkgs/issues/180841>
|
|
||||||
|
|
||||||
#### upstreaming to non-nixpkgs repos
|
#### upstreaming to non-nixpkgs repos
|
||||||
- gtk: build schemas even on cross compilation: <https://github.com/NixOS/nixpkgs/pull/247844>
|
- gtk: build schemas even on cross compilation: <https://github.com/NixOS/nixpkgs/pull/247844>
|
||||||
@@ -30,8 +33,6 @@
|
|||||||
|
|
||||||
## IMPROVEMENTS:
|
## IMPROVEMENTS:
|
||||||
### security/resilience
|
### 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!
|
- validate duplicity backups!
|
||||||
- encrypt more ~ dirs (~/archives, ~/records, ..?)
|
- encrypt more ~ dirs (~/archives, ~/records, ..?)
|
||||||
- best to do this after i know for sure i have good backups
|
- best to do this after i know for sure i have good backups
|
||||||
@@ -49,19 +50,36 @@
|
|||||||
- e.g. daily email checks; daily backup checks
|
- e.g. daily email checks; daily backup checks
|
||||||
- integrate `nix check` into Gitea actions?
|
- integrate `nix check` into Gitea actions?
|
||||||
|
|
||||||
|
### faster/better deployments
|
||||||
|
- remove audacity's dependency on webkitgtk (via wxwidgets)
|
||||||
|
|
||||||
### user experience
|
### user experience
|
||||||
#### moby
|
|
||||||
- fix cpuidle (gets better power consumption): <https://xnux.eu/log/077.html>
|
|
||||||
- install apps:
|
- install apps:
|
||||||
- display QR codes for WiFi endpoints: <https://linuxphoneapps.org/apps/noappid.wisperwind.wifi2qr/>
|
- display QR codes for WiFi endpoints: <https://linuxphoneapps.org/apps/noappid.wisperwind.wifi2qr/>
|
||||||
- shopping list: <https://linuxphoneapps.org/apps/ro.hume.cosmin.shoppinglist/>
|
- shopping list (not in nixpkgs): <https://linuxphoneapps.org/apps/ro.hume.cosmin.shoppinglist/>
|
||||||
- offline Wikipedia
|
- offline Wikipedia (or, add to `wike`)
|
||||||
|
- offline docs viewer (gtk): <https://github.com/workbenchdev/Biblioteca>
|
||||||
|
- some type of games manager/launcher
|
||||||
|
- Gnome Highscore (retro games)?: <https://gitlab.gnome.org/World/highscore>
|
||||||
|
- better maps for mobile (Osmin (QtQuick)? Pure Maps (Qt/Kirigami)? Gnome Maps is improved in 45)
|
||||||
|
- note-taking app: <https://linuxphoneapps.org/categories/note-taking/>
|
||||||
|
- OSK overlay specifically for mobile gaming
|
||||||
|
- i.e. mock joysticks, for use with SuperTux and SuperTuxKart
|
||||||
|
- install mobile-friendly games:
|
||||||
|
- Shattered Pixel Dungeon (nixpkgs `shattered-pixel-dungeon`; doesn't cross-compile b/c openjdk/libIDL) <https://github.com/ebolalex/shattered-pixel-dungeon>
|
||||||
|
- UnCiv (Civ V clone; nixpkgs `unciv`; doesn't cross-compile): <https://github.com/yairm210/UnCiv>
|
||||||
|
- Simon Tatham's Puzzle Collection (not in nixpkgs) <https://git.tartarus.org/?p=simon/puzzles.git>
|
||||||
|
- Shootin Stars (Godot; not in nixpkgs) <https://gitlab.com/greenbeast/shootin-stars>
|
||||||
|
|
||||||
|
#### moby
|
||||||
|
- fix cpuidle (gets better power consumption): <https://xnux.eu/log/077.html>
|
||||||
- SwayNC:
|
- SwayNC:
|
||||||
- don't show MPRIS if no players detected
|
- don't show MPRIS if no players detected
|
||||||
- this is a problem of playerctld, i guess
|
- this is a problem of playerctld, i guess
|
||||||
|
- also, the album icon when "Not playing" doesn't follow the size we give in the config
|
||||||
|
- that means mpris always takes up excessive space on moby
|
||||||
- add option to change audio output
|
- add option to change audio output
|
||||||
- fix colors (red alert) to match overall theme
|
- fix colors (red alert) to match overall theme
|
||||||
- extend width to 100% of portrait mode
|
|
||||||
- moby: tune GPS
|
- moby: tune GPS
|
||||||
- run only geoclue, and not gpsd, to save power?
|
- run only geoclue, and not gpsd, to save power?
|
||||||
- tune QGPS setting in eg25-control, for less jitter?
|
- tune QGPS setting in eg25-control, for less jitter?
|
||||||
@@ -81,6 +99,8 @@
|
|||||||
- phog: remove the gnome-shell runtime dependency to save hella closure size
|
- phog: remove the gnome-shell runtime dependency to save hella closure size
|
||||||
|
|
||||||
#### non-moby
|
#### non-moby
|
||||||
|
- RSS: integrate a paywall bypass
|
||||||
|
- e.g. self-hosted [ladder](https://github.com/everywall/ladder) (like 12ft.io)
|
||||||
- neovim: set up language server (lsp; rnix-lsp; nvim-lspconfig)
|
- neovim: set up language server (lsp; rnix-lsp; nvim-lspconfig)
|
||||||
- Helix: make copy-to-system clipboard be the default
|
- Helix: make copy-to-system clipboard be the default
|
||||||
- firefox/librewolf: persist history
|
- firefox/librewolf: persist history
|
||||||
|
34
flake.lock
generated
34
flake.lock
generated
@@ -5,11 +5,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1687709756,
|
"lastModified": 1694529238,
|
||||||
"narHash": "sha256-Y5wKlQSkgEK2weWdOu4J3riRd+kV/VCgHsqLNTTWQ/0=",
|
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "dbabf0ca0c0c4bce6ea5eaf65af5cb694d2082c7",
|
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -37,11 +37,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs-stable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1698544399,
|
"lastModified": 1700905716,
|
||||||
"narHash": "sha256-vhRmPyEyoPkrXF2iykBsWHA05MIaOSmMRLMF7Hul6+s=",
|
"narHash": "sha256-w1vHn2MbGfdC+CrP3xLZ3scsI06N0iQLU7eTHIVEFGw=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "d87c5d8c41c9b3b39592563242f3a448b5cc4bc9",
|
"rev": "dfb95385d21475da10b63da74ae96d89ab352431",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -53,16 +53,16 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-unpatched": {
|
"nixpkgs-unpatched": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1698611440,
|
"lastModified": 1701180790,
|
||||||
"narHash": "sha256-jPjHjrerhYDy3q9+s5EAsuhyhuknNfowY6yt6pjn9pc=",
|
"narHash": "sha256-kYWcHsk2A1VUpiOvSo7Pq175WnSVeltspTGM2q+Cr3U=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "0cbe9f69c234a7700596e943bfae7ef27a31b735",
|
"rev": "c9702bf40b036c0f1d3d5b0aaf3eee2bf920124c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"ref": "nixos-unstable",
|
"ref": "master",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@@ -83,11 +83,11 @@
|
|||||||
"nixpkgs-stable": "nixpkgs-stable"
|
"nixpkgs-stable": "nixpkgs-stable"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1698548647,
|
"lastModified": 1701127353,
|
||||||
"narHash": "sha256-7c03OjBGqnwDW0FBaBc+NjfEBxMkza+dxZGJPyIzfFE=",
|
"narHash": "sha256-qVNX0wOl0b7+I35aRu78xUphOyELh+mtUp1KBx89K1Q=",
|
||||||
"owner": "Mic92",
|
"owner": "Mic92",
|
||||||
"repo": "sops-nix",
|
"repo": "sops-nix",
|
||||||
"rev": "632c3161a6cc24142c8e3f5529f5d81042571165",
|
"rev": "b1edbf5c0464b4cced90a3ba6f999e671f0af631",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -119,11 +119,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1698634059,
|
"lastModified": 1699515935,
|
||||||
"narHash": "sha256-+Oyv6vDyCtBzab/5cTG0nUrHD9gj7KgGfD4D1Rn4fCk=",
|
"narHash": "sha256-cJIuVrYorhIzG5pRFZb+ZtaKhTFD92ThC42SaxvSe/E=",
|
||||||
"ref": "refs/heads/master",
|
"ref": "refs/heads/master",
|
||||||
"rev": "2419750ca98fc04af42c91e50c49a29c68d465d2",
|
"rev": "8a4273489d945f21d7e0ca6aac952460c7d4c391",
|
||||||
"revCount": 210,
|
"revCount": 216,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.uninsane.org/colin/uninsane"
|
"url": "https://git.uninsane.org/colin/uninsane"
|
||||||
},
|
},
|
||||||
|
98
flake.nix
98
flake.nix
@@ -36,13 +36,14 @@
|
|||||||
# - staging-next merged into master.
|
# - staging-next merged into master.
|
||||||
#
|
#
|
||||||
# which branch to source from?
|
# which branch to source from?
|
||||||
# - for everyday development, prefer `nixos-unstable` branch, as it provides good caching.
|
# - nixos-unstable: for everyday development; it provides good caching
|
||||||
# - if need to test bleeding updates (e.g. if submitting code into staging):
|
# - master: temporarily if i'm otherwise cherry-picking lots of already-applied patches
|
||||||
# - use `staging-next` if it's been cut (i.e. if there's an active staging-next -> master PR)
|
# - staging-next: if testing stuff that's been PR'd into staging, i.e. base library updates.
|
||||||
# - use `staging` if no staging-next branch has been cut.
|
# - staging: maybe if no staging-next -> master PR has been cut yet?
|
||||||
#
|
#
|
||||||
# <https://github.com/nixos/nixpkgs/tree/nixos-unstable>
|
# <https://github.com/nixos/nixpkgs/tree/nixos-unstable>
|
||||||
nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
# nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||||
|
nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=master";
|
||||||
# nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=staging-next";
|
# nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=staging-next";
|
||||||
# nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=staging";
|
# nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=staging";
|
||||||
|
|
||||||
@@ -111,7 +112,7 @@
|
|||||||
|
|
||||||
nixpkgsCompiledBy = system: nixpkgs.legacyPackages."${system}";
|
nixpkgsCompiledBy = system: nixpkgs.legacyPackages."${system}";
|
||||||
|
|
||||||
evalHost = { name, local, target }: nixpkgs.lib.nixosSystem {
|
evalHost = { name, local, target, light ? false }: nixpkgs.lib.nixosSystem {
|
||||||
system = target;
|
system = target;
|
||||||
modules = [
|
modules = [
|
||||||
{
|
{
|
||||||
@@ -124,6 +125,9 @@
|
|||||||
# nixpkgs.buildPlatform = local; # set by instantiate.nix instead
|
# nixpkgs.buildPlatform = local; # set by instantiate.nix instead
|
||||||
# nixpkgs.config.replaceStdenv = { pkgs }: pkgs.ccacheStdenv;
|
# nixpkgs.config.replaceStdenv = { pkgs }: pkgs.ccacheStdenv;
|
||||||
}
|
}
|
||||||
|
(optionalAttrs light {
|
||||||
|
sane.enableSlowPrograms = false;
|
||||||
|
})
|
||||||
(import ./hosts/instantiate.nix { hostName = name; })
|
(import ./hosts/instantiate.nix { hostName = name; })
|
||||||
self.nixosModules.default
|
self.nixosModules.default
|
||||||
self.nixosModules.passthru
|
self.nixosModules.passthru
|
||||||
@@ -139,21 +143,21 @@
|
|||||||
nixosConfigurations =
|
nixosConfigurations =
|
||||||
let
|
let
|
||||||
hosts = {
|
hosts = {
|
||||||
servo = { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
servo = { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||||
desko = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
desko = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||||
lappy = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
desko-light = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; light = true; };
|
||||||
moby = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
|
lappy = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||||
rescue = { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
lappy-light = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; light = true; };
|
||||||
|
moby = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
|
||||||
|
moby-light = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; light = true; };
|
||||||
|
rescue = { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||||
};
|
};
|
||||||
# cross-compiled builds: instead of emulating the host, build using a cross-compiler.
|
# cross-compiled builds: instead of emulating the host, build using a cross-compiler.
|
||||||
# - these are faster to *build* than the emulated variants (useful when tweaking packages),
|
# - these are faster to *build* than the emulated variants (useful when tweaking packages),
|
||||||
# - but fewer of their packages can be found in upstream caches.
|
# - but fewer of their packages can be found in upstream caches.
|
||||||
cross = mapAttrValues evalHost hosts;
|
cross = mapAttrValues evalHost hosts;
|
||||||
emulated = mapAttrValues
|
emulated = mapAttrValues
|
||||||
({name, local, target}: evalHost {
|
(args: evalHost (args // { local = null; }))
|
||||||
inherit name target;
|
|
||||||
local = null;
|
|
||||||
})
|
|
||||||
hosts;
|
hosts;
|
||||||
prefixAttrs = prefix: attrs: mapAttrs'
|
prefixAttrs = prefix: attrs: mapAttrs'
|
||||||
(name: value: {
|
(name: value: {
|
||||||
@@ -165,9 +169,9 @@
|
|||||||
(prefixAttrs "cross-" cross) //
|
(prefixAttrs "cross-" cross) //
|
||||||
(prefixAttrs "emulated-" emulated) // {
|
(prefixAttrs "emulated-" emulated) // {
|
||||||
# prefer native builds for these machines:
|
# prefer native builds for these machines:
|
||||||
inherit (emulated) servo desko lappy rescue;
|
inherit (emulated) servo desko desko-light lappy lappy-light rescue;
|
||||||
# prefer cross-compiled builds for these machines:
|
# prefer cross-compiled builds for these machines:
|
||||||
inherit (cross) moby;
|
inherit (cross) moby moby-light;
|
||||||
};
|
};
|
||||||
|
|
||||||
# unofficial output
|
# unofficial output
|
||||||
@@ -187,6 +191,7 @@
|
|||||||
imgs = mapAttrValues (host: host.config.system.build.img) self.nixosConfigurations;
|
imgs = mapAttrValues (host: host.config.system.build.img) self.nixosConfigurations;
|
||||||
|
|
||||||
# unofficial output
|
# unofficial output
|
||||||
|
hostConfigs = mapAttrValues (host: host.config) self.nixosConfigurations;
|
||||||
hostPkgs = mapAttrValues (host: host.config.system.build.pkgs) 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;
|
hostPrograms = mapAttrValues (host: mapAttrValues (p: p.package) host.config.sane.programs) self.nixosConfigurations;
|
||||||
|
|
||||||
@@ -266,9 +271,14 @@
|
|||||||
# let the user handle that edge case by re-running this whole command
|
# let the user handle that edge case by re-running this whole command
|
||||||
nixos-rebuild --flake '.#${host}' ${action} --target-host colin@${addr} --use-remote-sudo $@
|
nixos-rebuild --flake '.#${host}' ${action} --target-host colin@${addr} --use-remote-sudo $@
|
||||||
'';
|
'';
|
||||||
|
deployApp = host: addr: action: {
|
||||||
|
type = "app";
|
||||||
|
program = ''${deployScript host addr action}'';
|
||||||
|
};
|
||||||
|
|
||||||
# pkg updating.
|
# pkg updating.
|
||||||
# a cleaner alternative lives here: <https://discourse.nixos.org/t/how-can-i-run-the-updatescript-of-personal-packages/25274/2>
|
# a cleaner alternative lives here: <https://discourse.nixos.org/t/how-can-i-run-the-updatescript-of-personal-packages/25274/2>
|
||||||
|
# mkUpdater :: [ String ] -> { type = "app"; program = path; }
|
||||||
mkUpdater = attrPath: {
|
mkUpdater = attrPath: {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = let
|
program = let
|
||||||
@@ -293,7 +303,7 @@
|
|||||||
} else {}
|
} else {}
|
||||||
)
|
)
|
||||||
(pkgs.lib.getAttrFromPath basePath sanePkgs);
|
(pkgs.lib.getAttrFromPath basePath sanePkgs);
|
||||||
mkUpdaters = { ignore ? [] }@opts: basePath:
|
mkUpdaters = { ignore ? [], flakePrefix ? [] }@opts: basePath:
|
||||||
let
|
let
|
||||||
updaters = mkUpdatersNoAliases opts basePath;
|
updaters = mkUpdatersNoAliases opts basePath;
|
||||||
invokeUpdater = name: pkg:
|
invokeUpdater = name: pkg:
|
||||||
@@ -303,7 +313,7 @@
|
|||||||
|
|
||||||
# in case `name` has a `.` in it, we have to quote it
|
# in case `name` has a `.` in it, we have to quote it
|
||||||
escapedPath = builtins.map (p: ''"${p}"'') fullPath;
|
escapedPath = builtins.map (p: ''"${p}"'') fullPath;
|
||||||
updatePath = builtins.concatStringsSep "." ([ "update" "pkgs" ] ++ escapedPath);
|
updatePath = builtins.concatStringsSep "." (flakePrefix ++ escapedPath);
|
||||||
in pkgs.lib.optionalString doUpdateByDefault (
|
in pkgs.lib.optionalString doUpdateByDefault (
|
||||||
pkgs.lib.escapeShellArgs [
|
pkgs.lib.escapeShellArgs [
|
||||||
"nix" "run" ".#${updatePath}"
|
"nix" "run" ".#${updatePath}"
|
||||||
@@ -311,8 +321,9 @@
|
|||||||
);
|
);
|
||||||
in {
|
in {
|
||||||
type = "app";
|
type = "app";
|
||||||
|
# top-level app just invokes the updater of everything one layer below it
|
||||||
program = builtins.toString (pkgs.writeShellScript
|
program = builtins.toString (pkgs.writeShellScript
|
||||||
(builtins.concatStringsSep "-" (["update"] ++ basePath))
|
(builtins.concatStringsSep "-" (flakePrefix ++ basePath))
|
||||||
(builtins.concatStringsSep
|
(builtins.concatStringsSep
|
||||||
"\n"
|
"\n"
|
||||||
(pkgs.lib.mapAttrsToList invokeUpdater updaters)
|
(pkgs.lib.mapAttrsToList invokeUpdater updaters)
|
||||||
@@ -332,7 +343,7 @@
|
|||||||
- `nix run '.#update.feeds'`
|
- `nix run '.#update.feeds'`
|
||||||
- updates metadata for all feeds
|
- updates metadata for all feeds
|
||||||
- `nix run '.#init-feed' <url>`
|
- `nix run '.#init-feed' <url>`
|
||||||
- `nix run '.#deploy-{lappy,moby,moby-test,servo}' [nixos-rebuild args ...]`
|
- `nix run '.#deploy.{desko,lappy,moby,servo}[-light][.test]' [nixos-rebuild args ...]`
|
||||||
- `nix run '.#check'`
|
- `nix run '.#check'`
|
||||||
- make sure all systems build; NUR evaluates
|
- make sure all systems build; NUR evaluates
|
||||||
|
|
||||||
@@ -346,29 +357,27 @@
|
|||||||
nix flake show --option allow-import-from-derivation true
|
nix flake show --option allow-import-from-derivation true
|
||||||
'');
|
'');
|
||||||
};
|
};
|
||||||
update.pkgs = mkUpdaters { ignore = [ ["feeds"] ]; } [];
|
# wrangle some names to get package updaters which refer back into the flake, but also conditionally ignore certain paths (e.g. sane.feeds).
|
||||||
update.feeds = mkUpdaters {} [ "feeds" ];
|
# TODO: better design
|
||||||
|
update = rec {
|
||||||
|
_impl.pkgs.sane = mkUpdaters { flakePrefix = [ "update" "_impl" "pkgs" ]; ignore = [ [ "sane" "feeds" ] ]; } [ "sane" ];
|
||||||
|
pkgs = _impl.pkgs.sane;
|
||||||
|
_impl.feeds.sane.feeds = mkUpdaters { flakePrefix = [ "update" "_impl" "feeds" ]; } [ "sane" "feeds" ];
|
||||||
|
feeds = _impl.feeds.sane.feeds;
|
||||||
|
};
|
||||||
|
|
||||||
init-feed = {
|
init-feed = {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = "${pkgs.feeds.init-feed}";
|
program = "${pkgs.feeds.init-feed}";
|
||||||
};
|
};
|
||||||
|
|
||||||
deploy-lappy = {
|
deploy = {
|
||||||
type = "app";
|
lappy = deployApp "lappy" "lappy" "switch";
|
||||||
program = ''${deployScript "lappy" "lappy" "switch"}'';
|
lappy-light = deployApp "lappy-light" "lappy" "switch";
|
||||||
};
|
moby = deployApp "moby" "moby" "switch";
|
||||||
deploy-moby-test = {
|
moby-light = deployApp "moby-light" "moby" "switch";
|
||||||
type = "app";
|
moby-test = deployApp "moby" "moby" "test";
|
||||||
program = ''${deployScript "moby" "moby-hn" "test"}'';
|
servo = deployApp "servo" "servo" "switch";
|
||||||
};
|
|
||||||
deploy-moby = {
|
|
||||||
type = "app";
|
|
||||||
program = ''${deployScript "moby" "moby-hn" "switch"}'';
|
|
||||||
};
|
|
||||||
deploy-servo = {
|
|
||||||
type = "app";
|
|
||||||
program = ''${deployScript "servo" "servo" "switch"}'';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
sync-moby = {
|
sync-moby = {
|
||||||
@@ -427,18 +436,27 @@
|
|||||||
check.host-configs = {
|
check.host-configs = {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = let
|
program = let
|
||||||
checkHost = host: ''
|
checkHost = host: let
|
||||||
|
shellHost = pkgs.lib.replaceStrings [ "-" ] [ "_" ] host;
|
||||||
|
in ''
|
||||||
nix build -v '.#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}=$?
|
RC_${shellHost}=$?
|
||||||
'';
|
'';
|
||||||
in builtins.toString (pkgs.writeShellScript
|
in builtins.toString (pkgs.writeShellScript
|
||||||
"check-host-configs"
|
"check-host-configs"
|
||||||
''
|
''
|
||||||
|
# build minimally-usable hosts first, then their full image.
|
||||||
|
# this gives me a minimal image i can deploy or copy over, early.
|
||||||
|
${checkHost "desko-light"}
|
||||||
|
${checkHost "moby-light"}
|
||||||
|
${checkHost "lappy-light"}
|
||||||
|
|
||||||
${checkHost "desko"}
|
${checkHost "desko"}
|
||||||
${checkHost "lappy"}
|
${checkHost "lappy"}
|
||||||
${checkHost "servo"}
|
${checkHost "servo"}
|
||||||
${checkHost "moby"}
|
${checkHost "moby"}
|
||||||
${checkHost "rescue"}
|
${checkHost "rescue"}
|
||||||
|
|
||||||
echo "desko: $RC_desko"
|
echo "desko: $RC_desko"
|
||||||
echo "lappy: $RC_lappy"
|
echo "lappy: $RC_lappy"
|
||||||
echo "servo: $RC_servo"
|
echo "servo: $RC_servo"
|
||||||
|
@@ -11,23 +11,29 @@
|
|||||||
|
|
||||||
sops.secrets.colin-passwd.neededForUsers = true;
|
sops.secrets.colin-passwd.neededForUsers = true;
|
||||||
|
|
||||||
|
sane.ports.openFirewall = true; # for e.g. nix-serve
|
||||||
|
|
||||||
sane.roles.build-machine.enable = true;
|
sane.roles.build-machine.enable = true;
|
||||||
sane.roles.ac = true;
|
|
||||||
sane.roles.client = true;
|
sane.roles.client = true;
|
||||||
sane.roles.dev-machine = true;
|
sane.roles.dev-machine = true;
|
||||||
|
sane.roles.pc = true;
|
||||||
sane.services.wg-home.enable = true;
|
sane.services.wg-home.enable = true;
|
||||||
sane.services.wg-home.ip = config.sane.hosts.by-name."desko".wg-home.ip;
|
sane.services.wg-home.ip = config.sane.hosts.by-name."desko".wg-home.ip;
|
||||||
sane.services.duplicity.enable = true;
|
sane.services.duplicity.enable = true;
|
||||||
sane.services.nixserve.secretKeyFile = config.sops.secrets.nix_serve_privkey.path;
|
sane.services.nixserve.secretKeyFile = config.sops.secrets.nix_serve_privkey.path;
|
||||||
|
|
||||||
|
sane.nixcache.substituters.desko = false;
|
||||||
|
sane.nixcache.remote-builders.desko = false;
|
||||||
|
|
||||||
sane.gui.sway.enable = true;
|
sane.gui.sway.enable = true;
|
||||||
sane.programs.iphoneUtils.enableFor.user.colin = true;
|
sane.programs.iphoneUtils.enableFor.user.colin = true;
|
||||||
sane.programs.steam.enableFor.user.colin = true;
|
sane.programs.steam.enableFor.user.colin = true;
|
||||||
|
|
||||||
sane.programs.guiApps.suggestedPrograms = [ "desktopGuiApps" ];
|
|
||||||
sane.programs.consoleUtils.suggestedPrograms = [ "consoleMediaUtils" "desktopConsoleUtils" ];
|
|
||||||
# sane.programs.devPkgs.enableFor.user.colin = true;
|
# sane.programs.devPkgs.enableFor.user.colin = true;
|
||||||
|
|
||||||
|
sane.programs.signal-desktop.config.autostart = true;
|
||||||
|
sane.programs."gnome.geary".config.autostart = true;
|
||||||
|
|
||||||
boot.loader.efi.canTouchEfiVariables = false;
|
boot.loader.efi.canTouchEfiVariables = false;
|
||||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||||
|
|
||||||
|
@@ -1,14 +1,13 @@
|
|||||||
{ ... }:
|
{ ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
sane.persist.root-on-tmpfs = true;
|
|
||||||
# increase /tmp space (defaults to 50% of RAM) for building large nix things.
|
# increase /tmp space (defaults to 50% of RAM) for building large nix things.
|
||||||
# a cross-compiled kernel, particularly, will easily use 30+GB of tmp
|
# a cross-compiled kernel, particularly, will easily use 30+GB of tmp
|
||||||
fileSystems."/tmp".options = [ "size=64G" ];
|
fileSystems."/tmp".options = [ "size=64G" ];
|
||||||
|
|
||||||
fileSystems."/nix" = {
|
fileSystems."/nix" = {
|
||||||
# device = "/dev/disk/by-uuid/985a0a32-da52-4043-9df7-615adec2e4ff";
|
# device = "/dev/disk/by-uuid/0ab0770b-7734-4167-88d9-6e4e20bb2a56";
|
||||||
device = "/dev/disk/by-uuid/0ab0770b-7734-4167-88d9-6e4e20bb2a56";
|
device = "/dev/disk/by-uuid/845d85bf-761d-431b-a406-e6f20909154f";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [
|
options = [
|
||||||
"compress=zstd"
|
"compress=zstd"
|
||||||
@@ -17,8 +16,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/boot" = {
|
fileSystems."/boot" = {
|
||||||
# device = "/dev/disk/by-uuid/CAA7-E7D2";
|
# device = "/dev/disk/by-uuid/41B6-BAEF";
|
||||||
device = "/dev/disk/by-uuid/41B6-BAEF";
|
device = "/dev/disk/by-uuid/5049-9AFD";
|
||||||
fsType = "vfat";
|
fsType = "vfat";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
sane.roles.client = true;
|
sane.roles.client = true;
|
||||||
sane.roles.dev-machine = true;
|
sane.roles.dev-machine = true;
|
||||||
|
sane.roles.pc = true;
|
||||||
sane.services.wg-home.enable = true;
|
sane.services.wg-home.enable = true;
|
||||||
sane.services.wg-home.ip = config.sane.hosts.by-name."lappy".wg-home.ip;
|
sane.services.wg-home.ip = config.sane.hosts.by-name."lappy".wg-home.ip;
|
||||||
|
|
||||||
@@ -15,11 +16,7 @@
|
|||||||
boot.loader.efi.canTouchEfiVariables = false;
|
boot.loader.efi.canTouchEfiVariables = false;
|
||||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||||
|
|
||||||
sane.programs.guiApps.suggestedPrograms = [
|
sane.programs.stepmania.enableFor.user.colin = true;
|
||||||
"desktopGuiApps"
|
|
||||||
"stepmania"
|
|
||||||
];
|
|
||||||
sane.programs.consoleUtils.suggestedPrograms = [ "consoleMediaUtils" "desktopConsoleUtils" ];
|
|
||||||
|
|
||||||
sops.secrets.colin-passwd.neededForUsers = true;
|
sops.secrets.colin-passwd.neededForUsers = true;
|
||||||
|
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
{ ... }:
|
{ ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
sane.persist.root-on-tmpfs = true;
|
|
||||||
|
|
||||||
fileSystems."/nix" = {
|
fileSystems."/nix" = {
|
||||||
device = "/dev/disk/by-uuid/75230e56-2c69-4e41-b03e-68475f119980";
|
device = "/dev/disk/by-uuid/75230e56-2c69-4e41-b03e-68475f119980";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
# and so it just wouldn't handle any button inputs (sxmo_hook_inputhandler.sh not on path)
|
# and so it just wouldn't handle any button inputs (sxmo_hook_inputhandler.sh not on path)
|
||||||
SXMO_DEVICE_NAME = "three_button_touchscreen";
|
SXMO_DEVICE_NAME = "three_button_touchscreen";
|
||||||
};
|
};
|
||||||
package = (pkgs.sxmo-utils-latest.override { preferSystemd = true; }).overrideAttrs (base: {
|
package = (pkgs.sxmo-utils.override { preferSystemd = true; }).overrideAttrs (base: {
|
||||||
postPatch = (base.postPatch or "") + ''
|
postPatch = (base.postPatch or "") + ''
|
||||||
# after volume-button navigation mode, restore full keyboard functionality
|
# after volume-button navigation mode, restore full keyboard functionality
|
||||||
cp ${./xkb_mobile_normal_buttons} ./configs/xkb/xkb_mobile_normal_buttons
|
cp ${./xkb_mobile_normal_buttons} ./configs/xkb/xkb_mobile_normal_buttons
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
sane.roles.client = true;
|
sane.roles.client = true;
|
||||||
|
sane.roles.handheld = true;
|
||||||
sane.zsh.showDeadlines = false; # unlikely to act on them when in shell
|
sane.zsh.showDeadlines = false; # unlikely to act on them when in shell
|
||||||
sane.services.wg-home.enable = true;
|
sane.services.wg-home.enable = true;
|
||||||
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;
|
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;
|
||||||
@@ -32,15 +33,12 @@
|
|||||||
sops.secrets.colin-passwd.neededForUsers = true;
|
sops.secrets.colin-passwd.neededForUsers = true;
|
||||||
|
|
||||||
sane.gui.sxmo.enable = true;
|
sane.gui.sxmo.enable = true;
|
||||||
sane.programs.guiApps.suggestedPrograms = [ "handheldGuiApps" ];
|
|
||||||
# sane.programs.consoleUtils.enableFor.user.colin = false;
|
# sane.programs.consoleUtils.enableFor.user.colin = false;
|
||||||
# sane.programs.guiApps.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.blueberry.enableFor.user.colin = false; # bluetooth manager: doesn't cross compile!
|
||||||
|
sane.programs.dialect.enableFor.user.colin = false; # drags in 700MB of x86 dependencies (e.g. gtk4)
|
||||||
sane.programs.mercurial.enableFor.user.colin = false; # does not cross compile
|
sane.programs.mercurial.enableFor.user.colin = false; # does not cross compile
|
||||||
sane.programs.sequoia.enableFor.user.colin = false;
|
sane.programs.nvme-cli.enableFor.system = false; # does not cross compile (libhugetlbfs)
|
||||||
sane.programs.tuiApps.enableFor.user.colin = false; # visidata, others, don't compile well
|
|
||||||
# disabled for faster deploys
|
|
||||||
sane.programs.soundconverter.enableFor.user.colin = false;
|
|
||||||
|
|
||||||
# enabled for easier debugging
|
# enabled for easier debugging
|
||||||
sane.programs.eg25-control.enableFor.user.colin = true;
|
sane.programs.eg25-control.enableFor.user.colin = true;
|
||||||
@@ -48,6 +46,8 @@
|
|||||||
|
|
||||||
# sane.programs.ntfy-sh.config.autostart = true;
|
# sane.programs.ntfy-sh.config.autostart = true;
|
||||||
sane.programs.dino.config.autostart = true;
|
sane.programs.dino.config.autostart = true;
|
||||||
|
sane.programs.signal-desktop.config.autostart = true;
|
||||||
|
# sane.programs."gnome.geary".config.autostart = true;
|
||||||
# sane.programs.calls.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.mpv.config.vo = "wlshm"; #< see hosts/common/programs/mpv.nix for details
|
||||||
|
|
||||||
@@ -55,7 +55,6 @@
|
|||||||
# HACK/TODO: make `programs.P.env.VAR` behave according to `mime.priority`
|
# HACK/TODO: make `programs.P.env.VAR` behave according to `mime.priority`
|
||||||
sane.programs.firefox.env = lib.mkForce {};
|
sane.programs.firefox.env = lib.mkForce {};
|
||||||
sane.programs.epiphany.env.BROWSER = "epiphany";
|
sane.programs.epiphany.env.BROWSER = "epiphany";
|
||||||
sane.programs.firefox.enableFor.user.colin = false; # use epiphany instead
|
|
||||||
|
|
||||||
# note the .conf.d approach: using ~/.config/pipewire/pipewire.conf directly breaks all audio,
|
# note the .conf.d approach: using ~/.config/pipewire/pipewire.conf directly breaks all audio,
|
||||||
# presumably because that deletes the defaults entirely whereas the .conf.d approach selectively overrides defaults
|
# presumably because that deletes the defaults entirely whereas the .conf.d approach selectively overrides defaults
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
{ ... }:
|
{ ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
sane.persist.root-on-tmpfs = true;
|
|
||||||
fileSystems."/nix" = {
|
fileSystems."/nix" = {
|
||||||
device = "/dev/disk/by-uuid/1f1271f8-53ce-4081-8a29-60a4a6b5d6f9";
|
device = "/dev/disk/by-uuid/1f1271f8-53ce-4081-8a29-60a4a6b5d6f9";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
{ ... }:
|
{ ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
fileSystems."/" = {
|
fileSystems."/nix" = {
|
||||||
device = "/dev/disk/by-uuid/44445555-6666-7777-8888-999900001111";
|
device = "/dev/disk/by-uuid/44445555-6666-7777-8888-999900001111";
|
||||||
fsType = "ext4";
|
fsType = "ext4";
|
||||||
};
|
};
|
||||||
|
@@ -14,12 +14,11 @@
|
|||||||
signaldctl.enableFor.user.colin = true;
|
signaldctl.enableFor.user.colin = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.roles.ac = true;
|
|
||||||
sane.roles.build-machine.enable = true;
|
sane.roles.build-machine.enable = true;
|
||||||
sane.roles.build-machine.emulation = false;
|
sane.roles.build-machine.emulation = false;
|
||||||
sane.zsh.showDeadlines = false; # ~/knowledge doesn't always exist
|
sane.zsh.showDeadlines = false; # ~/knowledge doesn't always exist
|
||||||
sane.programs.consoleUtils.suggestedPrograms = [
|
sane.programs.consoleUtils.suggestedPrograms = [
|
||||||
"desktopConsoleUtils"
|
"pcConsoleUtils"
|
||||||
"sane-scripts.stop-all-servo"
|
"sane-scripts.stop-all-servo"
|
||||||
];
|
];
|
||||||
sane.services.dyn-dns.enable = true;
|
sane.services.dyn-dns.enable = true;
|
||||||
@@ -30,6 +29,8 @@
|
|||||||
sane.services.wg-home.ip = config.sane.hosts.by-name."servo".wg-home.ip;
|
sane.services.wg-home.ip = config.sane.hosts.by-name."servo".wg-home.ip;
|
||||||
sane.nixcache.substituters.servo = false;
|
sane.nixcache.substituters.servo = false;
|
||||||
sane.nixcache.substituters.desko = false;
|
sane.nixcache.substituters.desko = false;
|
||||||
|
sane.nixcache.remote-builders.desko = false;
|
||||||
|
sane.nixcache.remote-builders.servo = false;
|
||||||
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade
|
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade
|
||||||
|
|
||||||
# automatically log in at the virtual consoles.
|
# automatically log in at the virtual consoles.
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
{ ... }:
|
{ ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
sane.persist.root-on-tmpfs = true;
|
|
||||||
# increase /tmp space (defaults to 50% of RAM) for building large nix things.
|
# increase /tmp space (defaults to 50% of RAM) for building large nix things.
|
||||||
# even the stock `nixpkgs.linux` consumes > 16 GB of tmp
|
# even the stock `nixpkgs.linux` consumes > 16 GB of tmp
|
||||||
fileSystems."/tmp".options = [ "size=32G" ];
|
fileSystems."/tmp".options = [ "size=32G" ];
|
||||||
@@ -69,7 +68,7 @@
|
|||||||
the contents should be a subset of what's in ../media/datasets.
|
the contents should be a subset of what's in ../media/datasets.
|
||||||
'';
|
'';
|
||||||
# make sure large media is stored to the HDD
|
# make sure large media is stored to the HDD
|
||||||
sane.persist.sys.ext = [
|
sane.persist.sys.byStore.ext = [
|
||||||
{
|
{
|
||||||
user = "colin";
|
user = "colin";
|
||||||
group = "users";
|
group = "users";
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
./komga.nix
|
./komga.nix
|
||||||
./lemmy.nix
|
./lemmy.nix
|
||||||
./matrix
|
./matrix
|
||||||
|
./monero.nix
|
||||||
./navidrome.nix
|
./navidrome.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./nixserve.nix
|
./nixserve.nix
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
./pleroma.nix
|
./pleroma.nix
|
||||||
./postgres.nix
|
./postgres.nix
|
||||||
./prosody
|
./prosody
|
||||||
|
./slskd.nix
|
||||||
./transmission.nix
|
./transmission.nix
|
||||||
./trust-dns.nix
|
./trust-dns.nix
|
||||||
./wikipedia.nix
|
./wikipedia.nix
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
# - `sudo btrfs qgroup limit 20G /mnt/persist/ext/persist/var/export/playground`
|
# - `sudo btrfs qgroup limit 20G /mnt/persist/ext/persist/var/export/playground`
|
||||||
# to query the quota/status:
|
# to query the quota/status:
|
||||||
# - `sudo btrfs qgroup show -re /var/export/playground`
|
# - `sudo btrfs qgroup show -re /var/export/playground`
|
||||||
sane.persist.sys.ext = [
|
sane.persist.sys.byStore.ext = [
|
||||||
{ user = "root"; group = "export"; mode = "0775"; path = "/var/export/playground"; }
|
{ user = "root"; group = "export"; mode = "0775"; path = "/var/export/playground"; }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@@ -13,6 +13,10 @@
|
|||||||
services.gitea.appName = "Perfectly Sane Git";
|
services.gitea.appName = "Perfectly Sane Git";
|
||||||
# services.gitea.disableRegistration = true;
|
# services.gitea.disableRegistration = true;
|
||||||
|
|
||||||
|
services.gitea.database.createDatabase = false; #< silence warning which wants db user and name to be equal
|
||||||
|
# TODO: remove this after merge: <https://github.com/NixOS/nixpkgs/pull/268849>
|
||||||
|
services.gitea.database.socket = "/run/postgresql"; #< would have been set if createDatabase = true
|
||||||
|
|
||||||
# gitea doesn't create the git user
|
# gitea doesn't create the git user
|
||||||
users.users.git = {
|
users.users.git = {
|
||||||
description = "Gitea Service";
|
description = "Gitea Service";
|
||||||
|
37
hosts/by-name/servo/services/monero.nix
Normal file
37
hosts/by-name/servo/services/monero.nix
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# as of 2023/11/26: complete downloaded blockchain should be 200GiB on disk, give or take.
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.persist.sys.byStore.ext = [
|
||||||
|
# /var/lib/monero/lmdb is what consumes most of the space
|
||||||
|
{ user = "monero"; group = "monero"; path = "/var/lib/monero"; }
|
||||||
|
];
|
||||||
|
|
||||||
|
services.monero.enable = true;
|
||||||
|
services.monero.limits.upload = 5000; # in kB/s
|
||||||
|
services.monero.extraConfig = ''
|
||||||
|
# see: monero doc/ANONYMITY_NETWORKS.md
|
||||||
|
#
|
||||||
|
# "If any anonymity network is enabled, transactions being broadcast that lack a valid 'context'
|
||||||
|
# (i.e. the transaction did not come from a P2P connection) will only be sent to peers on anonymity networks."
|
||||||
|
#
|
||||||
|
# i think this means that setting tx-proxy here ensures any transactions sent locally to my node (via RPC)
|
||||||
|
# will be sent over an anonymity network.
|
||||||
|
tx-proxy=i2p,127.0.0.1:9000
|
||||||
|
tx-proxy=tor,127.0.0.1:9050
|
||||||
|
'';
|
||||||
|
|
||||||
|
services.i2p.enable = true;
|
||||||
|
# tor: `tor.enable` doesn't start a relay, exit node, proxy, etc. it's minimal.
|
||||||
|
# tor.client.enable configures a torsocks proxy, accessible *only* to localhost.
|
||||||
|
services.tor.enable = true;
|
||||||
|
services.tor.client.enable = true;
|
||||||
|
|
||||||
|
# monero ports: <https://monero.stackexchange.com/questions/604/what-ports-does-monero-use-rpc-p2p-etc>
|
||||||
|
# - 18080 = "P2P" monero node <-> monero node connections
|
||||||
|
# - 18081 = "RPC" monero client -> monero node connections
|
||||||
|
sane.ports.ports."18080" = {
|
||||||
|
protocol = [ "tcp" ];
|
||||||
|
visibleTo.wan = true;
|
||||||
|
description = "colin-monero-p2p";
|
||||||
|
};
|
||||||
|
}
|
74
hosts/by-name/servo/services/slskd.nix
Normal file
74
hosts/by-name/servo/services/slskd.nix
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# Soulseek daemon (p2p file sharing with an emphasis on Music)
|
||||||
|
# docs: <https://github.com/slskd/slskd/blob/master/docs/config.md>
|
||||||
|
#
|
||||||
|
# config precedence (higher precedence overrules lower precedence):
|
||||||
|
# - Default Values < Environment Variables < YAML Configuraiton File < Command Line Arguments
|
||||||
|
{ config, lib, ... }:
|
||||||
|
{
|
||||||
|
sane.persist.sys.byStore.plaintext = [
|
||||||
|
{ user = "slskd"; group = "slskd"; path = "/var/lib/slskd"; }
|
||||||
|
];
|
||||||
|
sops.secrets."slskd_env" = {
|
||||||
|
owner = config.users.users.slskd.name;
|
||||||
|
mode = "0400";
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users.slskd.extraGroups = [ "media" ];
|
||||||
|
|
||||||
|
sane.ports.ports."50000" = {
|
||||||
|
protocol = [ "tcp" ];
|
||||||
|
# not visible to WAN: i run this in a separate netns
|
||||||
|
visibleTo.ovpn = true;
|
||||||
|
description = "colin-soulseek";
|
||||||
|
};
|
||||||
|
|
||||||
|
sane.dns.zones."uninsane.org".inet.CNAME."soulseek" = "native";
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."soulseek.uninsane.org" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://10.0.1.6:5001";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.slskd.enable = true;
|
||||||
|
# env file, for auth (SLSKD_SLSK_PASSWORD, SLSKD_SLSK_USERNAME)
|
||||||
|
services.slskd.environmentFile = config.sops.secrets.slskd_env.path;
|
||||||
|
services.slskd.settings = {
|
||||||
|
soulseek.diagnostic_level = "Debug"; # one of "None"|"Warning"|"Info"|"Debug"
|
||||||
|
shares.directories = [
|
||||||
|
# folders to share
|
||||||
|
# syntax: <https://github.com/slskd/slskd/blob/master/docs/config.md#directories>
|
||||||
|
# [Alias]/path/on/disk
|
||||||
|
# NOTE: Music library is quick to scan; videos take a solid 10min to scan.
|
||||||
|
# TODO: re-enable the other libraries
|
||||||
|
# "[Audioooks]/var/lib/uninsane/media/Books/Audiobooks"
|
||||||
|
# "[Books]/var/lib/uninsane/media/Books/Books"
|
||||||
|
# "[Manga]/var/lib/uninsane/media/Books/Visual"
|
||||||
|
# "[games]/var/lib/uninsane/media/games"
|
||||||
|
"[Music]/var/lib/uninsane/media/Music"
|
||||||
|
# "[Film]/var/lib/uninsane/media/Videos/Film"
|
||||||
|
# "[Shows]/var/lib/uninsane/media/Videos/Shows"
|
||||||
|
];
|
||||||
|
# directories.downloads = "..." # TODO
|
||||||
|
# directories.incomplete = "..." # TODO
|
||||||
|
# what unit is this? kbps??
|
||||||
|
global.upload.speed_limit = 32000;
|
||||||
|
web.logging = true;
|
||||||
|
debug = true;
|
||||||
|
flags.no_logo = true; # don't show logo at start
|
||||||
|
# flags.volatile = true; # store searches and active transfers in RAM (completed transfers still go to disk). rec for btrfs/zfs
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.slskd = {
|
||||||
|
serviceConfig = {
|
||||||
|
# run this behind the OVPN static VPN
|
||||||
|
NetworkNamespacePath = "/run/netns/ovpns";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = "30s";
|
||||||
|
Group = "media";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@@ -91,5 +91,10 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
sane.dns.zones."uninsane.org".inet.CNAME."bt" = "native";
|
sane.dns.zones."uninsane.org".inet.CNAME."bt" = "native";
|
||||||
|
sane.ports.ports."51413" = {
|
||||||
|
protocol = [ "tcp" "udp" ];
|
||||||
|
visibleTo.ovpn = true;
|
||||||
|
description = "colin-bittorrent";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,6 +11,8 @@ in lib.mkMerge [
|
|||||||
# don't bind to IPv6 until i explicitly test that stack
|
# don't bind to IPv6 until i explicitly test that stack
|
||||||
services.trust-dns.settings.listen_addrs_ipv6 = [];
|
services.trust-dns.settings.listen_addrs_ipv6 = [];
|
||||||
services.trust-dns.quiet = true;
|
services.trust-dns.quiet = true;
|
||||||
|
# FIXME(2023/11/26): services.trust-dns.debug doesn't log requests: use RUST_LOG=debug env for that.
|
||||||
|
# - see: <https://github.com/hickory-dns/hickory-dns/issues/2082>
|
||||||
# services.trust-dns.debug = true;
|
# services.trust-dns.debug = true;
|
||||||
|
|
||||||
sane.ports.ports."53" = {
|
sane.ports.ports."53" = {
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
./fs.nix
|
./fs.nix
|
||||||
./hardware
|
./hardware
|
||||||
./home
|
./home
|
||||||
|
./hostnames.nix
|
||||||
./hosts.nix
|
./hosts.nix
|
||||||
./ids.nix
|
./ids.nix
|
||||||
./machine-id.nix
|
./machine-id.nix
|
||||||
@@ -21,25 +22,46 @@
|
|||||||
sane.nixcache.enable-trusted-keys = true;
|
sane.nixcache.enable-trusted-keys = true;
|
||||||
sane.nixcache.enable = lib.mkDefault true;
|
sane.nixcache.enable = lib.mkDefault true;
|
||||||
sane.persist.enable = lib.mkDefault true;
|
sane.persist.enable = lib.mkDefault true;
|
||||||
|
sane.root-on-tmpfs = lib.mkDefault true;
|
||||||
sane.programs.sysadminUtils.enableFor.system = lib.mkDefault true;
|
sane.programs.sysadminUtils.enableFor.system = lib.mkDefault true;
|
||||||
sane.programs.consoleUtils.enableFor.user.colin = lib.mkDefault true;
|
sane.programs.consoleUtils.enableFor.user.colin = lib.mkDefault true;
|
||||||
|
|
||||||
nixpkgs.config.allowUnfree = true;
|
nixpkgs.config.allowUnfree = true; # NIXPKGS_ALLOW_UNFREE=1
|
||||||
nixpkgs.config.allowBroken = true; # NIXPKGS_ALLOW_BROKEN
|
nixpkgs.config.allowBroken = true; # NIXPKGS_ALLOW_BROKEN=1
|
||||||
|
|
||||||
# time.timeZone = "America/Los_Angeles";
|
# time.timeZone = "America/Los_Angeles";
|
||||||
time.timeZone = "Etc/UTC"; # DST is too confusing for me => use a stable timezone
|
time.timeZone = "Etc/UTC"; # DST is too confusing for me => use a stable timezone
|
||||||
|
|
||||||
# allow `nix flake ...` command
|
|
||||||
# TODO: is this still required?
|
|
||||||
nix.extraOptions = ''
|
nix.extraOptions = ''
|
||||||
|
# see: `man nix.conf`
|
||||||
|
# useful when a remote builder has a faster internet connection than me
|
||||||
|
builders-use-substitutes = true # default: false
|
||||||
|
# maximum seconds to wait when connecting to binary substituter
|
||||||
|
connect-timeout = 3 # default: 0
|
||||||
|
# download-attempts = 5 # default: 5
|
||||||
|
# allow `nix flake ...` command
|
||||||
experimental-features = nix-command flakes
|
experimental-features = nix-command flakes
|
||||||
|
# whether to build from source when binary substitution fails
|
||||||
|
fallback = true # default: false
|
||||||
|
# whether to keep building dependencies if any other one fails
|
||||||
|
keep-going = true # default: false
|
||||||
|
# whether to keep build-only dependencies of GC roots (e.g. C compiler) when doing GC
|
||||||
|
keep-outputs = true # default: false
|
||||||
|
# how many lines to show from failed build
|
||||||
|
log-lines = 30 # default: 10
|
||||||
|
# narinfo-cache-negative-ttl = 3600 # default: 3600
|
||||||
|
# whether to use ~/.local/state/nix/profile instead of ~/.nix-profile, etc
|
||||||
|
use-xdg-base-directories = true # default: false
|
||||||
|
# whether to warn if repository has uncommited changes
|
||||||
|
warn-dirty = false # default: true
|
||||||
'';
|
'';
|
||||||
# hardlinks identical files in the nix store to save 25-35% disk space.
|
# hardlinks identical files in the nix store to save 25-35% disk space.
|
||||||
# unclear _when_ this occurs. it's not a service.
|
# unclear _when_ this occurs. it's not a service.
|
||||||
# does the daemon continually scan the nix store?
|
# does the daemon continually scan the nix store?
|
||||||
# does the builder use some content-addressed db to efficiently dedupe?
|
# does the builder use some content-addressed db to efficiently dedupe?
|
||||||
nix.settings.auto-optimise-store = true;
|
nix.settings.auto-optimise-store = true;
|
||||||
|
# TODO: see if i can remove this?
|
||||||
|
nix.settings.trusted-users = [ "root" ];
|
||||||
|
|
||||||
services.journald.extraConfig = ''
|
services.journald.extraConfig = ''
|
||||||
# docs: `man journald.conf`
|
# docs: `man journald.conf`
|
||||||
|
@@ -77,6 +77,7 @@ let
|
|||||||
(fromDb "feeds.simplecast.com/82FI35Px" // pol) # Ezra Klein Show
|
(fromDb "feeds.simplecast.com/82FI35Px" // pol) # Ezra Klein Show
|
||||||
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat) # Econ Talk
|
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat) # Econ Talk
|
||||||
(fromDb "feeds.simplecast.com/xKJ93w_w" // uncat) # Atlas Obscura
|
(fromDb "feeds.simplecast.com/xKJ93w_w" // uncat) # Atlas Obscura
|
||||||
|
(fromDb "feeds.simplecast.com/l2i9YnTd" // tech // pol) # Hard Fork (NYtimes tech)
|
||||||
(fromDb "feeds.transistor.fm/acquired" // tech)
|
(fromDb "feeds.transistor.fm/acquired" // tech)
|
||||||
(fromDb "lexfridman.com/podcast" // rat)
|
(fromDb "lexfridman.com/podcast" // rat)
|
||||||
(fromDb "mapspodcast.libsyn.com" // uncat) # Multidisciplinary Association for Psychedelic Studies
|
(fromDb "mapspodcast.libsyn.com" // uncat) # Multidisciplinary Association for Psychedelic Studies
|
||||||
@@ -136,10 +137,12 @@ let
|
|||||||
# DEVELOPERS
|
# DEVELOPERS
|
||||||
(fromDb "blog.jmp.chat" // tech)
|
(fromDb "blog.jmp.chat" // tech)
|
||||||
(fromDb "uninsane.org" // tech)
|
(fromDb "uninsane.org" // tech)
|
||||||
|
(fromDb "blog.thalheim.io" // tech) # Mic92
|
||||||
(fromDb "ascii.textfiles.com" // tech) # Jason Scott
|
(fromDb "ascii.textfiles.com" // tech) # Jason Scott
|
||||||
(fromDb "xn--gckvb8fzb.com" // tech)
|
(fromDb "xn--gckvb8fzb.com" // tech)
|
||||||
(fromDb "amosbbatto.wordpress.com" // tech)
|
(fromDb "amosbbatto.wordpress.com" // tech)
|
||||||
(fromDb "fasterthanli.me" // tech)
|
(fromDb "fasterthanli.me" // tech)
|
||||||
|
(fromDb "jeffgeerling.com" // tech)
|
||||||
(fromDb "mg.lol" // tech)
|
(fromDb "mg.lol" // tech)
|
||||||
# (fromDb "drewdevault.com" // tech)
|
# (fromDb "drewdevault.com" // tech)
|
||||||
## Ken Shirriff
|
## Ken Shirriff
|
||||||
|
@@ -12,8 +12,9 @@
|
|||||||
copy_bin_and_libs ${pkgs.util-linux}/bin/{cfdisk,lsblk,lscpu}
|
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.gptfdisk}/bin/{cgdisk,gdisk}
|
||||||
copy_bin_and_libs ${pkgs.smartmontools}/bin/smartctl
|
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
|
copy_bin_and_libs ${pkgs.e2fsprogs}/bin/resize2fs
|
||||||
|
'' + lib.optionalString pkgs.stdenv.hostPlatform.isx86_64 ''
|
||||||
|
copy_bin_and_libs ${pkgs.nvme-cli}/bin/nvme # doesn't cross compile
|
||||||
'';
|
'';
|
||||||
boot.kernelParams = [
|
boot.kernelParams = [
|
||||||
"boot.shell_on_fail"
|
"boot.shell_on_fail"
|
||||||
|
16
hosts/common/hostnames.nix
Normal file
16
hosts/common/hostnames.nix
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# TODO: move to hosts/common/
|
||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# give each host a shortname that all the other hosts know, to allow easy comms.
|
||||||
|
networking.hosts = lib.mkMerge (builtins.map
|
||||||
|
(host: let
|
||||||
|
cfg = config.sane.hosts.by-name."${host}";
|
||||||
|
in {
|
||||||
|
"${cfg.lan-ip}" = [ host ];
|
||||||
|
} // lib.optionalAttrs (cfg.wg-home.ip != null) {
|
||||||
|
"${cfg.wg-home.ip}" = [ "${host}-hn" ];
|
||||||
|
})
|
||||||
|
(builtins.attrNames config.sane.hosts.by-name)
|
||||||
|
);
|
||||||
|
}
|
@@ -36,4 +36,10 @@
|
|||||||
wg-home.endpoint = "uninsane.org:51820";
|
wg-home.endpoint = "uninsane.org:51820";
|
||||||
lan-ip = "10.78.79.51";
|
lan-ip = "10.78.79.51";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sane.hosts.by-name."supercap" = {
|
||||||
|
ssh.authorized = false;
|
||||||
|
ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHf/mqqkX45EWAcquV04MC3SUljTApdclH1gjI19F+PA";
|
||||||
|
lan-ip = "10.78.79.232";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@@ -49,6 +49,10 @@
|
|||||||
sane.ids.media.gid = 2414;
|
sane.ids.media.gid = 2414;
|
||||||
sane.ids.ntfy-sh.uid = 2415;
|
sane.ids.ntfy-sh.uid = 2415;
|
||||||
sane.ids.ntfy-sh.gid = 2415;
|
sane.ids.ntfy-sh.gid = 2415;
|
||||||
|
sane.ids.monero.uid = 2416;
|
||||||
|
sane.ids.monero.gid = 2416;
|
||||||
|
sane.ids.slskd.uid = 2417;
|
||||||
|
sane.ids.slskd.gid = 2417;
|
||||||
|
|
||||||
sane.ids.colin.uid = 1000;
|
sane.ids.colin.uid = 1000;
|
||||||
sane.ids.guest.uid = 1100;
|
sane.ids.guest.uid = 1100;
|
||||||
@@ -63,6 +67,8 @@
|
|||||||
sane.ids.systemd-oom.uid = 2005;
|
sane.ids.systemd-oom.uid = 2005;
|
||||||
sane.ids.systemd-oom.gid = 2005;
|
sane.ids.systemd-oom.gid = 2005;
|
||||||
sane.ids.wireshark.gid = 2006;
|
sane.ids.wireshark.gid = 2006;
|
||||||
|
sane.ids.nixremote.uid = 2007;
|
||||||
|
sane.ids.nixremote.gid = 2007;
|
||||||
|
|
||||||
# found on graphical hosts
|
# found on graphical hosts
|
||||||
sane.ids.nm-iodine.uid = 2101; # desko/moby/lappy
|
sane.ids.nm-iodine.uid = 2101; # desko/moby/lappy
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
{ pkgs, ... }:
|
{ pkgs, sane-lib, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
# allow `nix-shell` (and probably nix-index?) to locate our patched and custom packages
|
# allow `nix-shell` (and probably nix-index?) to locate our patched and custom packages
|
||||||
@@ -10,4 +10,7 @@
|
|||||||
# to avoid switching so much during development
|
# to avoid switching so much during development
|
||||||
"nixpkgs-overlays=/home/colin/dev/nixos/hosts/common/nix-path/overlay"
|
"nixpkgs-overlays=/home/colin/dev/nixos/hosts/common/nix-path/overlay"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# ensure new deployments have a source of this repo with which they can bootstrap.
|
||||||
|
environment.etc."nixos".source = ../../..;
|
||||||
}
|
}
|
||||||
|
107
hosts/common/programs/abaddon.nix
Normal file
107
hosts/common/programs/abaddon.nix
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
# discord gtk3 client
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs.abaddon;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.abaddon = {
|
||||||
|
configOption = with lib; mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.submodule {
|
||||||
|
options.autostart = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
package = pkgs.abaddon.overrideAttrs (upstream: {
|
||||||
|
patches = (upstream.patches or []) ++ [
|
||||||
|
(pkgs.fetchpatch {
|
||||||
|
url = "https://git.uninsane.org/colin/abaddon/commit/eb551f188d34679f75adcbc83cb8d5beb4d19fd6.patch";
|
||||||
|
name = ''"view members" default to false'';
|
||||||
|
hash = "sha256-9BX8iO86CU1lNrKS1G2BjDR+3IlV9bmhRNTsLrxChwQ=";
|
||||||
|
})
|
||||||
|
(pkgs.fetchpatch {
|
||||||
|
# this makes it so Abaddon reports its app_name in notifications.
|
||||||
|
# not 100% necessary; just a nice-to-have. maybe don't rely on it until it's merged upstream.
|
||||||
|
# upstream PR: <https://github.com/uowuo/abaddon/pull/247>
|
||||||
|
url = "https://git.uninsane.org/colin/abaddon/commit/18cd863fdbb5e6b1e9aaf9394dbd673d51839f30.patch";
|
||||||
|
name = "set glib application name";
|
||||||
|
hash = "sha256-IFYxf1D8hIsxgZehGd6hL3zJiBkPZfWGm+Faaa5ZFl4=";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
suggestedPrograms = [ "gnome-keyring" ];
|
||||||
|
|
||||||
|
fs.".config/abaddon/abaddon.ini".symlink.text = ''
|
||||||
|
# see abaddon README.md for options.
|
||||||
|
# at time of writing:
|
||||||
|
# | Setting | Type | Default | Description |
|
||||||
|
# |[discord]------|---------|---------|--------------------------------------------------------------------------------------------------|
|
||||||
|
# | `gateway` | string | | override url for Discord gateway. must be json format and use zlib stream compression |
|
||||||
|
# | `api_base` | string | | override base url for Discord API |
|
||||||
|
# | `memory_db` | boolean | false | if true, Discord data will be kept in memory as opposed to on disk |
|
||||||
|
# | `token` | string | | Discord token used to login, this can be set from the menu |
|
||||||
|
# | `prefetch` | boolean | false | if true, new messages will cause the avatar and image attachments to be automatically downloaded |
|
||||||
|
# | `autoconnect` | boolean | false | autoconnect to discord |
|
||||||
|
# |[http]--------|--------|---------|---------------------------------------------------------------------------------------------|
|
||||||
|
# | `user_agent` | string | | sets the user-agent to use in HTTP requests to the Discord API (not including media/images) |
|
||||||
|
# | `concurrent` | int | 20 | how many images can be concurrently retrieved |
|
||||||
|
# |[gui}------------------------|---------|---------|----------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
# | `member_list_discriminator` | boolean | true | show user discriminators in the member list |
|
||||||
|
# | `stock_emojis` | boolean | true | allow abaddon to substitute unicode emojis with images from emojis.bin, must be false to allow GTK to render emojis itself |
|
||||||
|
# | `custom_emojis` | boolean | true | download and use custom Discord emojis |
|
||||||
|
# | `css` | string | | path to the main CSS file |
|
||||||
|
# | `animations` | boolean | true | use animated images where available (e.g. server icons, emojis, avatars). false means static images will be used |
|
||||||
|
# | `animated_guild_hover_only` | boolean | true | only animate guild icons when the guild is being hovered over |
|
||||||
|
# | `owner_crown` | boolean | true | show a crown next to the owner |
|
||||||
|
# | `unreads` | boolean | true | show unread indicators and mention badges |
|
||||||
|
# | `save_state` | boolean | true | save the state of the gui (active channels, tabs, expanded channels) |
|
||||||
|
# | `alt_menu` | boolean | false | keep the menu hidden unless revealed with alt key |
|
||||||
|
# | `hide_to_tray` | boolean | false | hide abaddon to the system tray on window close |
|
||||||
|
# | `show_deleted_indicator` | boolean | true | show \[deleted\] indicator next to deleted messages instead of actually deleting the message |
|
||||||
|
# | `font_scale` | double | | scale font rendering. 1 is unchanged |
|
||||||
|
# |[style]------------------|--------|-----------------------------------------------------|
|
||||||
|
# | `linkcolor` | string | color to use for links in messages |
|
||||||
|
# | `expandercolor` | string | color to use for the expander in the channel list |
|
||||||
|
# | `nsfwchannelcolor` | string | color to use for NSFW channels in the channel list |
|
||||||
|
# | `channelcolor` | string | color to use for SFW channels in the channel list |
|
||||||
|
# | `mentionbadgecolor` | string | background color for mention badges |
|
||||||
|
# | `mentionbadgetextcolor` | string | color to use for number displayed on mention badges |
|
||||||
|
# | `unreadcolor` | string | color to use for the unread indicator |
|
||||||
|
# |[notifications]|---------|--------------------------|-------------------------------------------------------------------------------|
|
||||||
|
# | `enabled` | boolean | true (if not on Windows) | Enable desktop notifications |
|
||||||
|
# | `playsound` | boolean | true | Enable notification sounds. Requires ENABLE_NOTIFICATION_SOUNDS=TRUE in CMake |
|
||||||
|
# |[voice]--|--------|------------------------------------|------------------------------------------------------------|
|
||||||
|
# | `vad` | string | rnnoise if enabled, gate otherwise | Method used for voice activity detection. Changeable in UI |
|
||||||
|
# |[windows]|---------|---------|-------------------------|
|
||||||
|
# | `hideconsole` | boolean | true | Hide console on startup |
|
||||||
|
|
||||||
|
# N.B.: abaddon writes this file itself (and even when i don't change anything internally).
|
||||||
|
# it prefers no spaces around the equal sign.
|
||||||
|
[discord]
|
||||||
|
autoconnect=true
|
||||||
|
|
||||||
|
[notifications]
|
||||||
|
# playsound: i manage sounds via swaync
|
||||||
|
playsound=false
|
||||||
|
'';
|
||||||
|
|
||||||
|
persist.byStore.private = [
|
||||||
|
".cache/abaddon"
|
||||||
|
];
|
||||||
|
|
||||||
|
services.abaddon = {
|
||||||
|
description = "unofficial Discord chat client";
|
||||||
|
wantedBy = lib.mkIf cfg.config.autostart [ "default.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = "${cfg.package}/bin/abaddon";
|
||||||
|
Type = "simple";
|
||||||
|
Restart = "always";
|
||||||
|
RestartSec = "20s";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
10
hosts/common/programs/animatch.nix
Normal file
10
hosts/common/programs/animatch.nix
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.programs.animatch = {
|
||||||
|
persist.byStore.plaintext = [
|
||||||
|
# game progress
|
||||||
|
".config/Holy Pangolin/Animatch"
|
||||||
|
".local/share/Holy Pangolin/Animatch" # i think this one might be wrong
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
@@ -20,6 +20,7 @@ in
|
|||||||
"sane-scripts.bt-show"
|
"sane-scripts.bt-show"
|
||||||
];
|
];
|
||||||
"sane-scripts.dev" = declPackageSet [
|
"sane-scripts.dev" = declPackageSet [
|
||||||
|
"sane-scripts.clone"
|
||||||
"sane-scripts.dev-cargo-loop"
|
"sane-scripts.dev-cargo-loop"
|
||||||
"sane-scripts.git-init"
|
"sane-scripts.git-init"
|
||||||
];
|
];
|
||||||
@@ -41,7 +42,6 @@ in
|
|||||||
"sane-scripts.secrets-unlock"
|
"sane-scripts.secrets-unlock"
|
||||||
"sane-scripts.secrets-update-keys"
|
"sane-scripts.secrets-update-keys"
|
||||||
"sane-scripts.shutdown"
|
"sane-scripts.shutdown"
|
||||||
"sane-scripts.ssl-dump"
|
|
||||||
"sane-scripts.sudo-redirect"
|
"sane-scripts.sudo-redirect"
|
||||||
"sane-scripts.sync-from-servo"
|
"sane-scripts.sync-from-servo"
|
||||||
"sane-scripts.vpn"
|
"sane-scripts.vpn"
|
||||||
@@ -109,6 +109,7 @@ in
|
|||||||
"util-linux" # lsblk, lscpu, etc
|
"util-linux" # lsblk, lscpu, etc
|
||||||
"wget"
|
"wget"
|
||||||
"wirelesstools" # iwlist
|
"wirelesstools" # iwlist
|
||||||
|
"xq" # jq for XML
|
||||||
];
|
];
|
||||||
sysadminExtraUtils = declPackageSet [
|
sysadminExtraUtils = declPackageSet [
|
||||||
"backblaze-b2"
|
"backblaze-b2"
|
||||||
@@ -172,7 +173,7 @@ in
|
|||||||
"zsh"
|
"zsh"
|
||||||
];
|
];
|
||||||
|
|
||||||
desktopConsoleUtils = declPackageSet [
|
pcConsoleUtils = declPackageSet [
|
||||||
"gh" # MS GitHub cli
|
"gh" # MS GitHub cli
|
||||||
"nix-index"
|
"nix-index"
|
||||||
"nixpkgs-review"
|
"nixpkgs-review"
|
||||||
@@ -187,11 +188,11 @@ in
|
|||||||
"yt-dlp"
|
"yt-dlp"
|
||||||
];
|
];
|
||||||
|
|
||||||
tuiApps = declPackageSet [
|
pcTuiApps = declPackageSet [
|
||||||
"aerc" # email client
|
"aerc" # email client
|
||||||
"msmtp" # sendmail
|
"msmtp" # sendmail
|
||||||
"offlineimap" # email mailbox sync
|
"offlineimap" # email mailbox sync
|
||||||
"sfeed" # RSS fetcher
|
# "sfeed" # RSS fetcher
|
||||||
"visidata" # TUI spreadsheet viewer/editor
|
"visidata" # TUI spreadsheet viewer/editor
|
||||||
"w3m" # web browser
|
"w3m" # web browser
|
||||||
];
|
];
|
||||||
@@ -221,6 +222,8 @@ in
|
|||||||
# creds, but also 200 MB of node modules, etc
|
# creds, but also 200 MB of node modules, etc
|
||||||
discord.persist.byStore.private = [ ".config/discord" ];
|
discord.persist.byStore.private = [ ".config/discord" ];
|
||||||
|
|
||||||
|
endless-sky.persist.byStore.plaintext = [ ".local/share/endless-sky" ];
|
||||||
|
|
||||||
# `emote` will show a first-run dialog based on what's in this directory.
|
# `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.
|
# 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.
|
# TODO: package [smile](https://github.com/mijorus/smile) for probably a better mobile experience.
|
||||||
@@ -237,6 +240,8 @@ in
|
|||||||
# TODO: we can populate gh's stuff statically; it even lets us use the same oauth across machines
|
# TODO: we can populate gh's stuff statically; it even lets us use the same oauth across machines
|
||||||
gh.persist.byStore.private = [ ".config/gh" ];
|
gh.persist.byStore.private = [ ".config/gh" ];
|
||||||
|
|
||||||
|
gnome-2048.persist.byStore.plaintext = [ ".local/share/gnome-2048/scores" ];
|
||||||
|
|
||||||
"gnome.gnome-maps".persist.byStore.plaintext = [ ".cache/shumate" ];
|
"gnome.gnome-maps".persist.byStore.plaintext = [ ".cache/shumate" ];
|
||||||
"gnome.gnome-maps".persist.byStore.private = [ ".local/share/maps-places.json" ];
|
"gnome.gnome-maps".persist.byStore.private = [ ".local/share/maps-places.json" ];
|
||||||
|
|
||||||
@@ -253,16 +258,21 @@ in
|
|||||||
requests
|
requests
|
||||||
]);
|
]);
|
||||||
|
|
||||||
# creds, media
|
shattered-pixel-dungeon.persist.byStore.plaintext = [ ".local/share/.shatteredpixel/shattered-pixel-dungeon" ];
|
||||||
signal-desktop.persist.byStore.private = [ ".config/Signal" ];
|
|
||||||
|
|
||||||
# printer/filament settings
|
# printer/filament settings
|
||||||
slic3r.persist.byStore.plaintext = [ ".Slic3r" ];
|
slic3r.persist.byStore.plaintext = [ ".Slic3r" ];
|
||||||
|
|
||||||
|
space-cadet-pinball.persist.byStore.plaintext = [ ".local/share/SpaceCadetPinball" ];
|
||||||
|
|
||||||
|
superTux.persist.byStore.plaintext = [ ".local/share/supertux2" ];
|
||||||
|
|
||||||
tdesktop.persist.byStore.private = [ ".local/share/TelegramDesktop" ];
|
tdesktop.persist.byStore.private = [ ".local/share/TelegramDesktop" ];
|
||||||
|
|
||||||
tokodon.persist.byStore.private = [ ".cache/KDE/tokodon" ];
|
tokodon.persist.byStore.private = [ ".cache/KDE/tokodon" ];
|
||||||
|
|
||||||
|
vvvvvv.persist.byStore.plaintext = [ ".local/share/VVVVVV" ];
|
||||||
|
|
||||||
whalebird.persist.byStore.private = [ ".config/Whalebird" ];
|
whalebird.persist.byStore.private = [ ".config/Whalebird" ];
|
||||||
|
|
||||||
yarn.persist.byStore.plaintext = [ ".cache/yarn" ];
|
yarn.persist.byStore.plaintext = [ ".cache/yarn" ];
|
||||||
|
@@ -1,14 +1,34 @@
|
|||||||
#!/usr/bin/env nix-shell
|
#!/usr/bin/env nix-shell
|
||||||
#!nix-shell -i bash
|
#!nix-shell -i bash
|
||||||
|
|
||||||
full=$(cat /sys/class/power_supply/axp20x-battery/charge_full_design)
|
|
||||||
rate=$(cat /sys/class/power_supply/axp20x-battery/current_now)
|
|
||||||
perc=$(cat /sys/class/power_supply/axp20x-battery/capacity)
|
|
||||||
perc_left=$((100 - $perc))
|
|
||||||
# these icons come from sxmo; they only render in nerdfonts
|
# these icons come from sxmo; they only render in nerdfonts
|
||||||
bat_dis=""
|
bat_dis=""
|
||||||
bat_chg=""
|
bat_chg=""
|
||||||
|
|
||||||
|
try_path() {
|
||||||
|
# returns:
|
||||||
|
# - perc, perc_left (0-100)
|
||||||
|
# - full, rate (pos means charging)
|
||||||
|
if [ -f "$1/capacity" ]; then
|
||||||
|
perc=$(cat "$1/capacity")
|
||||||
|
perc_left=$((100 - $perc))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$1/charge_full_design" ] && [ -f "$1/current_now" ]; then
|
||||||
|
# current is positive when charging
|
||||||
|
full=$(cat "$1/charge_full_design")
|
||||||
|
rate=$(cat "$1/current_now")
|
||||||
|
fi
|
||||||
|
if [ -f "$1/energy_full" ] && [ -f "$1/energy_now" ]; then
|
||||||
|
# energy is positive when discharging
|
||||||
|
full=$(cat "$1/energy_full")
|
||||||
|
rate=-$(cat "$1/energy_now")
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
try_path "/sys/class/power_supply/axp20x-battery" # Pinephone
|
||||||
|
try_path "/sys/class/power_supply/BAT0" # Thinkpad
|
||||||
|
|
||||||
fmt_minutes() {
|
fmt_minutes() {
|
||||||
# args: <battery symbol> <text if ludicrous estimate> <estimated minutes to full/empty>
|
# args: <battery symbol> <text if ludicrous estimate> <estimated minutes to full/empty>
|
||||||
if [[ $3 -gt 1440 ]]; then
|
if [[ $3 -gt 1440 ]]; then
|
||||||
@@ -27,6 +47,6 @@ if [[ $rate -lt 0 ]]; then
|
|||||||
elif [[ $rate -gt 0 ]]; then
|
elif [[ $rate -gt 0 ]]; then
|
||||||
# charging
|
# charging
|
||||||
fmt_minutes "$bat_chg" '100%' "$(($full * 60 * $perc_left / (100 * $rate)))"
|
fmt_minutes "$bat_chg" '100%' "$(($full * 60 * $perc_left / (100 * $rate)))"
|
||||||
else
|
elif [[ "$perc" != "" ]]; then
|
||||||
echo "$bat_dis $perc%"
|
echo "$bat_dis $perc%"
|
||||||
fi
|
fi
|
||||||
|
@@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
./abaddon.nix
|
||||||
./aerc.nix
|
./aerc.nix
|
||||||
./alacritty.nix
|
./alacritty.nix
|
||||||
|
./animatch.nix
|
||||||
./assorted.nix
|
./assorted.nix
|
||||||
./bemenu.nix
|
./bemenu.nix
|
||||||
./brave.nix
|
./brave.nix
|
||||||
@@ -12,6 +14,7 @@
|
|||||||
./chatty.nix
|
./chatty.nix
|
||||||
./conky
|
./conky
|
||||||
./cozy.nix
|
./cozy.nix
|
||||||
|
./dialect.nix
|
||||||
./dino.nix
|
./dino.nix
|
||||||
./element-desktop.nix
|
./element-desktop.nix
|
||||||
./epiphany.nix
|
./epiphany.nix
|
||||||
@@ -31,6 +34,7 @@
|
|||||||
./gnome-weather.nix
|
./gnome-weather.nix
|
||||||
./gpodder.nix
|
./gpodder.nix
|
||||||
./gthumb.nix
|
./gthumb.nix
|
||||||
|
./gtkcord4.nix
|
||||||
./helix.nix
|
./helix.nix
|
||||||
./imagemagick.nix
|
./imagemagick.nix
|
||||||
./jellyfin-media-player.nix
|
./jellyfin-media-player.nix
|
||||||
@@ -55,16 +59,22 @@
|
|||||||
./rhythmbox.nix
|
./rhythmbox.nix
|
||||||
./ripgrep.nix
|
./ripgrep.nix
|
||||||
./sfeed.nix
|
./sfeed.nix
|
||||||
|
./signal-desktop.nix
|
||||||
./splatmoji.nix
|
./splatmoji.nix
|
||||||
|
./spot.nix
|
||||||
./spotify.nix
|
./spotify.nix
|
||||||
./steam.nix
|
./steam.nix
|
||||||
./stepmania.nix
|
./stepmania.nix
|
||||||
./sublime-music.nix
|
./sublime-music.nix
|
||||||
|
./supertuxkart.nix
|
||||||
|
./sway-autoscaler
|
||||||
./swaynotificationcenter.nix
|
./swaynotificationcenter.nix
|
||||||
./tangram.nix
|
./tangram.nix
|
||||||
./tor-browser-bundle-bin.nix
|
./tor-browser-bundle-bin.nix
|
||||||
./tuba.nix
|
./tuba.nix
|
||||||
./vlc.nix
|
./vlc.nix
|
||||||
|
./wike.nix
|
||||||
|
./wine.nix
|
||||||
./wireshark.nix
|
./wireshark.nix
|
||||||
./xarchiver.nix
|
./xarchiver.nix
|
||||||
./zeal.nix
|
./zeal.nix
|
||||||
|
13
hosts/common/programs/dialect.nix
Normal file
13
hosts/common/programs/dialect.nix
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.programs.dialect = {
|
||||||
|
package = pkgs.dialect.overrideAttrs (upstream: {
|
||||||
|
# TODO: send upstream
|
||||||
|
# TODO: figure out how to get audio working
|
||||||
|
# TODO: move to runtimeDependencies?
|
||||||
|
buildInputs = upstream.buildInputs ++ [
|
||||||
|
pkgs.glib-networking # for TLS
|
||||||
|
];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
@@ -48,7 +48,7 @@ in
|
|||||||
persist.byStore.private = [ ".local/share/dino" ];
|
persist.byStore.private = [ ".local/share/dino" ];
|
||||||
|
|
||||||
services.dino = {
|
services.dino = {
|
||||||
description = "auto-start and maintain dino XMPP connection";
|
description = "dino XMPP client";
|
||||||
wantedBy = lib.mkIf cfg.config.autostart [ "default.target" ];
|
wantedBy = lib.mkIf cfg.config.autostart [ "default.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${cfg.package}/bin/dino";
|
ExecStart = "${cfg.package}/bin/dino";
|
||||||
|
@@ -4,9 +4,14 @@
|
|||||||
# - <https://github.com/vector-im/element-desktop/issues/1029#issuecomment-1632688224>
|
# - <https://github.com/vector-im/element-desktop/issues/1029#issuecomment-1632688224>
|
||||||
# - `rm -rf ~/.config/Element/GPUCache`
|
# - `rm -rf ~/.config/Element/GPUCache`
|
||||||
# - <https://github.com/NixOS/nixpkgs/issues/244486>
|
# - <https://github.com/NixOS/nixpkgs/issues/244486>
|
||||||
{ ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
sane.programs.element-desktop = {
|
sane.programs.element-desktop = {
|
||||||
|
package = pkgs.element-desktop.override {
|
||||||
|
# use pre-build electron because otherwise it takes 4 hrs to build from source.
|
||||||
|
electron = pkgs.electron-bin;
|
||||||
|
};
|
||||||
|
|
||||||
# creds/session keys, etc
|
# creds/session keys, etc
|
||||||
persist.byStore.private = [ ".config/Element" ];
|
persist.byStore.private = [ ".config/Element" ];
|
||||||
|
|
||||||
|
@@ -13,7 +13,14 @@ let
|
|||||||
mobile-prefs = lib.optionals false pkgs.librewolf-pmos-mobile.extraPrefsFiles;
|
mobile-prefs = lib.optionals false pkgs.librewolf-pmos-mobile.extraPrefsFiles;
|
||||||
# allow easy switching between firefox and librewolf with `defaultSettings`, below
|
# allow easy switching between firefox and librewolf with `defaultSettings`, below
|
||||||
librewolfSettings = {
|
librewolfSettings = {
|
||||||
browser = pkgs.librewolf-unwrapped;
|
browser = pkgs.librewolf-unwrapped.overrideAttrs (upstream: {
|
||||||
|
# TEMP(2023/11/21): fix eval bug in wrapFirefox
|
||||||
|
# see: <https://github.com/NixOS/nixpkgs/pull/244591>
|
||||||
|
passthru = upstream.passthru // {
|
||||||
|
requireSigning = false;
|
||||||
|
allowAddonSideload = true;
|
||||||
|
};
|
||||||
|
});
|
||||||
extraPrefsFiles = pkgs.librewolf-unwrapped.extraPrefsFiles ++ mobile-prefs;
|
extraPrefsFiles = pkgs.librewolf-unwrapped.extraPrefsFiles ++ mobile-prefs;
|
||||||
libName = "librewolf";
|
libName = "librewolf";
|
||||||
dotDir = ".librewolf";
|
dotDir = ".librewolf";
|
||||||
@@ -229,7 +236,8 @@ in
|
|||||||
// scrollbar configuration, see: <https://artemis.sh/2023/10/12/scrollbars.html>
|
// scrollbar configuration, see: <https://artemis.sh/2023/10/12/scrollbars.html>
|
||||||
// style=4 gives rectangular scrollbars
|
// style=4 gives rectangular scrollbars
|
||||||
// could also enable "always show scrollbars" in about:preferences -- not sure what the actual pref name for that is
|
// 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);
|
// note that too-large scrollbars (like 50px wide) tend to obscure content (and make buttons unclickable)
|
||||||
|
defaultPref("widget.non-native-theme.scrollbar.size.override", 20);
|
||||||
defaultPref("widget.non-native-theme.scrollbar.style", 4);
|
defaultPref("widget.non-native-theme.scrollbar.style", 4);
|
||||||
'';
|
'';
|
||||||
fs."${cfg.browser.dotDir}/default".dir = {};
|
fs."${cfg.browser.dotDir}/default".dir = {};
|
||||||
|
@@ -41,6 +41,7 @@ in
|
|||||||
# XXX by default fractal stores its state in ~/.local/share/<build-profile>/<UUID>.
|
# XXX by default fractal stores its state in ~/.local/share/<build-profile>/<UUID>.
|
||||||
".local/share/hack" # for debug-like builds
|
".local/share/hack" # for debug-like builds
|
||||||
".local/share/stable" # for normal releases
|
".local/share/stable" # for normal releases
|
||||||
|
".local/share/fractal" # for version 5+, i think?
|
||||||
];
|
];
|
||||||
|
|
||||||
suggestedPrograms = [ "gnome-keyring" ];
|
suggestedPrograms = [ "gnome-keyring" ];
|
||||||
|
@@ -3,9 +3,23 @@
|
|||||||
# - it uses webkitgtk_4_1, which is expensive to build.
|
# - it uses webkitgtk_4_1, which is expensive to build.
|
||||||
# could be upgraded to webkitgtk latest if upgraded to gtk4
|
# could be upgraded to webkitgtk latest if upgraded to gtk4
|
||||||
# <https://gitlab.gnome.org/GNOME/geary/-/issues/1212>
|
# <https://gitlab.gnome.org/GNOME/geary/-/issues/1212>
|
||||||
{ ... }:
|
{ config, lib, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs."gnome.geary";
|
||||||
|
in
|
||||||
{
|
{
|
||||||
sane.programs."gnome.geary" = {
|
sane.programs."gnome.geary" = {
|
||||||
|
configOption = with lib; mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.submodule {
|
||||||
|
options.autostart = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
slowToBuild = true; # uses webkitgtk 4.1
|
||||||
persist.byStore.private = [
|
persist.byStore.private = [
|
||||||
# attachments, and email -- contained in a sqlite db
|
# attachments, and email -- contained in a sqlite db
|
||||||
".local/share/geary"
|
".local/share/geary"
|
||||||
@@ -51,5 +65,18 @@
|
|||||||
transport_security=transport
|
transport_security=transport
|
||||||
credentials=use-incoming
|
credentials=use-incoming
|
||||||
'';
|
'';
|
||||||
|
secrets.".config/geary/account_02/geary.ini" = ../../../secrets/common/geary_account_02.ini.bin;
|
||||||
|
|
||||||
|
services.geary = {
|
||||||
|
description = "Geary email client";
|
||||||
|
wantedBy = lib.mkIf cfg.config.autostart [ "default.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = "${cfg.package}/bin/geary";
|
||||||
|
Type = "simple";
|
||||||
|
Restart = "always";
|
||||||
|
RestartSec = "20s";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
33
hosts/common/programs/gtkcord4.nix
Normal file
33
hosts/common/programs/gtkcord4.nix
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs.gtkcord4;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.gtkcord4 = {
|
||||||
|
configOption = with lib; mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.submodule {
|
||||||
|
options.autostart = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
persist.byStore.private = [
|
||||||
|
".cache/gtkcord4"
|
||||||
|
".config/gtkcord4" # empty?
|
||||||
|
];
|
||||||
|
|
||||||
|
services.gtkcord4 = {
|
||||||
|
description = "unofficial Discord chat client";
|
||||||
|
wantedBy = lib.mkIf cfg.config.autostart [ "default.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = "${cfg.package}/bin/gtkcord4";
|
||||||
|
Type = "simple";
|
||||||
|
Restart = "always";
|
||||||
|
RestartSec = "20s";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@@ -6,6 +6,8 @@
|
|||||||
# package = pkgs.libreoffice-still;
|
# package = pkgs.libreoffice-still;
|
||||||
package = pkgs.libreoffice-fresh;
|
package = pkgs.libreoffice-fresh;
|
||||||
|
|
||||||
|
slowToBuild = true;
|
||||||
|
|
||||||
# disable first-run stuff
|
# disable first-run stuff
|
||||||
fs.".config/libreoffice/4/user/registrymodifications.xcu".symlink.text = ''
|
fs.".config/libreoffice/4/user/registrymodifications.xcu".symlink.text = ''
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
@@ -117,6 +117,7 @@ in
|
|||||||
mime.priority = 50; # default = 100; 50 in order to take precedence over vlc.
|
mime.priority = 50; # default = 100; 50 in order to take precedence over vlc.
|
||||||
mime.associations."audio/flac" = "mpv.desktop";
|
mime.associations."audio/flac" = "mpv.desktop";
|
||||||
mime.associations."audio/mpeg" = "mpv.desktop";
|
mime.associations."audio/mpeg" = "mpv.desktop";
|
||||||
|
mime.associations."audio/x-opus+ogg" = "mpv.desktop";
|
||||||
mime.associations."audio/x-vorbis+ogg" = "mpv.desktop";
|
mime.associations."audio/x-vorbis+ogg" = "mpv.desktop";
|
||||||
mime.associations."video/mp4" = "mpv.desktop";
|
mime.associations."video/mp4" = "mpv.desktop";
|
||||||
mime.associations."video/quicktime" = "mpv.desktop";
|
mime.associations."video/quicktime" = "mpv.desktop";
|
||||||
|
@@ -85,27 +85,13 @@ let
|
|||||||
plugin-config-lua = concatMapStrings (p: optionalString (p.type or "" == "lua") p.config) plugins;
|
plugin-config-lua = concatMapStrings (p: optionalString (p.type or "" == "lua") p.config) plugins;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# private because there could be sensitive things in the swap
|
|
||||||
sane.programs.neovim = {
|
sane.programs.neovim = {
|
||||||
persist.byStore.private = [ ".cache/vim-swap" ];
|
# package = config.programs.neovim.finalPackage;
|
||||||
env.EDITOR = "vim";
|
package = pkgs.wrapNeovimUnstable pkgs.neovim-unwrapped (pkgs.neovimUtils.makeNeovimConfig {
|
||||||
# git claims it should use EDITOR, but it doesn't!
|
withRuby = false; #< doesn't cross-compile w/o binfmt
|
||||||
env.GIT_EDITOR = "vim";
|
viAlias = true;
|
||||||
mime.priority = 200; # default=100 => yield to other, more specialized applications
|
vimAlias = true;
|
||||||
mime.associations."application/schema+json" = "nvim.desktop";
|
plugins = plugin-packages;
|
||||||
mime.associations."plain/text" = "nvim.desktop";
|
|
||||||
mime.associations."text/markdown" = "nvim.desktop";
|
|
||||||
};
|
|
||||||
|
|
||||||
programs.neovim = mkIf config.sane.programs.neovim.enabled {
|
|
||||||
# neovim: https://github.com/neovim/neovim
|
|
||||||
enable = true;
|
|
||||||
viAlias = true;
|
|
||||||
vimAlias = true;
|
|
||||||
configure = {
|
|
||||||
packages.plugins = {
|
|
||||||
start = plugin-packages;
|
|
||||||
};
|
|
||||||
customRC = ''
|
customRC = ''
|
||||||
" let the terminal handle mouse events, that way i get OS-level ctrl+shift+c/etc
|
" let the terminal handle mouse events, that way i get OS-level ctrl+shift+c/etc
|
||||||
" this used to be default, until <https://github.com/neovim/neovim/pull/19290>
|
" this used to be default, until <https://github.com/neovim/neovim/pull/19290>
|
||||||
@@ -147,6 +133,16 @@ in
|
|||||||
${plugin-config-lua}
|
${plugin-config-lua}
|
||||||
EOF
|
EOF
|
||||||
'';
|
'';
|
||||||
};
|
});
|
||||||
|
|
||||||
|
# private because there could be sensitive things in the swap
|
||||||
|
persist.byStore.private = [ ".cache/vim-swap" ];
|
||||||
|
env.EDITOR = "vim";
|
||||||
|
# git claims it should use EDITOR, but it doesn't!
|
||||||
|
env.GIT_EDITOR = "vim";
|
||||||
|
mime.priority = 200; # default=100 => yield to other, more specialized applications
|
||||||
|
mime.associations."application/schema+json" = "nvim.desktop";
|
||||||
|
mime.associations."plain/text" = "nvim.desktop";
|
||||||
|
mime.associations."text/markdown" = "nvim.desktop";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
35
hosts/common/programs/signal-desktop.nix
Normal file
35
hosts/common/programs/signal-desktop.nix
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs.signal-desktop;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.signal-desktop = {
|
||||||
|
configOption = with lib; mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.submodule {
|
||||||
|
options.autostart = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
package = pkgs.signal-desktop-from-src;
|
||||||
|
|
||||||
|
# creds, media
|
||||||
|
persist.byStore.private = [
|
||||||
|
".config/Signal"
|
||||||
|
];
|
||||||
|
|
||||||
|
services.signal-desktop = {
|
||||||
|
description = "Signal Messenger";
|
||||||
|
wantedBy = lib.mkIf cfg.config.autostart [ "default.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = "${cfg.package}/bin/signal-desktop";
|
||||||
|
Type = "simple";
|
||||||
|
Restart = "always";
|
||||||
|
RestartSec = "20s";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
11
hosts/common/programs/spot.nix
Normal file
11
hosts/common/programs/spot.nix
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.programs.spot = {
|
||||||
|
secrets.".cache/spot/librespot/credentials/credentials.json" = ../../../secrets/common/spot_credentials.json.bin;
|
||||||
|
persist.byStore.plaintext = [
|
||||||
|
".cache/spot/img" # album art
|
||||||
|
".cache/spot/librespot/audio" # audio/track cache
|
||||||
|
".cache/spot/net" # album metadata
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
10
hosts/common/programs/supertuxkart.nix
Normal file
10
hosts/common/programs/supertuxkart.nix
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.programs.superTuxKart = {
|
||||||
|
persist.byStore.plaintext = [
|
||||||
|
".cache/supertuxkart"
|
||||||
|
".config/supertuxkart"
|
||||||
|
".local/share/supertuxkart"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
44
hosts/common/programs/sway-autoscaler/default.nix
Normal file
44
hosts/common/programs/sway-autoscaler/default.nix
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.programs.sway-autoscaler;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.programs.sway-autoscaler = {
|
||||||
|
configOption = with lib; mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.submodule {
|
||||||
|
options.autostart = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
options.defaultScale = mkOption {
|
||||||
|
type = types.number;
|
||||||
|
default = 1;
|
||||||
|
};
|
||||||
|
options.interval = mkOption {
|
||||||
|
type = types.number;
|
||||||
|
default = 5;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
package = pkgs.static-nix-shell.mkBash {
|
||||||
|
pname = "sway-autoscaler";
|
||||||
|
pkgs = [ "jq" "sway" "util-linux" ];
|
||||||
|
src = ./.;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.sway-autoscaler = {
|
||||||
|
description = "adjust global desktop scale to match the activate application";
|
||||||
|
wantedBy = lib.mkIf cfg.config.autostart [ "default.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = "${cfg.package}/bin/sway-autoscaler --loop-sec ${builtins.toString cfg.config.interval}";
|
||||||
|
Type = "simple";
|
||||||
|
Restart = "always";
|
||||||
|
RestartSec = "10s";
|
||||||
|
};
|
||||||
|
environment.SWAY_DEFAULT_SCALE = builtins.toString cfg.config.defaultScale;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
87
hosts/common/programs/sway-autoscaler/sway-autoscaler
Executable file
87
hosts/common/programs/sway-autoscaler/sway-autoscaler
Executable file
@@ -0,0 +1,87 @@
|
|||||||
|
#!/usr/bin/env nix-shell
|
||||||
|
#!nix-shell -i bash -p jq -p sway -p util-linux
|
||||||
|
|
||||||
|
help() {
|
||||||
|
echo "queries the focused window and apply an appropriate display-wide scale."
|
||||||
|
echo "this should be considered a temporary workaround until more apps support small displays."
|
||||||
|
echo ""
|
||||||
|
echo "args:"
|
||||||
|
echo " -v | --verbose"
|
||||||
|
echo " --loop-sec N: re-compute the scale every N seconds. else, run once and exit."
|
||||||
|
echo ""
|
||||||
|
echo "environment variables:"
|
||||||
|
echo " SWAY_DEFAULT_SCALE=N: scale to apply when no known window is selected."
|
||||||
|
# TODO: could use map-style environment variables to allow external per-app config
|
||||||
|
# - SWAY_SCALE_org.gnome.Maps=1 ; ...
|
||||||
|
}
|
||||||
|
|
||||||
|
options=$(getopt -l h,loop-sec:,verbose -o h,v -- "" "${@}")
|
||||||
|
eval "set -- ${options}"
|
||||||
|
|
||||||
|
verbose=false
|
||||||
|
loop=false
|
||||||
|
loop_sec=
|
||||||
|
while true; do
|
||||||
|
case "$1" in
|
||||||
|
(-h|--help)
|
||||||
|
shift
|
||||||
|
help
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
(--loop-sec)
|
||||||
|
shift
|
||||||
|
loop=true
|
||||||
|
loop_sec="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
(-v|--verbose)
|
||||||
|
shift
|
||||||
|
verbose=true
|
||||||
|
;;
|
||||||
|
(--)
|
||||||
|
shift
|
||||||
|
if [ $# -eq 1 ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
echo "invalid arguments: '$1'"
|
||||||
|
echo ""
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
autoscale() {
|
||||||
|
focused=$(swaymsg -t get_tree | jq --raw-output '.. | select(.type?) | select(.focused==true) | .app_id')
|
||||||
|
$verbose && echo "focused: '$focused'"
|
||||||
|
|
||||||
|
scale=${SWAY_DEFAULT_SCALE:-1}
|
||||||
|
case "$focused" in
|
||||||
|
(org.gnome.Maps)
|
||||||
|
# scale=1.6: 3 turns visible at once in landscape
|
||||||
|
# scale=1.25: max scale at which no text/menuitems are cutoff in vertical mode
|
||||||
|
# 5 turns visible at once in landscape
|
||||||
|
# scale=1.2: max of 6 turns visible at once in landscape
|
||||||
|
# scale=1.1: max of 7 turns visible at once in landscape
|
||||||
|
# scale=1: max of 8 turns visible at once in landscape
|
||||||
|
#
|
||||||
|
# as scale is increased past 1.1, vertical mode becomes substantially less usable
|
||||||
|
# as scale is decreased past 1.3, the whole desktop UI becomes less usable (keyboard, workspaces)
|
||||||
|
scale=1.2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
$verbose && echo "scaling to $scale"
|
||||||
|
swaymsg -q -- output '*' scale "$scale"
|
||||||
|
}
|
||||||
|
|
||||||
|
if $loop; then
|
||||||
|
while true; do
|
||||||
|
autoscale
|
||||||
|
sleep "$loop_sec"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
autoscale
|
||||||
|
fi
|
@@ -116,8 +116,15 @@ in
|
|||||||
package = pkgs.rmDbusServices (pkgs.swaynotificationcenter.overrideAttrs (upstream: {
|
package = pkgs.rmDbusServices (pkgs.swaynotificationcenter.overrideAttrs (upstream: {
|
||||||
# allow toggle buttons:
|
# allow toggle buttons:
|
||||||
patches = (upstream.patches or []) ++ [
|
patches = (upstream.patches or []) ++ [
|
||||||
|
# (pkgs.fetchpatch {
|
||||||
|
# url = "https://github.com/ErikReider/SwayNotificationCenter/pull/304.patch";
|
||||||
|
# name = "Add toggle button";
|
||||||
|
# hash = "sha256-bove2EXc5FZ5nN1X1FYOn3czCgHG03ibIAupJNoctiM=";
|
||||||
|
# })
|
||||||
(pkgs.fetchpatch {
|
(pkgs.fetchpatch {
|
||||||
url = "https://github.com/ErikReider/SwayNotificationCenter/pull/304.patch";
|
# import of <https://github.com/ErikReider/SwayNotificationCenter/pull/304>
|
||||||
|
# as of 2023/11/08 the upstream patch has merge conflicts AND runtime issues (see wip-swaync-update nixos branch)
|
||||||
|
url = "https://git.uninsane.org/colin/SwayNotificationCenter/commit/d9a0d938b88cbee65cfaef887af77a5a23d5fe89.patch";
|
||||||
name = "Add toggle button";
|
name = "Add toggle button";
|
||||||
hash = "sha256-bove2EXc5FZ5nN1X1FYOn3czCgHG03ibIAupJNoctiM=";
|
hash = "sha256-bove2EXc5FZ5nN1X1FYOn3czCgHG03ibIAupJNoctiM=";
|
||||||
})
|
})
|
||||||
@@ -145,11 +152,14 @@ in
|
|||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
.widget-buttons-grid>flowbox>flowboxchild>button.toggle {
|
||||||
/* text color for inactive buttons, and "Clear All" button.*/
|
/* text color for inactive buttons, and "Clear All" button.*/
|
||||||
color: rgb(172, 172, 172);
|
color: rgb(172, 172, 172);
|
||||||
|
/* padding defaults to 16px; tighten, so i can squish it all onto one row */
|
||||||
|
padding-left: 0px;
|
||||||
|
padding-right: 0px;
|
||||||
}
|
}
|
||||||
button.active {
|
.widget-buttons-grid>flowbox>flowboxchild>button.toggle.active {
|
||||||
color: rgb(255, 255, 255);
|
color: rgb(255, 255, 255);
|
||||||
background-color: rgb(0, 110, 190);
|
background-color: rgb(0, 110, 190);
|
||||||
}
|
}
|
||||||
@@ -208,12 +218,18 @@ in
|
|||||||
# - SWAYNC_REPLACES_ID
|
# - SWAYNC_REPLACES_ID
|
||||||
# - SWAYNC_ID
|
# - SWAYNC_ID
|
||||||
# - SWAYNC_SUMMARY
|
# - SWAYNC_SUMMARY
|
||||||
incoming-im = {
|
incoming-im-known-app-name = {
|
||||||
# trigger notification sound on behalf of these IM clients.
|
# trigger notification sound on behalf of these IM clients.
|
||||||
app-name = "(Chats|Dino|discord|Element|Fractal)";
|
app-name = "(Chats|Dino|discord|Element|Fractal|gtkcord4)";
|
||||||
body = "^(?!Incoming call).*$"; #< don't match Dino Incoming calls
|
body = "^(?!Incoming call).*$"; #< don't match Dino Incoming calls
|
||||||
exec = "${fbcli} --event proxied-message-new-instant";
|
exec = "${fbcli} --event proxied-message-new-instant";
|
||||||
};
|
};
|
||||||
|
incoming-im-known-desktop-entry = {
|
||||||
|
# trigger notification sound on behalf of these IM clients.
|
||||||
|
# these clients don't have an app-name (listed as "<unknown>"), but do have a desktop-entry
|
||||||
|
desktop-entry = "com.github.uowuo.abaddon";
|
||||||
|
exec = "${fbcli} --event proxied-message-new-instant";
|
||||||
|
};
|
||||||
incoming-call = {
|
incoming-call = {
|
||||||
app-name = "Dino";
|
app-name = "Dino";
|
||||||
body = "^Incoming call$";
|
body = "^Incoming call$";
|
||||||
@@ -318,22 +334,22 @@ in
|
|||||||
lib.optionals config.sane.programs.eg25-control.enabled [
|
lib.optionals config.sane.programs.eg25-control.enabled [
|
||||||
{
|
{
|
||||||
type = "toggle";
|
type = "toggle";
|
||||||
label = "gps";
|
label = ""; # GPS services; other icons: gps, ⌖, 🛰, 🌎,
|
||||||
command = "/run/wrappers/bin/sudo ${systemctl-toggle}/bin/systemctl-toggle eg25-control-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";
|
active = "${pkgs.systemd}/bin/systemctl is-active eg25-control-gps.service";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
type = "toggle";
|
type = "toggle";
|
||||||
label = "5g";
|
label = ""; # icons: 5g, 📡, 📱, ᯤ, ⚡, , 🌐, 📶, 🗼, , , ,
|
||||||
# modem and NetworkManager auto-establishes a connection when powered.
|
# modem and NetworkManager auto-establishes a connection when powered.
|
||||||
# though some things like `wg-home` VPN tunnel will remain routed over the old interface.
|
# 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";
|
command = "/run/wrappers/bin/sudo ${systemctl-toggle}/bin/systemctl-toggle eg25-control-powered";
|
||||||
active = "${pkgs.systemd}/bin/systemctl is-active eg25-control-powered.service";
|
active = "${pkgs.systemd}/bin/systemctl is-active eg25-control-powered.service";
|
||||||
}
|
}
|
||||||
] ++ [
|
] ++ lib.optionals false [
|
||||||
{
|
{
|
||||||
type = "toggle";
|
type = "toggle";
|
||||||
label = "vpn::hn";
|
label = "vpn::hn"; # route all traffic through servo; useful to debug moby's networking
|
||||||
command = "/run/wrappers/bin/sudo ${systemctl-toggle}/bin/systemctl-toggle wg-quick-vpn-servo";
|
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";
|
active = "${pkgs.systemd}/bin/systemctl is-active wg-quick-vpn-servo.service";
|
||||||
}
|
}
|
||||||
@@ -344,6 +360,35 @@ in
|
|||||||
command = "${systemctl-toggle}/bin/systemctl-toggle --user gnome-calls";
|
command = "${systemctl-toggle}/bin/systemctl-toggle --user gnome-calls";
|
||||||
active = "${pkgs.systemd}/bin/systemctl is-active --user gnome-calls";
|
active = "${pkgs.systemd}/bin/systemctl is-active --user gnome-calls";
|
||||||
}
|
}
|
||||||
|
] ++ lib.optionals config.sane.programs."gnome.geary".enabled [
|
||||||
|
{
|
||||||
|
type = "toggle";
|
||||||
|
label = ""; # email (Geary); other icons: ✉, [E], 📧,
|
||||||
|
command = "${systemctl-toggle}/bin/systemctl-toggle --user geary";
|
||||||
|
active = "${pkgs.systemd}/bin/systemctl is-active --user geary";
|
||||||
|
}
|
||||||
|
] ++ lib.optionals config.sane.programs.abaddon.enabled [
|
||||||
|
{
|
||||||
|
type = "toggle";
|
||||||
|
label = ""; # Discord chat client; icons: , 🎮
|
||||||
|
command = "${systemctl-toggle}/bin/systemctl-toggle --user abaddon";
|
||||||
|
active = "${pkgs.systemd}/bin/systemctl is-active --user abaddon";
|
||||||
|
}
|
||||||
|
# ] ++ lib.optionals config.sane.programs.gtkcord4.enabled [
|
||||||
|
# # XXX: disabled in favor of abaddon: gtkcord4 leaks memory
|
||||||
|
# {
|
||||||
|
# type = "toggle";
|
||||||
|
# label = ""; # Discord chat client; icons: , 🎮
|
||||||
|
# command = "${systemctl-toggle}/bin/systemctl-toggle --user gtkcord4";
|
||||||
|
# active = "${pkgs.systemd}/bin/systemctl is-active --user gtkcord4";
|
||||||
|
# }
|
||||||
|
] ++ lib.optionals config.sane.programs.signal-desktop.enabled [
|
||||||
|
{
|
||||||
|
type = "toggle";
|
||||||
|
label = "💬"; # Signal messenger; other icons:
|
||||||
|
command = "${systemctl-toggle}/bin/systemctl-toggle --user signal-desktop";
|
||||||
|
active = "${pkgs.systemd}/bin/systemctl is-active --user signal-desktop";
|
||||||
|
}
|
||||||
] ++ lib.optionals config.sane.programs.dino.enabled [
|
] ++ lib.optionals config.sane.programs.dino.enabled [
|
||||||
{
|
{
|
||||||
type = "toggle";
|
type = "toggle";
|
||||||
|
@@ -27,6 +27,8 @@ in
|
|||||||
'' + (upstream.preFixup or "");
|
'' + (upstream.preFixup or "");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
slowToBuild = true; # only true for cross-compiled tangram
|
||||||
|
|
||||||
persist.byStore.private = [
|
persist.byStore.private = [
|
||||||
".cache/Tangram"
|
".cache/Tangram"
|
||||||
".local/share/Tangram"
|
".local/share/Tangram"
|
||||||
|
@@ -1,26 +1,6 @@
|
|||||||
{ pkgs, ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
sane.programs.tuba = {
|
sane.programs.tuba = {
|
||||||
package = pkgs.tuba.overrideAttrs (upstream: {
|
|
||||||
postInstall = (upstream.postInstall or "") + ''
|
|
||||||
# ship a `tuba` alias to the actual tuba binary, since i can never remember its name
|
|
||||||
ln -s $out/bin/dev.geopjr.Tuba $out/bin/tuba
|
|
||||||
'';
|
|
||||||
|
|
||||||
preFixup = (upstream.preFixup or "") + ''
|
|
||||||
# 2023/09/24: fix so i can upload media when creating a post.
|
|
||||||
# see: <https://github.com/GeopJr/Tuba/issues/414#issuecomment-1732695845>
|
|
||||||
gappsWrapperArgs+=(
|
|
||||||
--prefix GDK_DEBUG , no-portals
|
|
||||||
)
|
|
||||||
'';
|
|
||||||
# alternative to disabling portals is to remove the filters on FileDialogs.
|
|
||||||
# done like so (but would want to apply to the other dialogs too)
|
|
||||||
# postPatch = (upstream.postPatch or "") + ''
|
|
||||||
# substituteInPlace src/Dialogs/ProfileEdit.vala \
|
|
||||||
# --replace "default_filter = filter" ""
|
|
||||||
# '';
|
|
||||||
});
|
|
||||||
suggestedPrograms = [ "gnome-keyring" ];
|
suggestedPrograms = [ "gnome-keyring" ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
18
hosts/common/programs/wike.nix
Normal file
18
hosts/common/programs/wike.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.programs.wike = {
|
||||||
|
# wike probably meant to put everything here in a subdir, but didn't.
|
||||||
|
persist.byStore.cryptClearOnBoot = [
|
||||||
|
".cache/webkitgtk"
|
||||||
|
".local/share/webkitgtk"
|
||||||
|
];
|
||||||
|
persist.byStore.private = [
|
||||||
|
".local/share/historic.json" # history
|
||||||
|
# .local/share/cookies (probably not necessary to persist?)
|
||||||
|
|
||||||
|
# .local/share/booklists.json (empty; not sure if wike's)
|
||||||
|
# .local/share/bookmarks.json (empty; not sure if wike's)
|
||||||
|
# .local/share/languages.json (not sure if wike's)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
11
hosts/common/programs/wine.nix
Normal file
11
hosts/common/programs/wine.nix
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
sane.programs.wine = {
|
||||||
|
# no need for the cryptographic nature, just needs to not use loads of / tmpfs.
|
||||||
|
persist.byStore.cryptClearOnBoot = [ ".wine" ];
|
||||||
|
persist.byStore.plaintext = [
|
||||||
|
# Power Bomberman: <https://www.bombermanboard.com/viewtopic.php?t=1925>
|
||||||
|
".wine/drive_c/users/colin/AppData/pb"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
@@ -1,4 +1,6 @@
|
|||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
{
|
{
|
||||||
|
sane.programs.wireshark.slowToBuild = true;
|
||||||
|
|
||||||
programs.wireshark.enable = config.sane.programs.wireshark.enabled;
|
programs.wireshark.enable = config.sane.programs.wireshark.enabled;
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,7 @@ in {
|
|||||||
sane.programs.zeal = {
|
sane.programs.zeal = {
|
||||||
# package = pkgs.zeal-qt6; #< TODO: upgrade system to qt6 versions of everything (i.e. jellyfin-media-player, nheko)
|
# package = pkgs.zeal-qt6; #< TODO: upgrade system to qt6 versions of everything (i.e. jellyfin-media-player, nheko)
|
||||||
package = pkgs.zeal-qt5;
|
package = pkgs.zeal-qt5;
|
||||||
|
slowToBuild = true;
|
||||||
persist.byStore.plaintext = [
|
persist.byStore.plaintext = [
|
||||||
".cache/Zeal"
|
".cache/Zeal"
|
||||||
".local/share/Zeal"
|
".local/share/Zeal"
|
||||||
|
@@ -67,6 +67,8 @@ in
|
|||||||
'' + ''
|
'' + ''
|
||||||
|
|
||||||
HISTFILE="$HOME/.local/share/zsh/history"
|
HISTFILE="$HOME/.local/share/zsh/history"
|
||||||
|
HISTSIZE=1000000
|
||||||
|
SAVEHIST=1000000
|
||||||
|
|
||||||
# auto-cd into any of these dirs by typing them and pressing 'enter':
|
# auto-cd into any of these dirs by typing them and pressing 'enter':
|
||||||
hash -d 3rd="/home/colin/dev/3rd"
|
hash -d 3rd="/home/colin/dev/3rd"
|
||||||
@@ -105,18 +107,19 @@ in
|
|||||||
# common typos
|
# common typos
|
||||||
"cd.." = "cd ..";
|
"cd.." = "cd ..";
|
||||||
"cd../" = "cd ../";
|
"cd../" = "cd ../";
|
||||||
# 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`
|
# ls helpers (eza is a nicer `ls`
|
||||||
"l" = "eza --oneline"; # show one entry per line
|
"l" = "eza --oneline"; # show one entry per line
|
||||||
"ll" = "eza --long --time-style=long-iso";
|
"ll" = "eza --long --time-style=long-iso";
|
||||||
|
# overcome poor defaults
|
||||||
|
"lsof" = "lsof -P"; #< lsof: use port *numbers*, not names
|
||||||
|
"tcpdump" = "tcpdump -n"; #< tcpdump: use port *numbers*, not names
|
||||||
};
|
};
|
||||||
setOptions = [
|
setOptions = [
|
||||||
# docs: `man zshoptions`
|
# docs: `man zshoptions`
|
||||||
# nixos defaults:
|
# nixos defaults:
|
||||||
"HIST_FCNTL_LOCK"
|
"HIST_FCNTL_LOCK"
|
||||||
"HIST_IGNORE_DUPS"
|
"HIST_IGNORE_DUPS"
|
||||||
|
"HIST_EXPIRE_DUPS_FIRST"
|
||||||
"SHARE_HISTORY"
|
"SHARE_HISTORY"
|
||||||
# customizations:
|
# customizations:
|
||||||
"AUTO_CD" # type directory name to go there
|
"AUTO_CD" # type directory name to go there
|
||||||
@@ -148,6 +151,11 @@ in
|
|||||||
pushd "$1";
|
pushd "$1";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function repo() {
|
||||||
|
# navigate to a local checkout of the source code for repo (i.e. package) $1
|
||||||
|
eval $(sane-clone "$1")
|
||||||
|
};
|
||||||
|
|
||||||
function switch() {
|
function switch() {
|
||||||
sudo nixos-rebuild --flake . switch --keep-going;
|
sudo nixos-rebuild --flake . switch --keep-going;
|
||||||
}
|
}
|
||||||
|
@@ -1,45 +1,25 @@
|
|||||||
{ config, lib, sane-data, sane-lib, ... }:
|
{ config, lib, sane-lib, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (builtins) attrValues head map mapAttrs tail;
|
keysForHost = hostName: let
|
||||||
|
hostCfg = config.sane.hosts.by-name."${hostName}";
|
||||||
|
in {
|
||||||
|
"root@${hostName}" = hostCfg.ssh.host_pubkey;
|
||||||
|
"colin@${hostName}" = lib.mkIf (hostCfg.ssh.user_pubkey != null && hostCfg.ssh.authorized) hostCfg.ssh.user_pubkey;
|
||||||
|
};
|
||||||
|
hostKeys = builtins.map keysForHost (builtins.attrNames config.sane.hosts.by-name);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
sane.ssh.pubkeys =
|
sane.ssh.pubkeys = lib.mkMerge (hostKeys ++ [
|
||||||
let
|
{
|
||||||
# path is a DNS-style path like [ "org" "uninsane" "root" ]
|
"root@uninsane.org" = config.sane.hosts.by-name.servo.ssh.host_pubkey;
|
||||||
keyNameForPath = path:
|
"root@git.uninsane.org" = config.sane.hosts.by-name.servo.ssh.host_pubkey;
|
||||||
let
|
|
||||||
rev = lib.reverseList path;
|
|
||||||
name = head rev;
|
|
||||||
host = lib.concatStringsSep "." (tail rev);
|
|
||||||
in
|
|
||||||
"${name}@${host}";
|
|
||||||
|
|
||||||
# [{ path :: [String], value :: String }] for the keys we want to install
|
# documented here: <https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints>
|
||||||
globalKeys = sane-lib.flattenAttrs sane-data.keys;
|
# Github actually uses multiple keys -- one per format
|
||||||
|
"root@github.com" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl";
|
||||||
keysForHost = hostCfg: sane-lib.mapToAttrs
|
}
|
||||||
(name: {
|
]);
|
||||||
inherit name;
|
|
||||||
value = {
|
|
||||||
root = hostCfg.ssh.host_pubkey;
|
|
||||||
} // (lib.optionalAttrs hostCfg.ssh.authorized {
|
|
||||||
colin = hostCfg.ssh.user_pubkey;
|
|
||||||
});
|
|
||||||
})
|
|
||||||
hostCfg.names
|
|
||||||
;
|
|
||||||
domainKeys = sane-lib.flattenAttrs (
|
|
||||||
sane-lib.joinAttrsets (
|
|
||||||
map keysForHost (builtins.attrValues config.sane.hosts.by-name)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
in lib.mkMerge (map
|
|
||||||
({ path, value }: {
|
|
||||||
"${keyNameForPath path}" = lib.mkIf (value != null) value;
|
|
||||||
})
|
|
||||||
(globalKeys ++ domainKeys)
|
|
||||||
);
|
|
||||||
|
|
||||||
services.openssh = {
|
services.openssh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@@ -6,8 +6,6 @@
|
|||||||
# sets group to "users" (?)
|
# sets group to "users" (?)
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
home = "/home/colin";
|
home = "/home/colin";
|
||||||
createHome = true;
|
|
||||||
homeMode = "0700";
|
|
||||||
# i don't get exactly what this is, but nixos defaults to this non-deterministically
|
# i don't get exactly what this is, but nixos defaults to this non-deterministically
|
||||||
# in /var/lib/nixos/auto-subuid-map and i don't want that.
|
# in /var/lib/nixos/auto-subuid-map and i don't want that.
|
||||||
subUidRanges = [
|
subUidRanges = [
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
{ ... }:
|
{ config, ... }:
|
||||||
{
|
{
|
||||||
sane.persist.sys.byStore.cryptClearOnBoot = [
|
sane.persist.sys.byStore.cryptClearOnBoot = [
|
||||||
# when running commands as root, some things may create ~/.cache entries.
|
# when running commands as root, some things may create ~/.cache entries.
|
||||||
|
@@ -4,7 +4,6 @@
|
|||||||
imports = [
|
imports = [
|
||||||
./derived-secrets
|
./derived-secrets
|
||||||
./gui
|
./gui
|
||||||
./hostnames.nix
|
|
||||||
./hosts.nix
|
./hosts.nix
|
||||||
./nixcache.nix
|
./nixcache.nix
|
||||||
./roles
|
./roles
|
||||||
|
@@ -1,4 +1,10 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
declPackageSet = pkgs: {
|
||||||
|
package = null;
|
||||||
|
suggestedPrograms = pkgs;
|
||||||
|
};
|
||||||
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./gnome.nix
|
./gnome.nix
|
||||||
@@ -10,74 +16,122 @@
|
|||||||
./theme
|
./theme
|
||||||
];
|
];
|
||||||
|
|
||||||
sane.programs.guiApps = {
|
sane.programs.gameApps = declPackageSet [
|
||||||
package = null;
|
"animatch"
|
||||||
suggestedPrograms = lib.optionals (pkgs.system == "x86_64-linux") [
|
"gnome-2048"
|
||||||
"x86GuiApps"
|
"gnome.hitori" # like sudoku
|
||||||
] ++ [
|
"superTux" # keyboard-only controls
|
||||||
# package sets
|
"superTuxKart" # poor FPS on pinephone
|
||||||
"tuiApps"
|
];
|
||||||
] ++ [
|
sane.programs.pcGameApps = declPackageSet [
|
||||||
"alacritty" # terminal emulator
|
# "andyetitmoves" # TODO: fix build!
|
||||||
"calls" # gnome calls (dialer/handler)
|
# "armagetronad" # tron/lightcycles; WAN and LAN multiplayer
|
||||||
# "celluloid" # mpv frontend
|
# "cutemaze" # meh: trivial maze game; qt6 and keyboard-only
|
||||||
"chatty" # matrix/xmpp/irc client
|
# "cuyo" # trivial puyo-puyo clone
|
||||||
"cozy" # audiobook player
|
"endless-sky" # space merchantilism/exploration
|
||||||
"dino" # XMPP client
|
# "factorio"
|
||||||
# "emote"
|
"frozen-bubble" # WAN + LAN + 1P/2P bubble bobble
|
||||||
"epiphany" # gnome's web browser
|
"hase" # WAN worms game
|
||||||
"evince" # works on phosh
|
# "hedgewars" # WAN + LAN worms game (5~10 people online at any moment; <https://hedgewars.org>)
|
||||||
"firefox"
|
# "libremines" # meh: trivial minesweeper; qt6
|
||||||
# "flare-signal" # gtk4 signal client
|
# "mario0" # SMB + portal
|
||||||
# "foliate" # e-book reader
|
# "mindustry"
|
||||||
"fractal" # matrix client
|
# "minesweep-rs" # CLI minesweeper
|
||||||
"g4music" # local music player
|
# "nethack"
|
||||||
# "gnome.cheese"
|
# "osu-lazer"
|
||||||
# "gnome-feeds" # RSS reader (with claimed mobile support)
|
# "pinball" # 3d pinball; kb/mouse. old sourceforge project
|
||||||
# "gnome.file-roller"
|
# "powermanga" # STYLISH space invaders derivative (keyboard-only)
|
||||||
"gnome.geary" # adaptive e-mail client
|
"shattered-pixel-dungeon" # doesn't cross compile
|
||||||
"gnome.gnome-maps"
|
"space-cadet-pinball" # LMB/RMB controls (bindable though. volume buttons?)
|
||||||
# "gnome-podcasts"
|
"tumiki-fighters" # keyboard-only
|
||||||
# "gnome.gnome-system-monitor"
|
"vvvvvv" # keyboard-only controls
|
||||||
# "gnome.gnome-terminal" # works on phosh
|
"wine"
|
||||||
"gnome.gnome-weather"
|
];
|
||||||
"gpodder"
|
|
||||||
"gthumb"
|
|
||||||
"komikku"
|
|
||||||
"koreader"
|
|
||||||
"lemoa" # lemmy app
|
|
||||||
# "lollypop"
|
|
||||||
"mate.engrampa" # archive manager
|
|
||||||
"mepo" # maps viewer
|
|
||||||
"mpv"
|
|
||||||
"networkmanagerapplet" # for nm-connection-editor: it's better than not having any gui!
|
|
||||||
"ntfy-sh" # notification service
|
|
||||||
# "newsflash"
|
|
||||||
"pavucontrol"
|
|
||||||
# "picard" # music tagging
|
|
||||||
# "libsForQt5.plasmatube" # Youtube player
|
|
||||||
"soundconverter"
|
|
||||||
# "sublime-music"
|
|
||||||
"tangram" # web browser
|
|
||||||
# "tdesktop" # broken on phosh
|
|
||||||
# "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
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.programs.desktopGuiApps = {
|
sane.programs.guiApps = declPackageSet [
|
||||||
package = null;
|
# package sets
|
||||||
suggestedPrograms = [
|
"gameApps"
|
||||||
|
"guiBaseApps"
|
||||||
|
];
|
||||||
|
|
||||||
|
sane.programs.guiBaseApps = declPackageSet [
|
||||||
|
"abaddon" # discord client
|
||||||
|
"alacritty" # terminal emulator
|
||||||
|
"dialect" # language translation
|
||||||
|
"dino" # XMPP client
|
||||||
|
# "emote"
|
||||||
|
"evince" # works on phosh
|
||||||
|
# "flare-signal" # gtk4 signal client
|
||||||
|
# "foliate" # e-book reader
|
||||||
|
"fractal" # matrix client
|
||||||
|
"g4music" # local music player
|
||||||
|
# "gnome.cheese"
|
||||||
|
# "gnome-feeds" # RSS reader (with claimed mobile support)
|
||||||
|
# "gnome.file-roller"
|
||||||
|
"gnome.geary" # adaptive e-mail client; uses webkitgtk 4.1
|
||||||
|
"gnome.gnome-calculator"
|
||||||
|
"gnome.gnome-calendar"
|
||||||
|
"gnome.gnome-clocks"
|
||||||
|
"gnome.gnome-maps"
|
||||||
|
# "gnome-podcasts"
|
||||||
|
# "gnome.gnome-system-monitor"
|
||||||
|
# "gnome.gnome-terminal" # works on phosh
|
||||||
|
"gnome.gnome-weather"
|
||||||
|
"gthumb"
|
||||||
|
# "gtkcord4" # Discord client. 2023/11/21: disabled because it leaks memory
|
||||||
|
"lemoa" # lemmy app
|
||||||
|
# "lollypop"
|
||||||
|
"mate.engrampa" # archive manager
|
||||||
|
"mepo" # maps viewer
|
||||||
|
"mpv"
|
||||||
|
"networkmanagerapplet" # for nm-connection-editor: it's better than not having any gui!
|
||||||
|
"ntfy-sh" # notification service
|
||||||
|
# "newsflash"
|
||||||
|
"pavucontrol"
|
||||||
|
# "picard" # music tagging
|
||||||
|
# "libsForQt5.plasmatube" # Youtube player
|
||||||
|
"signal-desktop"
|
||||||
|
"spot" # Gnome Spotfy client
|
||||||
|
# "sublime-music"
|
||||||
|
# "tdesktop" # broken on phosh
|
||||||
|
# "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
|
||||||
|
];
|
||||||
|
|
||||||
|
sane.programs.handheldGuiApps = declPackageSet [
|
||||||
|
"calls" # gnome calls (dialer/handler)
|
||||||
|
# "celluloid" # mpv frontend
|
||||||
|
"chatty" # matrix/xmpp/irc client
|
||||||
|
"cozy" # audiobook player
|
||||||
|
"epiphany" # gnome's web browser
|
||||||
|
"gpodder"
|
||||||
|
"komikku"
|
||||||
|
"koreader"
|
||||||
|
"megapixels" # camera app
|
||||||
|
"portfolio-filemanager"
|
||||||
|
"tangram" # web browser
|
||||||
|
"wike" # Wikipedia Reader
|
||||||
|
"xarchiver"
|
||||||
|
];
|
||||||
|
|
||||||
|
sane.programs.pcGuiApps = declPackageSet (
|
||||||
|
[
|
||||||
|
# package sets
|
||||||
|
"pcGameApps"
|
||||||
|
"pcTuiApps"
|
||||||
|
] ++ [
|
||||||
"audacity"
|
"audacity"
|
||||||
"blanket" # ambient noise generator
|
"blanket" # ambient noise generator
|
||||||
"brave" # for the integrated wallet -- as a backup
|
"brave" # for the integrated wallet -- as a backup
|
||||||
# "cantata" # music player (mpd frontend)
|
# "cantata" # music player (mpd frontend)
|
||||||
# "chromium" # chromium takes hours to build. brave is chromium-based, distributed in binary form, so prefer it.
|
# "chromium" # chromium takes hours to build. brave is chromium-based, distributed in binary form, so prefer it.
|
||||||
|
"discord" # x86-only
|
||||||
"electrum"
|
"electrum"
|
||||||
"element-desktop"
|
"element-desktop"
|
||||||
|
"firefox"
|
||||||
"font-manager"
|
"font-manager"
|
||||||
# "gajim" # XMPP client. cross build tries to import host gobject-introspection types (2023/09/01)
|
# "gajim" # XMPP client. cross build tries to import host gobject-introspection types (2023/09/01)
|
||||||
"gimp" # broken on phosh
|
"gimp" # broken on phosh
|
||||||
@@ -87,50 +141,29 @@
|
|||||||
"gnome.nautilus" # file browser
|
"gnome.nautilus" # file browser
|
||||||
# "gnome.totem" # video player, supposedly supports UPnP
|
# "gnome.totem" # video player, supposedly supports UPnP
|
||||||
"handbrake"
|
"handbrake"
|
||||||
"hase"
|
|
||||||
"inkscape"
|
"inkscape"
|
||||||
# "jellyfin-media-player"
|
# "jellyfin-media-player"
|
||||||
"kdenlive"
|
"kdenlive"
|
||||||
"kid3" # audio tagging
|
"kid3" # audio tagging
|
||||||
"krita"
|
"krita"
|
||||||
"libreoffice" # TODO: replace with an office suite that uses saner packaging?
|
"libreoffice" # TODO: replace with an office suite that uses saner packaging?
|
||||||
|
"losslesscut-bin" # x86-only
|
||||||
|
"makemkv" # x86-only
|
||||||
|
"monero-gui" # x86-only
|
||||||
"mumble"
|
"mumble"
|
||||||
"nheko"
|
# "nheko" # Matrix chat client
|
||||||
# "obsidian"
|
# "obsidian"
|
||||||
# "rhythmbox" # local music player
|
# "rhythmbox" # local music player
|
||||||
"slic3r"
|
"slic3r"
|
||||||
|
"soundconverter"
|
||||||
|
"spotify" # x86-only
|
||||||
"steam"
|
"steam"
|
||||||
|
"tor-browser-bundle-bin" # x86-only
|
||||||
"vlc"
|
"vlc"
|
||||||
"wireshark" # could maybe ship the cli as sysadmin pkg
|
"wireshark" # could maybe ship the cli as sysadmin pkg
|
||||||
];
|
"zecwallet-lite" # x86-only
|
||||||
};
|
]
|
||||||
|
);
|
||||||
sane.programs.handheldGuiApps = {
|
|
||||||
package = null;
|
|
||||||
suggestedPrograms = [
|
|
||||||
"megapixels" # camera app
|
|
||||||
"portfolio-filemanager"
|
|
||||||
"xarchiver"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.programs.x86GuiApps = {
|
|
||||||
package = null;
|
|
||||||
suggestedPrograms = [
|
|
||||||
"discord"
|
|
||||||
# "gnome.zenity" # for kaiteki (it will use qarma, kdialog, or zenity)
|
|
||||||
# "gpt2tc" # XXX: unreliable mirror
|
|
||||||
# "kaiteki" # Pleroma client
|
|
||||||
# "logseq" # Personal Knowledge Management
|
|
||||||
"losslesscut-bin"
|
|
||||||
"makemkv"
|
|
||||||
"monero-gui"
|
|
||||||
"signal-desktop"
|
|
||||||
"spotify"
|
|
||||||
"tor-browser-bundle-bin"
|
|
||||||
"zecwallet-lite"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
sane.persist.sys.byStore.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/alsa" # preserve output levels, default devices
|
||||||
|
@@ -15,5 +15,5 @@ https://bt.uninsane.org
|
|||||||
https://sci-hub.se
|
https://sci-hub.se
|
||||||
https://archive.is
|
https://archive.is
|
||||||
https://news.ycombinator.com
|
https://news.ycombinator.com
|
||||||
http://10.78.79.1 # router/firewall
|
http://10.78.79.1 # router/firewall
|
||||||
https://jochen-hoenicke.de/queue # johoe's mempool (bitcoin/ethereum)
|
https://jochen-hoenicke.de/queue # johoe's mempool (bitcoin/ethereum)
|
||||||
|
@@ -14,7 +14,7 @@ let
|
|||||||
echo "launching sway-session (sway.desktop)..." | ${systemd-cat} --identifier=sway-session
|
echo "launching sway-session (sway.desktop)..." | ${systemd-cat} --identifier=sway-session
|
||||||
sway 2>&1 | ${systemd-cat} --identifier=sway-session
|
sway 2>&1 | ${systemd-cat} --identifier=sway-session
|
||||||
'';
|
'';
|
||||||
origSway = (pkgs.sway.override {
|
origSway = pkgs.sway.override {
|
||||||
# this override is what `programs.nixos` would do internally if we left `package` unset.
|
# this override is what `programs.nixos` would do internally if we left `package` unset.
|
||||||
extraSessionCommands = scfg.extraSessionCommands;
|
extraSessionCommands = scfg.extraSessionCommands;
|
||||||
extraOptions = scfg.extraOptions;
|
extraOptions = scfg.extraOptions;
|
||||||
@@ -22,7 +22,7 @@ let
|
|||||||
withGtkWrapper = scfg.wrapperFeatures.gtk;
|
withGtkWrapper = scfg.wrapperFeatures.gtk;
|
||||||
isNixOS = true;
|
isNixOS = true;
|
||||||
# TODO: `enableXWayland = ...`?
|
# TODO: `enableXWayland = ...`?
|
||||||
});
|
};
|
||||||
desktop-file = pkgs.runCommand "sway-desktop-wrapper" {} ''
|
desktop-file = pkgs.runCommand "sway-desktop-wrapper" {} ''
|
||||||
mkdir -p $out/share/wayland-sessions
|
mkdir -p $out/share/wayland-sessions
|
||||||
substitute ${origSway}/share/wayland-sessions/sway.desktop $out/share/wayland-sessions/sway.desktop \
|
substitute ${origSway}/share/wayland-sessions/sway.desktop $out/share/wayland-sessions/sway.desktop \
|
||||||
@@ -112,7 +112,7 @@ in
|
|||||||
# TODO: split these into their own option scope
|
# TODO: split these into their own option scope
|
||||||
brightness_down_cmd = mkOption {
|
brightness_down_cmd = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "${pkgs.brightnessctl}/bin/brightnessctl set -2%";
|
default = "${pkgs.brightnessctl}/bin/brightnessctl set 2%-";
|
||||||
description = "command to run when use wants to decrease screen brightness";
|
description = "command to run when use wants to decrease screen brightness";
|
||||||
};
|
};
|
||||||
brightness_up_cmd = mkOption {
|
brightness_up_cmd = mkOption {
|
||||||
|
@@ -142,20 +142,30 @@ bar {
|
|||||||
for_window [app_id="pinentry-.*"] floating true
|
for_window [app_id="pinentry-.*"] floating true
|
||||||
for_window [app_id="foot" title=".*sxmo/modem/.*/draft.txt.*"] resize set height 25
|
for_window [app_id="foot" title=".*sxmo/modem/.*/draft.txt.*"] resize set height 25
|
||||||
for_window [title="megapixels"] inhibit_idle open
|
for_window [title="megapixels"] inhibit_idle open
|
||||||
# Dino (XMPP) is ordinarily started for the purpose of daemonizing (but still visible). keep it on a predictable, out-of-the-way workspace
|
|
||||||
# TODO: could be neat to somehow do this in a way that it never steals focus from anything...
|
# workspace assignments
|
||||||
|
# mostly, messengers belong on WS 1
|
||||||
for_window [app_id="im.dino.Dino"] move container to workspace number 1
|
for_window [app_id="im.dino.Dino"] move container to workspace number 1
|
||||||
for_window [app_id="org.gnome.Fractal"] move container to workspace number 1
|
for_window [app_id="org.gnome.Fractal"] move container to workspace number 1
|
||||||
|
for_window [app_id="geary"] move container to workspace number 1
|
||||||
|
for_window [class="Signal"] move container to workspace number 1
|
||||||
|
for_window [app_id="xyz.diamondb.gtkcord4"] move container to workspace number 1
|
||||||
|
for_window [app_id="abaddon"] move container to workspace number 1
|
||||||
|
|
||||||
### displays
|
### displays
|
||||||
## DESKTOP
|
## DESKTOP
|
||||||
output "Samsung Electric Company S22C300 0x00007F35" {
|
output "Goldstar Company Ltd LG ULTRAWIDE 0x00004E94" {
|
||||||
pos 0,0
|
pos 0,0
|
||||||
|
res 3440x1440
|
||||||
|
}
|
||||||
|
output "Samsung Electric Company S22C300 0x00007F35" {
|
||||||
|
pos 3440,0
|
||||||
res 1920x1080
|
res 1920x1080
|
||||||
}
|
}
|
||||||
output "Goldstar Company Ltd LG ULTRAWIDE 0x00004E94" {
|
# projector
|
||||||
pos 1920,0
|
output "MS Telematica TV 0x00000001" {
|
||||||
res 3440x1440
|
pos 5360,0
|
||||||
|
res 1920x1080
|
||||||
}
|
}
|
||||||
|
|
||||||
## LAPTOP
|
## LAPTOP
|
||||||
|
161
hosts/modules/gui/sxmo/bonsai.nix
Normal file
161
hosts/modules/gui/sxmo/bonsai.nix
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
# bonsai docs: <https://sr.ht/~stacyharper/bonsai/>
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.sane.gui.sxmo.bonsaid;
|
||||||
|
|
||||||
|
delayType = with lib; types.submodule {
|
||||||
|
options = {
|
||||||
|
type = mkOption {
|
||||||
|
type = types.enum [ "delay" ];
|
||||||
|
# default = "delay";
|
||||||
|
};
|
||||||
|
delay_duration = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
description = ''
|
||||||
|
used for "delay" types only.
|
||||||
|
nanoseconds until the event is finalized.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
transitions = mkOption {
|
||||||
|
type = types.listOf transitionType;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
list of transitions out of this state (i.e. after completing the delay).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
eventType = with lib; types.submodule {
|
||||||
|
options = {
|
||||||
|
type = mkOption {
|
||||||
|
type = types.enum [ "event" ];
|
||||||
|
# default = "event";
|
||||||
|
};
|
||||||
|
event_name = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
name of event which this transition applies to.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
transitions = mkOption {
|
||||||
|
type = types.listOf transitionType;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
list of transitions out of this state.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
execType = with lib; types.submodule {
|
||||||
|
options = {
|
||||||
|
type = mkOption {
|
||||||
|
type = types.enum [ "exec" ];
|
||||||
|
# default = "exec";
|
||||||
|
};
|
||||||
|
command = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
description = ''
|
||||||
|
command to run when the event is triggered.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
transitions = mkOption {
|
||||||
|
type = types.listOf transitionType;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
list of transitions out of this state (i.e. after successfully executing the command)
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
isDelay = x: delayType.check x && x.type == "delay";
|
||||||
|
isEvent = x: eventType.check x && x.type == "event";
|
||||||
|
isExec = x: execType.check x && x.type == "exec";
|
||||||
|
# unfortunately, `types.oneOf` is naive about submodules, so we need our own type.
|
||||||
|
# transitionType = lib.types.oneOf [ delayType eventType execType ];
|
||||||
|
transitionType = with lib.types; mkOptionType {
|
||||||
|
name = "transition";
|
||||||
|
check = x: isDelay x || isEvent x || isExec x;
|
||||||
|
merge = loc: defs: let
|
||||||
|
defList = builtins.map (d: d.value) defs;
|
||||||
|
in
|
||||||
|
if builtins.all isDelay defList then
|
||||||
|
delayType.merge loc defs
|
||||||
|
else if builtins.all isEvent defList then
|
||||||
|
eventType.merge loc defs
|
||||||
|
else if builtins.all isExec defList then
|
||||||
|
execType.merge loc defs
|
||||||
|
else
|
||||||
|
mergeOneOption loc defs
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
# transitionType = with lib; types.submodule {
|
||||||
|
# options = {
|
||||||
|
# type = mkOption {
|
||||||
|
# type = types.enum [ "delay" "event" "exec" ];
|
||||||
|
# };
|
||||||
|
# delay_duration = mkOption {
|
||||||
|
# type = types.nullOr types.int;
|
||||||
|
# default = null;
|
||||||
|
# description = ''
|
||||||
|
# used for "delay" types only.
|
||||||
|
# nanoseconds until the event is finalized.
|
||||||
|
# '';
|
||||||
|
# };
|
||||||
|
# event_name = mkOption {
|
||||||
|
# type = types.nullOr types.str;
|
||||||
|
# default = null;
|
||||||
|
# description = ''
|
||||||
|
# name of event which this transition applies to.
|
||||||
|
# '';
|
||||||
|
# };
|
||||||
|
# transitions = mkOption {
|
||||||
|
# type = types.nullOr (types.listOf transitionType);
|
||||||
|
# default = null;
|
||||||
|
# description = ''
|
||||||
|
# list of transitions out of this state.
|
||||||
|
# '';
|
||||||
|
# };
|
||||||
|
# command = mkOption {
|
||||||
|
# type = types.nullOr (types.listOf types.str);
|
||||||
|
# default = null;
|
||||||
|
# description = ''
|
||||||
|
# used for "exec" types only.
|
||||||
|
# command to run when the event is triggered.
|
||||||
|
# '';
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = with lib; {
|
||||||
|
sane.gui.sxmo.bonsaid.package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.bonsai;
|
||||||
|
};
|
||||||
|
sane.gui.sxmo.bonsaid.transitions = mkOption {
|
||||||
|
type = types.listOf transitionType;
|
||||||
|
default = [];
|
||||||
|
};
|
||||||
|
sane.gui.sxmo.bonsaid.configFile = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = pkgs.writeText "bonsai_tree.json" (builtins.toJSON cfg.transitions);
|
||||||
|
description = ''
|
||||||
|
configuration file to pass to bonsai.
|
||||||
|
usually auto-generated from the sibling options; exposed mainly for debugging or convenience.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = lib.mkIf config.sane.gui.sxmo.enable {
|
||||||
|
sane.user.services.bonsaid = {
|
||||||
|
description = "programmable input dispatcher";
|
||||||
|
script = ''
|
||||||
|
${pkgs.coreutils}/bin/rm -f $XDG_RUNTIME_DIR/bonsai
|
||||||
|
exec ${cfg.package}/bin/bonsaid -t ${cfg.configFile}
|
||||||
|
'';
|
||||||
|
serviceConfig.Type = "simple";
|
||||||
|
serviceConfig.Restart = "always";
|
||||||
|
serviceConfig.RestartSec = "5s";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@@ -28,10 +28,10 @@
|
|||||||
# - startup
|
# - startup
|
||||||
# - daemon based (lisgsd, idle_locker, statusbar_periodics)
|
# - daemon based (lisgsd, idle_locker, statusbar_periodics)
|
||||||
# - auto-started at login
|
# - auto-started at login
|
||||||
# - managable by `sxmo_daemons.sh`
|
# - managable by `sxmo_jobs.sh`
|
||||||
# - list available daemons: `sxmo_daemons.sh list`
|
# - list available daemons: `sxmo_jobs.sh list`
|
||||||
# - query if a daemon is active: `sxmo_daemons.sh running <my-daemon>`
|
# - query if a daemon is active: `sxmo_jobs.sh running <my-daemon>`
|
||||||
# - start daemon: `sxmo_daemons.sh start <my-daemon>`
|
# - start daemon: `sxmo_jobs.sh start <my-daemon>`
|
||||||
# - managable by `superctl`
|
# - managable by `superctl`
|
||||||
# - `superctl status`
|
# - `superctl status`
|
||||||
# - user hooks:
|
# - user hooks:
|
||||||
@@ -70,7 +70,7 @@ let
|
|||||||
hookPkgs = {
|
hookPkgs = {
|
||||||
inputhandler = pkgs.static-nix-shell.mkBash {
|
inputhandler = pkgs.static-nix-shell.mkBash {
|
||||||
pname = "sxmo_hook_inputhandler.sh";
|
pname = "sxmo_hook_inputhandler.sh";
|
||||||
pkgs = [ "coreutils" ];
|
pkgs = [ "coreutils" "playerctl" "pulseaudio" ];
|
||||||
src = ./hooks;
|
src = ./hooks;
|
||||||
};
|
};
|
||||||
postwake = pkgs.static-nix-shell.mkBash {
|
postwake = pkgs.static-nix-shell.mkBash {
|
||||||
@@ -130,7 +130,7 @@ in
|
|||||||
};
|
};
|
||||||
sane.gui.sxmo.package = mkOption {
|
sane.gui.sxmo.package = mkOption {
|
||||||
type = types.package;
|
type = types.package;
|
||||||
default = pkgs.sxmo-utils-latest.override { preferSystemd = true; };
|
default = pkgs.sxmo-utils.override { preferSystemd = true; };
|
||||||
description = ''
|
description = ''
|
||||||
sxmo base scripts and hooks collection.
|
sxmo base scripts and hooks collection.
|
||||||
consider overriding the outputs under /share/sxmo/default_hooks
|
consider overriding the outputs under /share/sxmo/default_hooks
|
||||||
@@ -234,6 +234,9 @@ in
|
|||||||
SXMO_DISABLE_CONFIGVERSION_CHECK = mkSettingsOpt "1" "allow omitting the configversion line from user-provided sxmo dotfiles";
|
SXMO_DISABLE_CONFIGVERSION_CHECK = mkSettingsOpt "1" "allow omitting the configversion line from user-provided sxmo dotfiles";
|
||||||
SXMO_UNLOCK_IDLE_TIME = mkSettingsOpt "300" "how many seconds of inactivity before locking the screen"; # lock -> screenoff happens 8s later, not configurable
|
SXMO_UNLOCK_IDLE_TIME = mkSettingsOpt "300" "how many seconds of inactivity before locking the screen"; # lock -> screenoff happens 8s later, not configurable
|
||||||
# SXMO_WM = mkSettingsOpt "sway" "sway or dwm. ordinarily initialized by sxmo_{x,w}init.sh";
|
# SXMO_WM = mkSettingsOpt "sway" "sway or dwm. ordinarily initialized by sxmo_{x,w}init.sh";
|
||||||
|
SXMO_NO_AUDIO = mkSettingsOpt "1" "don't start pipewire/pulseaudio in sxmo_hook_start.sh";
|
||||||
|
SXMO_STATES = mkSettingsOpt "unlock screenoff" "list of states the device should support (unlock, lock, screenoff)";
|
||||||
|
SXMO_SWAY_SCALE = mkSettingsOpt "1" "sway output scale";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
default = {};
|
default = {};
|
||||||
@@ -250,6 +253,10 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
imports = [
|
||||||
|
./bonsai.nix
|
||||||
|
];
|
||||||
|
|
||||||
config = lib.mkMerge [
|
config = lib.mkMerge [
|
||||||
{
|
{
|
||||||
sane.programs.sxmoApps = {
|
sane.programs.sxmoApps = {
|
||||||
@@ -259,11 +266,14 @@ in
|
|||||||
"bemenu" # specifically to import its theming
|
"bemenu" # specifically to import its theming
|
||||||
"sfeed" # want this here so that the user's ~/.sfeed/sfeedrc gets created
|
"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
|
||||||
|
# "sway-autoscaler"
|
||||||
];
|
];
|
||||||
|
|
||||||
persist.byStore.cryptClearOnBoot = [
|
persist.byStore.cryptClearOnBoot = [
|
||||||
# builds to be 10's of MB per day
|
# builds to be 10's of MB per day
|
||||||
# ".local/state/superd/logs"
|
# ".local/state/superd/logs"
|
||||||
|
".local/share/sxmo/modem" # SMS
|
||||||
|
".local/share/sxmo/notifications" # so i can see new SMS messages. not sure actually if this needs persisting or if it'll re-hydrate from modem.
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -297,7 +307,7 @@ in
|
|||||||
# these could be added, but i don't see much benefit.
|
# these could be added, but i don't see much benefit.
|
||||||
font = "pango:monospace 10";
|
font = "pango:monospace 10";
|
||||||
mod = "Mod1"; # prefer Alt
|
mod = "Mod1"; # prefer Alt
|
||||||
xwayland = false; # disable to reduce RAM usage.
|
# xwayland = false; # disable to reduce RAM usage. N.B.: xwayland is needed for electron apps!
|
||||||
workspace_layout = "tabbed";
|
workspace_layout = "tabbed";
|
||||||
|
|
||||||
brightness_down_cmd = "sxmo_brightness.sh down";
|
brightness_down_cmd = "sxmo_brightness.sh down";
|
||||||
@@ -343,7 +353,7 @@ in
|
|||||||
|
|
||||||
# kill anything leftover from the previous sxmo run. this way we can (try to) be reentrant
|
# kill anything leftover from the previous sxmo run. this way we can (try to) be reentrant
|
||||||
echo "sxmo_init: killing stale daemons (if active)"
|
echo "sxmo_init: killing stale daemons (if active)"
|
||||||
sxmo_daemons.sh stop all
|
sxmo_jobs.sh stop all
|
||||||
pkill bemenu
|
pkill bemenu
|
||||||
pkill wvkbd
|
pkill wvkbd
|
||||||
pkill superd
|
pkill superd
|
||||||
@@ -376,6 +386,8 @@ in
|
|||||||
|
|
||||||
sane.programs.sxmoApps.enableFor.user.colin = true;
|
sane.programs.sxmoApps.enableFor.user.colin = true;
|
||||||
|
|
||||||
|
sane.programs.sway-autoscaler.config.defaultScale = builtins.fromJSON cfg.settings.SXMO_SWAY_SCALE;
|
||||||
|
|
||||||
# sxmo internally uses doas instead of sudo
|
# sxmo internally uses doas instead of sudo
|
||||||
security.doas.enable = true;
|
security.doas.enable = true;
|
||||||
security.doas.wheelNeedsPassword = false;
|
security.doas.wheelNeedsPassword = false;
|
||||||
@@ -403,6 +415,81 @@ in
|
|||||||
cfg.settings
|
cfg.settings
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
sane.gui.sxmo.bonsaid.transitions = let
|
||||||
|
doExec = inputName: transitions: {
|
||||||
|
type = "exec";
|
||||||
|
command = [
|
||||||
|
"setsid"
|
||||||
|
"-f"
|
||||||
|
"sxmo_hook_inputhandler.sh"
|
||||||
|
inputName
|
||||||
|
];
|
||||||
|
inherit transitions;
|
||||||
|
};
|
||||||
|
onDelay = ms: transitions: {
|
||||||
|
type = "delay";
|
||||||
|
delay_duration = ms * 1000000;
|
||||||
|
inherit transitions;
|
||||||
|
};
|
||||||
|
onEvent = eventName: transitions: {
|
||||||
|
type = "event";
|
||||||
|
event_name = eventName;
|
||||||
|
inherit transitions;
|
||||||
|
};
|
||||||
|
friendlyToBonsai = { timeout ? null, trigger ? null, power_pressed ? {}, power_released ? {}, voldown_pressed ? {}, voldown_released ? {}, volup_pressed ? {}, volup_released ? {} }@args:
|
||||||
|
if trigger != null then [
|
||||||
|
(doExec trigger (friendlyToBonsai (builtins.removeAttrs args ["trigger"])))
|
||||||
|
] else [
|
||||||
|
(lib.mkIf (timeout != null) (onDelay (timeout.ms or 400) (friendlyToBonsai (builtins.removeAttrs timeout ["ms"]))))
|
||||||
|
(lib.mkIf (power_pressed != {}) (onEvent "power_pressed" (friendlyToBonsai power_pressed)))
|
||||||
|
(lib.mkIf (power_released != {}) (onEvent "power_released" (friendlyToBonsai power_released)))
|
||||||
|
(lib.mkIf (voldown_pressed != {}) (onEvent "voldown_pressed" (friendlyToBonsai voldown_pressed)))
|
||||||
|
(lib.mkIf (voldown_released != {}) (onEvent "voldown_released" (friendlyToBonsai voldown_released)))
|
||||||
|
(lib.mkIf (volup_pressed != {}) (onEvent "volup_pressed" (friendlyToBonsai volup_pressed)))
|
||||||
|
(lib.mkIf (volup_released != {}) (onEvent "volup_released" (friendlyToBonsai volup_released)))
|
||||||
|
];
|
||||||
|
recurseVolUpDown = ttl: if ttl == 0 then {
|
||||||
|
} else {
|
||||||
|
voldown_pressed = {
|
||||||
|
trigger = "powerhold_voldown";
|
||||||
|
timeout.ms = 1000;
|
||||||
|
power_released = {};
|
||||||
|
} // recurseVolUpDown (ttl - 1);
|
||||||
|
|
||||||
|
volup_pressed = {
|
||||||
|
trigger = "powerhold_volup";
|
||||||
|
timeout.ms = 1000;
|
||||||
|
power_released = {};
|
||||||
|
} // recurseVolUpDown (ttl - 1);
|
||||||
|
};
|
||||||
|
in friendlyToBonsai {
|
||||||
|
# map sequences of "events" to an argument to pass to sxmo_hook_inputhandler.sh
|
||||||
|
|
||||||
|
# tap the power button N times to trigger N different actions
|
||||||
|
power_pressed.timeout.ms = 1200; # press w/o release. this is a long timeout because it's tied to the "kill window" action.
|
||||||
|
power_pressed.timeout.trigger = "powerhold";
|
||||||
|
power_pressed.power_released.timeout.trigger = "powerbutton_one";
|
||||||
|
power_pressed.power_released.timeout.ms = 600; # long timeout to make `powertoggle_*` easier
|
||||||
|
power_pressed.power_released.power_pressed.trigger = "powerbutton_two";
|
||||||
|
|
||||||
|
# power_pressed.power_released.power_released.timeout.trigger = "powerbutton_two";
|
||||||
|
# power_pressed.power_released.power_released.power_released.trigger = "powerbutton_three";
|
||||||
|
|
||||||
|
# tap power, then tap up/down after releasing it
|
||||||
|
power_pressed.power_released.voldown_pressed.trigger = "powertoggle_voldown";
|
||||||
|
power_pressed.power_released.volup_pressed.trigger = "powertoggle_volup";
|
||||||
|
|
||||||
|
# chording: hold power and then tap vol-up N times to adjust the volume by N increments.
|
||||||
|
# XXX: HOLDING POWER LIKE THIS IS RISKY. but the default hard-power-off is like 10s, so... i guess this works until it becomes a problem...?
|
||||||
|
power_pressed.voldown_pressed = (recurseVolUpDown 5).voldown_pressed;
|
||||||
|
power_pressed.volup_pressed = (recurseVolUpDown 5).volup_pressed;
|
||||||
|
|
||||||
|
# tap just one of the volume buttons.
|
||||||
|
voldown_pressed.trigger = "voldown_one";
|
||||||
|
volup_pressed.trigger = "volup_one";
|
||||||
|
};
|
||||||
|
|
||||||
# sxmo puts in /share/sxmo:
|
# sxmo puts in /share/sxmo:
|
||||||
# - profile.d/sxmo_init.sh
|
# - profile.d/sxmo_init.sh
|
||||||
# - appcfg/
|
# - appcfg/
|
||||||
@@ -424,6 +511,7 @@ in
|
|||||||
# the fallout of this is that during intense lag (e.g. OOM or swapping) it can
|
# the fallout of this is that during intense lag (e.g. OOM or swapping) it can
|
||||||
# start the service many times.
|
# start the service many times.
|
||||||
# see <repo:craftyguy/superd:internal/cmd/cmd.go>
|
# see <repo:craftyguy/superd:internal/cmd/cmd.go>
|
||||||
|
# startTimerDuration = 100 * time.Millisecond
|
||||||
# TODO: better fix may be to patch `sxmo_hook_lisgdstart.sh` and force it to behave as a singleton
|
# TODO: better fix may be to patch `sxmo_hook_lisgdstart.sh` and force it to behave as a singleton
|
||||||
# systemd.services."dedupe-sxmo-lisgd" = {
|
# systemd.services."dedupe-sxmo-lisgd" = {
|
||||||
# description = "kill duplicate lisgd processes started by superd";
|
# description = "kill duplicate lisgd processes started by superd";
|
||||||
@@ -534,18 +622,8 @@ in
|
|||||||
sxmo_wob = sxmoService "wob";
|
sxmo_wob = sxmoService "wob";
|
||||||
sxmo-x11-status = sxmoService "status_xsetroot";
|
sxmo-x11-status = sxmoService "status_xsetroot";
|
||||||
|
|
||||||
bonsaid = {
|
bonsaid.path = sxmoPath;
|
||||||
description = "programmable input dispatcher";
|
bonsaid.script = lib.mkBefore sxmoEnvSetup;
|
||||||
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";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env nix-shell
|
#!/usr/bin/env nix-shell
|
||||||
#!nix-shell -i bash -p coreutils
|
#!nix-shell -i bash -p coreutils -p playerctl -p pulseaudio
|
||||||
|
|
||||||
# input map considerations
|
# input map considerations
|
||||||
# - using compound actions causes delays.
|
# - using compound actions causes delays.
|
||||||
@@ -12,28 +12,33 @@
|
|||||||
#
|
#
|
||||||
# proposed future design:
|
# proposed future design:
|
||||||
# - when unlocked:
|
# - when unlocked:
|
||||||
# - volup1 -> app menu
|
# - volup-release -> app menu
|
||||||
# - voldown1 -> toggle keyboard
|
# - volup-hold -> WM menu
|
||||||
# - pow1 -> volup1 -> volume up
|
# - voldown-release -> toggle keyboard
|
||||||
# - pow1 -> voldown1 -> volume down
|
# - voldown-hold -> terminal
|
||||||
# - pow2 -> screen off
|
# - pow-volup xN -> volume up
|
||||||
# - pow3 -> kill app
|
# - pow-voldown xN -> volume down
|
||||||
# - when locked:
|
# - pow-x2 -> screen off
|
||||||
# - volup1 -> volume up
|
# - pow-hold -> kill app
|
||||||
# - voldown1 -> volume down
|
# - when screenoff:
|
||||||
# - pow1 -> screen on
|
# - volup -> volume up
|
||||||
# - pow2 -> toggle player
|
# - voldown -> volume down
|
||||||
# benefits
|
# - pow-x1 -> screen on
|
||||||
|
# - pow-x2 -> toggle player
|
||||||
|
# - pow-volup -> seek +30s
|
||||||
|
# - pow-voldown -> seek -10s
|
||||||
|
# benefits:
|
||||||
# - volup and voldown are able to be far more responsive
|
# - volup and voldown are able to be far more responsive
|
||||||
# - which means faster vkbd, menus, volume adjustment (when locked)
|
# - which means faster vkbd, menus, volume adjustment (when locked)
|
||||||
# limitations
|
# - less mental load than the chording-based approach (where i hold power to adjust volume)
|
||||||
# - terminal is unmapped. that could be mapped to pow1?
|
# - less risk due to not chording the power button
|
||||||
# - wm menu is unmapped. but i never used that much anyway
|
# drawbacks:
|
||||||
|
# - volup/down actions are triggered by the release instead of the press; slight additional latency for pulling open the keyboard
|
||||||
|
# - moving the WM menu into the top-level menu could allow keeping voldown free of complication
|
||||||
|
|
||||||
# increments to use for volume adjustment
|
# increments to use for volume adjustment
|
||||||
VOL_INCR_1=5
|
VOL_INCR_1=5
|
||||||
VOL_INCR_2=10
|
VOL_INCR_2=10
|
||||||
VOL_INCR_3=15
|
|
||||||
|
|
||||||
# replicating the naming from upstream sxmo_hook_inputhandler.sh...
|
# replicating the naming from upstream sxmo_hook_inputhandler.sh...
|
||||||
ACTION="$1"
|
ACTION="$1"
|
||||||
@@ -53,9 +58,9 @@ handle_with() {
|
|||||||
# # probably not handling proximity* correctly here
|
# # probably not handling proximity* correctly here
|
||||||
# case "$STATE" in
|
# case "$STATE" in
|
||||||
# *lock)
|
# *lock)
|
||||||
# respond_with sxmo_state_switch.sh set screenoff
|
# respond_with sxmo_state.sh set screenoff
|
||||||
# *)
|
# *)
|
||||||
# respond_with sxmo_state_switch.sh set unlock
|
# respond_with sxmo_state.sh set unlock
|
||||||
# esac
|
# esac
|
||||||
# }
|
# }
|
||||||
|
|
||||||
@@ -69,7 +74,7 @@ if [ "$STATE" = "unlock" ]; then
|
|||||||
case "$ACTION" in
|
case "$ACTION" in
|
||||||
# powerbutton_one: intentional default to no-op
|
# powerbutton_one: intentional default to no-op
|
||||||
# powerbutton_two: intentional default to screenoff
|
# powerbutton_two: intentional default to screenoff
|
||||||
"powerbutton_three")
|
"powerhold")
|
||||||
# power thrice: kill active window
|
# power thrice: kill active window
|
||||||
handle_with sxmo_killwindow.sh
|
handle_with sxmo_killwindow.sh
|
||||||
;;
|
;;
|
||||||
@@ -78,19 +83,18 @@ if [ "$STATE" = "unlock" ]; then
|
|||||||
# volume up once: app-specific menu w/ fallback to SXMO system menu
|
# volume up once: app-specific menu w/ fallback to SXMO system menu
|
||||||
handle_with sxmo_appmenu.sh
|
handle_with sxmo_appmenu.sh
|
||||||
;;
|
;;
|
||||||
# volup_two: intentionally defaulted for volume control
|
|
||||||
"volup_three")
|
|
||||||
# volume up thrice: DE menu
|
|
||||||
handle_with sxmo_wmmenu.sh
|
|
||||||
;;
|
|
||||||
|
|
||||||
"voldown_one")
|
"voldown_one")
|
||||||
# volume down once: toggle keyboard
|
# volume down once: toggle keyboard
|
||||||
handle_with sxmo_keyboard.sh toggle
|
handle_with sxmo_keyboard.sh toggle
|
||||||
;;
|
;;
|
||||||
# voldown_two: intentionally defaulted for volume control
|
|
||||||
"voldown_three")
|
"powertoggle_volup")
|
||||||
# volume down thrice: launch terminal
|
# power -> volume up: DE menu
|
||||||
|
handle_with sxmo_wmmenu.sh
|
||||||
|
;;
|
||||||
|
"powertoggle_voldown")
|
||||||
|
# power -> volume down: launch terminal
|
||||||
handle_with sxmo_terminal.sh
|
handle_with sxmo_terminal.sh
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -102,9 +106,17 @@ if [ "$STATE" = "screenoff" ]; then
|
|||||||
# power twice => toggle media player
|
# power twice => toggle media player
|
||||||
handle_with playerctl play-pause
|
handle_with playerctl play-pause
|
||||||
;;
|
;;
|
||||||
"powerbutton_three")
|
"powerhold")
|
||||||
# power once during deep sleep often gets misread as power three, so treat these same
|
# power toggle during deep sleep often gets misread as power hold, so treat same
|
||||||
handle_with sxmo_state_switch.sh set unlock
|
handle_with sxmo_state.sh set unlock
|
||||||
|
;;
|
||||||
|
"powertoggle_volup"|"powerhold_volup")
|
||||||
|
# power -> volume up: seek forward
|
||||||
|
handle_with playerctl position 30+
|
||||||
|
;;
|
||||||
|
"powertoggle_voldown"|"powerhold_voldown")
|
||||||
|
# power -> volume down: seek backward
|
||||||
|
handle_with playerctl position 10-
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
@@ -113,32 +125,27 @@ fi
|
|||||||
case "$ACTION" in
|
case "$ACTION" in
|
||||||
"powerbutton_one")
|
"powerbutton_one")
|
||||||
# power once => unlock
|
# power once => unlock
|
||||||
handle_with sxmo_state_switch.sh set unlock
|
handle_with sxmo_state.sh set unlock
|
||||||
;;
|
;;
|
||||||
"powerbutton_two")
|
"powerbutton_two")
|
||||||
# power twice => screenoff
|
# power twice => screenoff
|
||||||
handle_with sxmo_state_switch.sh set screenoff
|
handle_with sxmo_state.sh set screenoff
|
||||||
;;
|
;;
|
||||||
# powerbutton_three: intentional no-op because overloading the kill-window handler is risky
|
# powerbutton_three: intentional no-op because overloading the kill-window handler is risky
|
||||||
|
|
||||||
"volup_one")
|
"volup_one")
|
||||||
handle_with sxmo_audio.sh vol up "$VOL_INCR_1"
|
handle_with pactl set-sink-volume @DEFAULT_SINK@ +"$VOL_INCR_1%"
|
||||||
;;
|
;;
|
||||||
"volup_two")
|
"voldown_one")
|
||||||
handle_with sxmo_audio.sh vol up "$VOL_INCR_2"
|
handle_with pactl set-sink-volume @DEFAULT_SINK@ -"$VOL_INCR_1%"
|
||||||
;;
|
|
||||||
"volup_three")
|
|
||||||
handle_with sxmo_audio.sh vol up "$VOL_INCR_3"
|
|
||||||
;;
|
;;
|
||||||
|
|
||||||
"voldown_one")
|
# HOLD power button and tap volup/down to adjust volume
|
||||||
handle_with sxmo_audio.sh vol down "$VOL_INCR_1"
|
"powerhold_volup")
|
||||||
|
handle_with pactl set-sink-volume @DEFAULT_SINK@ +"$VOL_INCR_1%"
|
||||||
;;
|
;;
|
||||||
"voldown_two")
|
"powerhold_voldown")
|
||||||
handle_with sxmo_audio.sh vol down "$VOL_INCR_2"
|
handle_with pactl set-sink-volume @DEFAULT_SINK@ -"$VOL_INCR_1%"
|
||||||
;;
|
|
||||||
"voldown_three")
|
|
||||||
handle_with sxmo_audio.sh vol down "$VOL_INCR_3"
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@@ -11,7 +11,7 @@ swaymsg mode default
|
|||||||
sxmo_wm.sh dpms on
|
sxmo_wm.sh dpms on
|
||||||
sxmo_wm.sh inputevent touchscreen off
|
sxmo_wm.sh inputevent touchscreen off
|
||||||
|
|
||||||
sxmo_daemons.sh start periodic_blink sxmo_run_periodically.sh "$BLINK_FREQ" sxmo_led.sh blink red blue
|
sxmo_jobs.sh start periodic_blink sxmo_run_periodically.sh "$BLINK_FREQ" sxmo_led.sh blink red blue
|
||||||
|
|
||||||
wait
|
wait
|
||||||
|
|
||||||
|
@@ -7,11 +7,11 @@
|
|||||||
# Create xdg user directories, such as ~/Pictures
|
# Create xdg user directories, such as ~/Pictures
|
||||||
xdg-user-dirs-update
|
xdg-user-dirs-update
|
||||||
|
|
||||||
sxmo_daemons.sh start daemon_manager
|
sxmo_jobs.sh start daemon_manager
|
||||||
|
|
||||||
# Periodically update some status bar components
|
# Periodically update some status bar components
|
||||||
sxmo_hook_statusbar.sh all
|
sxmo_hook_statusbar.sh all
|
||||||
sxmo_daemons.sh start statusbar_periodics sxmo_run_aligned.sh 60 \
|
sxmo_jobs.sh start statusbar_periodics sxmo_run_aligned.sh 60 \
|
||||||
sxmo_hook_statusbar.sh periodics
|
sxmo_hook_statusbar.sh periodics
|
||||||
|
|
||||||
# TODO: start these externally, via `wantedBy` in nix
|
# TODO: start these externally, via `wantedBy` in nix
|
||||||
@@ -24,7 +24,7 @@ systemctl --user start bonsaid
|
|||||||
# swaymsg output '*' bg "$SXMO_BG_IMG" fill
|
# swaymsg output '*' bg "$SXMO_BG_IMG" fill
|
||||||
|
|
||||||
# To setup initial lock state
|
# To setup initial lock state
|
||||||
sxmo_state_switch.sh set unlock
|
sxmo_state.sh set unlock
|
||||||
|
|
||||||
# Turn on auto-suspend
|
# Turn on auto-suspend
|
||||||
if [ -w "/sys/power/wakeup_count" ] && [ -f "/sys/power/wake_lock" ]; then
|
if [ -w "/sys/power/wakeup_count" ] && [ -f "/sys/power/wake_lock" ]; then
|
||||||
@@ -63,7 +63,7 @@ systemctl --user start sxmo_soundmonitor
|
|||||||
# rotate UI based on physical display angle by default
|
# rotate UI based on physical display angle by default
|
||||||
if [ -n "$SXMO_AUTOROTATE" ]; then
|
if [ -n "$SXMO_AUTOROTATE" ]; then
|
||||||
# TODO: this could use ~/.cache/sxmo/sxmo.autorotate like for lisgd above
|
# TODO: this could use ~/.cache/sxmo/sxmo.autorotate like for lisgd above
|
||||||
sxmo_daemons.sh start autorotate sxmo_autorotate.sh
|
sxmo_jobs.sh start autorotate sxmo_autorotate.sh
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Play a funky startup tune if you want (disabled by default)
|
# Play a funky startup tune if you want (disabled by default)
|
||||||
|
@@ -1,22 +0,0 @@
|
|||||||
{ config, lib, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
# give each host a shortname that all the other hosts know, to allow easy comms.
|
|
||||||
networking.hosts = lib.mkMerge [
|
|
||||||
(lib.mapAttrs' (host: cfg: {
|
|
||||||
# bare-name for LAN addresses
|
|
||||||
# if using router's DNS, these mappings will already exist.
|
|
||||||
# if using a different DNS provider (which servo does), then we need to explicity provide them.
|
|
||||||
# ugly hack. would be better to get servo to somehow use the router's DNS
|
|
||||||
name = cfg.lan-ip;
|
|
||||||
value = [ host ];
|
|
||||||
}) config.sane.hosts.by-name)
|
|
||||||
|
|
||||||
(lib.mapAttrs' (host: cfg: {
|
|
||||||
# -hn suffixed name for communication over my wg-home VPN.
|
|
||||||
# hn = "home network"
|
|
||||||
name = cfg.wg-home.ip;
|
|
||||||
value = [ "${host}-hn" ];
|
|
||||||
}) config.sane.hosts.by-name)
|
|
||||||
];
|
|
||||||
}
|
|
@@ -13,7 +13,8 @@ let
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
ssh.user_pubkey = mkOption {
|
ssh.user_pubkey = mkOption {
|
||||||
type = types.str;
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
description = ''
|
description = ''
|
||||||
ssh pubkey that the primary user of this machine will use when connecting to other machines.
|
ssh pubkey that the primary user of this machine will use when connecting to other machines.
|
||||||
e.g. "ssh-ed25519 AAAA<base64>".
|
e.g. "ssh-ed25519 AAAA<base64>".
|
||||||
|
@@ -2,6 +2,12 @@
|
|||||||
# if one of these hosts is offline, instead manually specify just cachix:
|
# if one of these hosts is offline, instead manually specify just cachix:
|
||||||
# - `nixos-rebuild --option substituters https://cache.nixos.org/`
|
# - `nixos-rebuild --option substituters https://cache.nixos.org/`
|
||||||
#
|
#
|
||||||
|
# additionally, sends build jobs to supercap/servo/desko (splits the jobs across all that are enabled).
|
||||||
|
# to verify one particular remote builder:
|
||||||
|
# - `nix store ping --store ssh://servo`
|
||||||
|
# NOTE: if your unix user doesn't have ssh access to the remote builder, do the above as root (not just sudo, actual root).
|
||||||
|
# - `sudo su; nix store ping --store ssh://supercap`
|
||||||
|
#
|
||||||
# future improvements:
|
# future improvements:
|
||||||
# - apply for community arm build box:
|
# - apply for community arm build box:
|
||||||
# - <https://github.com/nix-community/aarch64-build-box>
|
# - <https://github.com/nix-community/aarch64-build-box>
|
||||||
@@ -36,6 +42,18 @@ in
|
|||||||
nixos = subOpt;
|
nixos = subOpt;
|
||||||
cachix = subOpt;
|
cachix = subOpt;
|
||||||
};
|
};
|
||||||
|
sane.nixcache.remote-builders.desko = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
sane.nixcache.remote-builders.servo = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
sane.nixcache.remote-builders.supercap = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
@@ -55,5 +73,44 @@ in
|
|||||||
"desko:Q7mjjqoBMgNQ5P0e63sLur65A+D4f3Sv4QiycDIKxiI="
|
"desko:Q7mjjqoBMgNQ5P0e63sLur65A+D4f3Sv4QiycDIKxiI="
|
||||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||||
];
|
];
|
||||||
|
|
||||||
|
nix.buildMachines = [
|
||||||
|
(lib.mkIf cfg.remote-builders.desko {
|
||||||
|
hostName = "desko";
|
||||||
|
system = "x86_64-linux";
|
||||||
|
protocol = "ssh-ng";
|
||||||
|
maxJobs = 4; # constrained by ram, for things like webkitgtk, etc.
|
||||||
|
speedFactor = 8;
|
||||||
|
supportedFeatures = [ "big-parallel" ];
|
||||||
|
mandatoryFeatures = [ ];
|
||||||
|
sshUser = "nixremote";
|
||||||
|
sshKey = config.sops.secrets."nixremote_ssh_key".path;
|
||||||
|
})
|
||||||
|
(lib.mkIf cfg.remote-builders.servo {
|
||||||
|
hostName = "servo";
|
||||||
|
system = "x86_64-linux";
|
||||||
|
protocol = "ssh-ng";
|
||||||
|
maxJobs = 3; # constrained by ram, for things like webkitgtk, etc.
|
||||||
|
speedFactor = 2;
|
||||||
|
supportedFeatures = [
|
||||||
|
# "big-parallel" # it can't reliably build webkitgtk
|
||||||
|
];
|
||||||
|
mandatoryFeatures = [ ];
|
||||||
|
sshUser = "nixremote";
|
||||||
|
sshKey = config.sops.secrets."nixremote_ssh_key".path;
|
||||||
|
})
|
||||||
|
(lib.mkIf cfg.remote-builders.supercap {
|
||||||
|
hostName = "supercap";
|
||||||
|
system = "x86_64-linux";
|
||||||
|
protocol = "ssh-ng";
|
||||||
|
maxJobs = 32;
|
||||||
|
speedFactor = 16;
|
||||||
|
supportedFeatures = [ "big-parallel" ];
|
||||||
|
mandatoryFeatures = [ ];
|
||||||
|
sshUser = "root";
|
||||||
|
sshKey = config.sops.secrets."nixremote_ssh_key".path;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
nix.distributedBuilds = lib.mkIf (cfg.remote-builders.desko || cfg.remote-builders.servo || cfg.remote-builders.supercap) true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,16 +0,0 @@
|
|||||||
{ config, lib, ... }:
|
|
||||||
{
|
|
||||||
options.sane.roles.ac = with lib; mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
services which you probably only want to use with AC power.
|
|
||||||
specifically because they drain resources like power or bandwidth.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf config.sane.roles.ac {
|
|
||||||
# sane.yggdrasil.enable = true;
|
|
||||||
# services.i2p.enable = true;
|
|
||||||
};
|
|
||||||
}
|
|
@@ -28,6 +28,7 @@ in
|
|||||||
sane.programs.qemu.enableFor.user.colin = true;
|
sane.programs.qemu.enableFor.user.colin = true;
|
||||||
# serve packages to other machines that ask for them
|
# serve packages to other machines that ask for them
|
||||||
sane.services.nixserve.enable = true;
|
sane.services.nixserve.enable = true;
|
||||||
|
sane.services.nixserve.remoteBuilderPubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG4KI7I2w5SvXRgUrXYiuBXPuTL+ZZsPoru5a2YkIuCf root@nixremote";
|
||||||
|
|
||||||
# each concurrent derivation realization uses a different nix build user.
|
# each concurrent derivation realization uses a different nix build user.
|
||||||
# default is 32 build users, limiting us to that many concurrent jobs.
|
# default is 32 build users, limiting us to that many concurrent jobs.
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./ac.nix
|
|
||||||
./build-machine.nix
|
./build-machine.nix
|
||||||
./client
|
./client
|
||||||
./dev-machine.nix
|
./dev-machine.nix
|
||||||
|
./handheld.nix
|
||||||
|
./pc.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
fileSystems."/tmp" = lib.mkIf (config.sane.roles.build-machine.enable || config.sane.roles.dev-machine) {
|
fileSystems."/tmp" = lib.mkIf (config.sane.roles.build-machine.enable || config.sane.roles.dev-machine) {
|
||||||
|
17
hosts/modules/roles/handheld.nix
Normal file
17
hosts/modules/roles/handheld.nix
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{ config, lib, ... }:
|
||||||
|
{
|
||||||
|
options.sane.roles.handheld = with lib; mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
services/programs which you probably only want on a handheld device.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf config.sane.roles.handheld {
|
||||||
|
sane.programs.guiApps.suggestedPrograms = [
|
||||||
|
"handheldGuiApps"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
23
hosts/modules/roles/pc.nix
Normal file
23
hosts/modules/roles/pc.nix
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{ config, lib, ... }:
|
||||||
|
{
|
||||||
|
options.sane.roles.pc = with lib; mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
programs/services which only make sense for a PC form factor (e.g. keyboard + mouse).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf config.sane.roles.pc {
|
||||||
|
sane.programs.guiApps.suggestedPrograms = [
|
||||||
|
"pcGuiApps"
|
||||||
|
];
|
||||||
|
sane.programs.gameApps.suggestedPrograms = [
|
||||||
|
"pcGameApps"
|
||||||
|
];
|
||||||
|
sane.programs.consoleUtils.suggestedPrograms = [
|
||||||
|
"consoleMediaUtils"
|
||||||
|
"pcConsoleUtils"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
@@ -8,5 +8,4 @@ moduleArgs:
|
|||||||
|
|
||||||
{
|
{
|
||||||
feeds = import ./feeds moduleArgs;
|
feeds = import ./feeds moduleArgs;
|
||||||
keys = import ./keys.nix;
|
|
||||||
}
|
}
|
||||||
|
@@ -1,23 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 479140,
|
|
||||||
"content_type": "text/xml; charset=utf-8",
|
|
||||||
"description": "ACQ2 is Ben and David's conversations with expert founders and investors.",
|
"description": "ACQ2 is Ben and David's conversations with expert founders and investors.",
|
||||||
"favicon": "",
|
|
||||||
"favicon_data_uri": "",
|
|
||||||
"hubs": [
|
|
||||||
"https://pubsubhubbub.appspot.com/"
|
|
||||||
],
|
|
||||||
"is_podcast": true,
|
"is_podcast": true,
|
||||||
"is_push": true,
|
|
||||||
"item_count": 95,
|
|
||||||
"last_updated": "2023-09-18T05:11:04+00:00",
|
|
||||||
"score": 24,
|
|
||||||
"self_url": "https://feeds.transistor.fm/acq2",
|
|
||||||
"site_name": "",
|
"site_name": "",
|
||||||
"site_url": "https://feeds.transistor.fm",
|
"site_url": "https://feeds.transistor.fm",
|
||||||
"title": "ACQ2 by Acquired",
|
"title": "ACQ2 by Acquired",
|
||||||
"url": "https://feeds.transistor.fm/acq2",
|
"url": "https://feeds.transistor.fm/acq2",
|
||||||
"velocity": 0.052,
|
"velocity": 0.052
|
||||||
"version": "rss20"
|
|
||||||
}
|
}
|
@@ -1,21 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 1423488,
|
|
||||||
"content_type": "application/rss+xml; charset=utf-8",
|
|
||||||
"description": "Industry veterans, degenerate gamblers & besties Chamath Palihapitiya, Jason Calacanis, David Sacks & David Friedberg cover all things economic, tech, political, social & poker.",
|
"description": "Industry veterans, degenerate gamblers & besties Chamath Palihapitiya, Jason Calacanis, David Sacks & David Friedberg cover all things economic, tech, political, social & poker.",
|
||||||
"favicon": "",
|
|
||||||
"favicon_data_uri": "",
|
|
||||||
"hubs": [],
|
|
||||||
"is_podcast": true,
|
"is_podcast": true,
|
||||||
"is_push": false,
|
|
||||||
"item_count": 160,
|
|
||||||
"last_updated": "2023-09-22T22:51:00+00:00",
|
|
||||||
"score": 18,
|
|
||||||
"self_url": "https://allinchamathjason.libsyn.com/rss",
|
|
||||||
"site_name": "All-In with Chamath, Jason, Sacks & Friedberg",
|
"site_name": "All-In with Chamath, Jason, Sacks & Friedberg",
|
||||||
"site_url": "https://allinchamathjason.libsyn.com",
|
"site_url": "https://allinchamathjason.libsyn.com",
|
||||||
"title": "All-In with Chamath, Jason, Sacks & Friedberg",
|
"title": "All-In with Chamath, Jason, Sacks & Friedberg",
|
||||||
"url": "https://allinchamathjason.libsyn.com/rss",
|
"url": "https://allinchamathjason.libsyn.com/rss",
|
||||||
"velocity": 0.124,
|
"velocity": 0.124
|
||||||
"version": "rss20"
|
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
@@ -1,23 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 14856,
|
|
||||||
"content_type": "application/rss+xml; charset=utf-8",
|
|
||||||
"description": "A podcast around the idea of creating a Civilizational Bootstrapper, a set of tools and technology that can be used to replicate the foundations of civilization along with itself.",
|
"description": "A podcast around the idea of creating a Civilizational Bootstrapper, a set of tools and technology that can be used to replicate the foundations of civilization along with itself.",
|
||||||
"favicon": "",
|
|
||||||
"favicon_data_uri": "",
|
|
||||||
"hubs": [
|
|
||||||
"https://pubsubhubbub.appspot.com/"
|
|
||||||
],
|
|
||||||
"is_podcast": true,
|
"is_podcast": true,
|
||||||
"is_push": true,
|
|
||||||
"item_count": 7,
|
|
||||||
"last_updated": "2023-05-05T21:46:30+00:00",
|
|
||||||
"score": 22,
|
|
||||||
"self_url": "https://anchor.fm/s/34c7232c/podcast/rss",
|
|
||||||
"site_name": "",
|
"site_name": "",
|
||||||
"site_url": "",
|
"site_url": "",
|
||||||
"title": "Civboot",
|
"title": "Civboot",
|
||||||
"url": "https://anchor.fm/s/34c7232c/podcast/rss",
|
"url": "https://anchor.fm/s/34c7232c/podcast/rss",
|
||||||
"velocity": 0.006,
|
"velocity": 0.006
|
||||||
"version": "rss20"
|
|
||||||
}
|
}
|
@@ -1,21 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 208377,
|
|
||||||
"content_type": "application/xml; charset=utf-8",
|
|
||||||
"description": "applieddivinitystudies@gmail.com",
|
"description": "applieddivinitystudies@gmail.com",
|
||||||
"favicon": "",
|
|
||||||
"favicon_data_uri": "",
|
|
||||||
"hubs": [],
|
|
||||||
"is_podcast": false,
|
"is_podcast": false,
|
||||||
"is_push": false,
|
|
||||||
"item_count": 20,
|
|
||||||
"last_updated": "2023-08-02T08:22:33.539000+00:00",
|
|
||||||
"score": 26,
|
|
||||||
"self_url": "https://applieddivinitystudies.com/atom.xml",
|
|
||||||
"site_name": "Applied Divinity Studies",
|
"site_name": "Applied Divinity Studies",
|
||||||
"site_url": "https://applieddivinitystudies.com",
|
"site_url": "https://applieddivinitystudies.com",
|
||||||
"title": "Applied Divinity Studies",
|
"title": "Applied Divinity Studies",
|
||||||
"url": "https://www.applieddivinitystudies.com/atom.xml",
|
"url": "https://www.applieddivinitystudies.com/atom.xml",
|
||||||
"velocity": 0.054,
|
"velocity": 0.048
|
||||||
"version": "atom10"
|
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,21 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 24700,
|
|
||||||
"content_type": "text/xml; charset=utf-8",
|
|
||||||
"description": "Austin Vernon's Blog",
|
"description": "Austin Vernon's Blog",
|
||||||
"favicon": "",
|
|
||||||
"favicon_data_uri": "",
|
|
||||||
"hubs": [],
|
|
||||||
"is_podcast": false,
|
"is_podcast": false,
|
||||||
"is_push": false,
|
|
||||||
"item_count": 54,
|
|
||||||
"last_updated": "2023-09-08T00:00:00+00:00",
|
|
||||||
"score": 24,
|
|
||||||
"self_url": "",
|
|
||||||
"site_name": "Austin Vernon - Austin Vernon's Blog",
|
"site_name": "Austin Vernon - Austin Vernon's Blog",
|
||||||
"site_url": "https://austinvernon.site",
|
"site_url": "https://austinvernon.site",
|
||||||
"title": "Austin Vernon",
|
"title": "Austin Vernon",
|
||||||
"url": "https://austinvernon.site/rss.xml",
|
"url": "https://austinvernon.site/rss.xml",
|
||||||
"velocity": 0.059,
|
"velocity": 0.058
|
||||||
"version": "rss20"
|
|
||||||
}
|
}
|
@@ -1,21 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 592815,
|
|
||||||
"content_type": "application/xml; charset=utf-8",
|
|
||||||
"description": "A free newsletter by Balaji.",
|
"description": "A free newsletter by Balaji.",
|
||||||
"favicon": "",
|
|
||||||
"favicon_data_uri": "",
|
|
||||||
"hubs": [],
|
|
||||||
"is_podcast": true,
|
"is_podcast": true,
|
||||||
"is_push": false,
|
|
||||||
"item_count": 20,
|
|
||||||
"last_updated": "2023-07-04T11:31:07+00:00",
|
|
||||||
"score": 14,
|
|
||||||
"self_url": "https://balajis.com/feed",
|
|
||||||
"site_name": "balajis.com | Substack",
|
"site_name": "balajis.com | Substack",
|
||||||
"site_url": "https://balajis.com",
|
"site_url": "https://balajis.com",
|
||||||
"title": "balajis.com",
|
"title": "balajis.com",
|
||||||
"url": "https://balajis.com/feed",
|
"url": "https://balajis.com/feed",
|
||||||
"velocity": 0.022,
|
"velocity": 0.027
|
||||||
"version": "rss20"
|
|
||||||
}
|
}
|
@@ -1,21 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 328802,
|
|
||||||
"content_type": "application/rss+xml; charset=utf-8",
|
|
||||||
"description": "",
|
"description": "",
|
||||||
"favicon": "https://images.squarespace-cdn.com/content/v1/50363cf324ac8e905e7df861/ebdb4645-db93-4967-881d-db698ee59c2c/favicon.ico?format=100w",
|
|
||||||
"favicon_data_uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAMAAABHPGVmAAAB4FBMVEUAAADmRjIBAADmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjLmRjL///8mIgRMAAAAnnRSTlMAAAA6W1pZTTESpvnryogzAeaCFKwboQv38vP6X449P0FPe8b8vw5mhe02aAif/VhCZx/h4PVD1xwEmQVt3i1uBwwWPpv0Ybu8vtLx7m/JSf5IniT28DWLOTxAUX3EzSgXaXJxc0URa+elCjSdnKLWGewykUv4VSB87zgmHs8iKbZlCbFXhLfHGOpKY9VTjaOuUDAG2tvLGidGL+iWJUyE2tMAAAJwSURBVHja7df5U1JRGMZxnxItw6Q0FdTCoowyWiSJMLXQrMAyU9ojWxQFc8+MijYL23db+VsbTsCZC9xkbu9JnTnfH58Z+MywvAN5MplMJpPJFjuoRoqszNelVVC4ajUpAxTFMlqjL15bYgAEIbx160sBUQivbAMgCuGVVwCkSKUxmakq9dZUEyM1GzclMtdu3mKJsbZuo0XqAF7p9ko2WnfQIjvBJ6B+FxttuwUgfNxjYuteeoSHfQ1srRaL2OPj/kaBCGA2xkfHAXEI4DzIxhoDNQKeq4m974eaQYu0tFYkOnzE3dYen0xHqW+Xo+NYouMnPGzxdjqFH8iTpwzCT31Xx+lWiD/1pu4zAEiRnt5UqVtf7Esh+Fs5I2fPnU924eKly3+cK/7kM+Bq37XrWbtxE9pOPfoHAmwdHEoiQW9MpRA0fuMBnYcdr0IggVjVkGFNCFtdt9hc7hSA8LnAEp9HRjlC9XLxYGbna2xcgdh6rel5JjQjwORUfDa6FcjY7fFgWr7pf0DusHnmrgIJhJGZVgS4d5/N9gdKJAK6Xyvo746xHg5RIo8A3mP3ExtbbX2gREJPdYny62afJT+vz6NkiGpzL5ghFLG+NAhHXr1mhkik4U0YzFAgfmSWC/K2q0rZVLve8a4lYmCPVyI9ZW3DikIT0zkhJe9rlU02fhj9CE5wJEseXy5ItriwIGINIk97SwmZ8ZEjFvsnZZ+/NJMjc+7ovLKoixwJfEVGlIj6N14iEllGSBhZIkY8swNN6XV+o0TUKlrxH5DBZYZ4xb9c+D7yI5A9/U8ypP6XX6XIPAWw8P94mUwmk8lki95vmJ/g9Xmlv3QAAAAASUVORK5CYII=",
|
|
||||||
"hubs": [],
|
|
||||||
"is_podcast": false,
|
"is_podcast": false,
|
||||||
"is_push": false,
|
|
||||||
"item_count": 20,
|
|
||||||
"last_updated": "2023-08-27T13:29:00+00:00",
|
|
||||||
"score": 8,
|
|
||||||
"self_url": "",
|
|
||||||
"site_name": "Benedict Evans",
|
"site_name": "Benedict Evans",
|
||||||
"site_url": "https://www.ben-evans.com",
|
"site_url": "https://www.ben-evans.com",
|
||||||
"title": "Essays - Benedict Evans",
|
"title": "Essays - Benedict Evans",
|
||||||
"url": "https://www.ben-evans.com/benedictevans?format=rss",
|
"url": "https://www.ben-evans.com/benedictevans?format=rss",
|
||||||
"velocity": 0.027,
|
"velocity": 0.026
|
||||||
"version": "rss20"
|
|
||||||
}
|
}
|
@@ -1,21 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 264830,
|
|
||||||
"content_type": "application/xml; charset=utf-8",
|
|
||||||
"description": "Yet another programming blog. Thoughts on software and related misadventures.",
|
"description": "Yet another programming blog. Thoughts on software and related misadventures.",
|
||||||
"favicon": "https://bitbashing.io/favicon.ico",
|
|
||||||
"favicon_data_uri": "data:image/png;base64,AAABAAEAEBACAAEAAQCwAAAAFgAAACgAAAAQAAAAIAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUFBQAAAAAAP//AAD//wAA7/8AAO//AADv/wAA7/8AAO//AADvAwAA7/8AAO8DAADv/wAA7/8AAO//AADv/wAA//8AAP//AAD//wAA//8AAO//AADv/wAA7/8AAO//AADv/wAA7wMAAO//AADvAwAA7/8AAO//AADv/wAA7/8AAP//AAD//wAA",
|
|
||||||
"hubs": [],
|
|
||||||
"is_podcast": false,
|
"is_podcast": false,
|
||||||
"is_push": false,
|
|
||||||
"item_count": 10,
|
|
||||||
"last_updated": "2023-09-08T00:00:00+00:00",
|
|
||||||
"score": 20,
|
|
||||||
"self_url": "https://bitbashing.io/feed.xml",
|
|
||||||
"site_name": "Bit Bashing",
|
"site_name": "Bit Bashing",
|
||||||
"site_url": "https://bitbashing.io",
|
"site_url": "https://bitbashing.io",
|
||||||
"title": "Bit Bashing",
|
"title": "Bit Bashing",
|
||||||
"url": "https://bitbashing.io/feed.xml",
|
"url": "https://bitbashing.io/feed.xml",
|
||||||
"velocity": 0.003,
|
"velocity": 0.004
|
||||||
"version": "rss20"
|
|
||||||
}
|
}
|
@@ -1,21 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 1,
|
|
||||||
"content_length": 436175,
|
|
||||||
"content_type": "text/xml; charset=utf-8",
|
|
||||||
"description": null,
|
"description": null,
|
||||||
"favicon": "",
|
|
||||||
"favicon_data_uri": "",
|
|
||||||
"hubs": [],
|
|
||||||
"is_podcast": false,
|
"is_podcast": false,
|
||||||
"is_push": false,
|
|
||||||
"item_count": 63,
|
|
||||||
"last_updated": "2023-09-09T00:00:00+00:00",
|
|
||||||
"score": -4,
|
|
||||||
"self_url": "",
|
|
||||||
"site_name": "Daniel Janus \u2013 blog",
|
"site_name": "Daniel Janus \u2013 blog",
|
||||||
"site_url": "https://blog.danieljanus.pl",
|
"site_url": "https://blog.danieljanus.pl",
|
||||||
"title": "code \u00b7 words \u00b7 emotions: Daniel Janus\u2019s blog",
|
"title": "code \u00b7 words \u00b7 emotions: Daniel Janus\u2019s blog",
|
||||||
"url": "https://blog.danieljanus.pl/atom.xml",
|
"url": "https://blog.danieljanus.pl/atom.xml",
|
||||||
"velocity": 0.01,
|
"velocity": 0.01
|
||||||
"version": "atom10"
|
|
||||||
}
|
}
|
@@ -1,23 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 555845,
|
|
||||||
"content_type": "application/atom+xml; charset=utf-8",
|
|
||||||
"description": "I'm David Rosenthal, and this is a place to discuss the work I'm doing in Digital Preservation.",
|
"description": "I'm David Rosenthal, and this is a place to discuss the work I'm doing in Digital Preservation.",
|
||||||
"favicon": "",
|
|
||||||
"favicon_data_uri": "",
|
|
||||||
"hubs": [
|
|
||||||
"http://pubsubhubbub.appspot.com/"
|
|
||||||
],
|
|
||||||
"is_podcast": false,
|
"is_podcast": false,
|
||||||
"is_push": true,
|
|
||||||
"item_count": 25,
|
|
||||||
"last_updated": "2023-09-19T15:00:00.137000+00:00",
|
|
||||||
"score": 20,
|
|
||||||
"self_url": "https://www.blogger.com/feeds/4503292949532760618/posts/default",
|
|
||||||
"site_name": "DSHR's Blog",
|
"site_name": "DSHR's Blog",
|
||||||
"site_url": "https://blog.dshr.org",
|
"site_url": "https://blog.dshr.org",
|
||||||
"title": "DSHR's Blog",
|
"title": "DSHR's Blog",
|
||||||
"url": "https://blog.dshr.org/feeds/posts/default",
|
"url": "https://blog.dshr.org/feeds/posts/default",
|
||||||
"velocity": 0.308,
|
"velocity": 0.333
|
||||||
"version": "atom10"
|
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
@@ -1,21 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 66707,
|
|
||||||
"content_type": "application/xml; charset=utf-8",
|
|
||||||
"description": "Empowering everyone to build reliable and efficient software.",
|
"description": "Empowering everyone to build reliable and efficient software.",
|
||||||
"favicon": "https://blog.rust-lang.org/images/favicon-16x16.png",
|
|
||||||
"favicon_data_uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4gseBBkAzEcAUAAAAWlJREFUOMul079L1WEUBvCPdhPUzbhC3JYQwn6MLTU4CA5C/QMJimQS2NDiZpM0NDoZ0iK4+SdIV5ykpgKtIYyiqCBSuKBBibflufBiVxt64eV73uc855z3fb7ndPh7daMPU/gR7ByeYRc/nbJGMI8GjvAKb2M34hspA84U9jgeYAIv8Bi9+IxFnMcYLqCJ12WiYTzHL0wee05Xcb6H3+EOt8CeXK0Z526b/R1ruIL74c4nVi3v+4BvOAxhHzv4lHMTb3A1WAO1zqjdhRU8SjWpOIBBvAx2hFEsRZ8pmEn28ZC+FhXLvY9L4UwHm+ksBNo79kvf4QlWC61uxR5qkSqoJttkROqN7wDvk+Q6LuIh+nEnMdVSxOYJ+zKetsEbqFVy9QXMpYE28TE3gC+YxXaKDeFGYvYqIa7jZppjI/2w1GZGzia4npiDSpz1tCjcjg5VbAW7hrtpqjqW8/3nMLXee+IwdfzvOP8BuzB3onylpecAAAAASUVORK5CYII=",
|
|
||||||
"hubs": [],
|
|
||||||
"is_podcast": false,
|
"is_podcast": false,
|
||||||
"is_push": false,
|
|
||||||
"item_count": 10,
|
|
||||||
"last_updated": "2023-09-22T00:00:00+00:00",
|
|
||||||
"score": 20,
|
|
||||||
"self_url": "https://blog.rust-lang.org/feed.xml",
|
|
||||||
"site_name": "The Rust Programming Language Blog",
|
"site_name": "The Rust Programming Language Blog",
|
||||||
"site_url": "https://blog.rust-lang.org",
|
"site_url": "https://blog.rust-lang.org",
|
||||||
"title": "Rust Blog",
|
"title": "Rust Blog",
|
||||||
"url": "https://blog.rust-lang.org/feed.xml",
|
"url": "https://blog.rust-lang.org/feed.xml",
|
||||||
"velocity": 0.114,
|
"velocity": 0.125
|
||||||
"version": "atom10"
|
|
||||||
}
|
}
|
9
modules/data/feeds/sources/blog.thalheim.io/default.json
Normal file
9
modules/data/feeds/sources/blog.thalheim.io/default.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"description": "Recent content on blog.thalheim.io",
|
||||||
|
"is_podcast": false,
|
||||||
|
"site_name": "~/git/blog",
|
||||||
|
"site_url": "https://blog.thalheim.io",
|
||||||
|
"title": "~/git/blog",
|
||||||
|
"url": "https://blog.thalheim.io/index.xml",
|
||||||
|
"velocity": 0.007
|
||||||
|
}
|
@@ -1,21 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 11276,
|
|
||||||
"content_type": "application/rss+xml; charset=utf-8",
|
|
||||||
"description": "bunnie's blog",
|
"description": "bunnie's blog",
|
||||||
"favicon": "https://www.bunniestudios.com/favicon.ico",
|
|
||||||
"favicon_data_uri": "data:image/png;base64,AAABAAEAEBAAAAAAAABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAFBQUADU1NQBdXV0AoKCgACYmJgBpaWkATk5OAIODgwAKCgoAfHx8ALi4uACxsbEAAgICAKOjowA+Pj4AAQEBAERERADy8vIABwcHABsbGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAASAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAALAAAAAAAAAAAAABMAAAAAAAAAAAAAAAAABQAACgAAAAAPAAAAAAAAAAkAAAAAAAAOAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADCQAAAAAAAAAAAAAAAAAAABANAAAAAAAAAAAAAAAAAP//AADAfQAAwTgAAMeZAADPnwAAz88AAM/PAADPzwAAz58AAMefAADDHwAAyD8AAM//AADP/wAAD/8AAA//AAA=",
|
|
||||||
"hubs": [],
|
|
||||||
"is_podcast": false,
|
"is_podcast": false,
|
||||||
"is_push": false,
|
|
||||||
"item_count": 5,
|
|
||||||
"last_updated": "2023-08-21T20:53:41+00:00",
|
|
||||||
"score": 20,
|
|
||||||
"self_url": "https://www.bunniestudios.com/blog/?feed=rss2",
|
|
||||||
"site_name": " bunnie's blog",
|
"site_name": " bunnie's blog",
|
||||||
"site_url": "https://www.bunniestudios.com",
|
"site_url": "https://www.bunniestudios.com",
|
||||||
"title": "bunnie's blog",
|
"title": "bunnie's blog",
|
||||||
"url": "https://www.bunniestudios.com/blog/?feed=rss2",
|
"url": "https://www.bunniestudios.com/blog/?feed=rss2",
|
||||||
"velocity": 0.076,
|
"velocity": 0.108
|
||||||
"version": "rss20"
|
|
||||||
}
|
}
|
@@ -1,21 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 9276,
|
|
||||||
"content_type": "application/rss+xml; charset=utf-8",
|
|
||||||
"description": "Community News For All of Seattle's Capitol Hill",
|
"description": "Community News For All of Seattle's Capitol Hill",
|
||||||
"favicon": "https://www.capitolhillseattle.com/favicon.ico",
|
|
||||||
"favicon_data_uri": "data:image/png;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAD///////////////////////////39/f/h4eH/vb29/729vf/i4uL//f39/////////////////////////////////////////////f39/6+vr/81NTX/AgIC/wAAAP8AAAD/AgIC/zU1Nf+wsLD//f39////////////////////////////+vr6/2pqav8BAQH/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AQEB/2xsbP/6+vr//////////////////v7+/7u7u/9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/VVVV/1VVVf9VVVX/vb29//7+/v/+/v7//////87Ozv8eHh7/HBwc/xwcHP8cHBz/t7e3/z8/P/+VlZX/WVlZ/xwcHP8cHBz/HBwc/x4eHv/Q0ND//v7+//7+/v9hYWH/AAAA/yUlJf/Dw8P/4ODg//n5+f/29vb//Pz8/+Li4v9MTEz/AAAA/wAAAP8AAAD/ZGRk///////7+/v/MTEx/xUVFf8WFhb/jY2N//7+/v/+/v7//v7+//7+/v/+/v7/+vr6/2FhYf8VFRX/FRUV/zMzM//8/Pz/7+/v/xgYGP8TExP/ExMT/xMTE/+2trb//v7+//7+/v/+/v7//v7+//7+/v/z8/P/JiYm/xMTE/8ZGRn/8PDw/+zs7P8EBAT/AAAA/wAAAP8AAAD/NjY2//39/f/+/v7//v7+//7+/v/+/v7//v7+/zk5Of8AAAD/BgYG/+3t7f/5+fn/FhYW/wAAAP8AAAD/AAAA/wICAv/T09P//v7+//7+/v/+/v7//v7+//7+/v9BQUH/AAAA/xcXF//5+fn//v7+/1FRUf8AAAD/AAAA/wAAAP8AAAD/RUVF//Pz8//+/v7//v7+//7+/v/+/v7/Li4u/wAAAP9UVFT///////////+7u7v/AQEB/wAAAP8AAAD/AAAA/wAAAP8fHx//vLy8//7+/v/+/v7/8/Pz/xEREf8BAQH/vb29/////////////f39/1hYWP8AAAD/AAAA/wAAAP8AAAD/GBgY/15eXv+Li4v/39/f/2tra/8AAAD/W1tb//7+/v/////////////////x8fH/Q0ND/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wMDA/8AAAD/RUVF//Ly8v////////////////////////////b29v+EhIT/EhIS/wAAAP8AAAD/AAAA/wAAAP8TExP/hYWF//f39/////////////////////////////////////////////Ly8v+2trb/kJCQ/5CQkP+3t7f/8/Pz////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
|
||||||
"hubs": [],
|
|
||||||
"is_podcast": false,
|
"is_podcast": false,
|
||||||
"is_push": false,
|
|
||||||
"item_count": 5,
|
|
||||||
"last_updated": "2023-09-22T15:12:34+00:00",
|
|
||||||
"score": 17,
|
|
||||||
"self_url": "https://www.capitolhillseattle.com/feed/",
|
|
||||||
"site_name": "CHS Capitol Hill Seattle News",
|
"site_name": "CHS Capitol Hill Seattle News",
|
||||||
"site_url": "https://www.capitolhillseattle.com",
|
"site_url": "https://www.capitolhillseattle.com",
|
||||||
"title": "CHS Capitol Hill Seattle News",
|
"title": "CHS Capitol Hill Seattle News",
|
||||||
"url": "https://www.capitolhillseattle.com/feed/",
|
"url": "https://www.capitolhillseattle.com/feed/",
|
||||||
"velocity": 5.393,
|
"velocity": 4.071
|
||||||
"version": "rss20"
|
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
@@ -1,21 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 10372863,
|
|
||||||
"content_type": "application/rss+xml; charset=utf-8",
|
|
||||||
"description": "An independent podcast examining what the U.S. Congress is doing with our money and in our names. \n\nwww.congressionaldish.com\nFollow @JenBriney on Twitter",
|
"description": "An independent podcast examining what the U.S. Congress is doing with our money and in our names. \n\nwww.congressionaldish.com\nFollow @JenBriney on Twitter",
|
||||||
"favicon": "",
|
|
||||||
"favicon_data_uri": "",
|
|
||||||
"hubs": [],
|
|
||||||
"is_podcast": true,
|
"is_podcast": true,
|
||||||
"is_push": false,
|
|
||||||
"item_count": 284,
|
|
||||||
"last_updated": "2023-09-18T01:17:36+00:00",
|
|
||||||
"score": 20,
|
|
||||||
"self_url": "https://feeds.libsyn.com/39908/rss",
|
|
||||||
"site_name": "test220119a",
|
"site_name": "test220119a",
|
||||||
"site_url": "https://feeds.libsyn.com",
|
"site_url": "https://feeds.libsyn.com",
|
||||||
"title": "Congressional Dish",
|
"title": "Congressional Dish",
|
||||||
"url": "https://feeds.libsyn.com/39908/rss",
|
"url": "https://feeds.libsyn.com/39908/rss",
|
||||||
"velocity": 0.07,
|
"velocity": 0.07
|
||||||
"version": "rss20"
|
|
||||||
}
|
}
|
@@ -1,21 +1,9 @@
|
|||||||
{
|
{
|
||||||
"bozo": 0,
|
|
||||||
"content_length": 74156,
|
|
||||||
"content_type": "application/rss+xml; charset=utf-8",
|
|
||||||
"description": "Cory Doctorow's Literary Works",
|
"description": "Cory Doctorow's Literary Works",
|
||||||
"favicon": "https://craphound.com/favicon.ico",
|
|
||||||
"favicon_data_uri": "data:image/png;base64,AAABAAIAEBAAAAAAIABoBAAAJgAAABAQAAAAAAgAaAUAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////xEREf8RERH/ERER/xEREf//////////////////////ERER/xEREf8RERH/ERER/////////////////xEREf8RERH/0dHR/9vb2/8RERH/ERER////////////ERER/xEREf/u7u7/3Nzc/xEREf8RERH///////////8RERH//////////////////////xEREf/+/v7/8fHx/xEREf//////////////////////ERER///////Z2dn/ERER//////////////////////8RERH/qamp/3x8fP8RERH//////////////////////xEREf/k5OT/ERER/xEREf//////////////////////ERER/wkJCf8QEBD/ERER//////////////////7+/v8RERH/ERER/xEREf8RERH/ERER/xEREf8RERH/ERER/xEREf/g4OD/29vb/xEREf8RERH/ERER/xEREf8RERH/ERER/xEREf///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAEAAAACAAAAABAAgAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAACQkJ/xAQEP8RERH/fHx8/6mpqf/R0dH/2dnZ/9vb2//c3Nz/4ODg/+Tk5P/u7u7/8fHx//7+/v//////AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/w4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4CAgICDg4ODgICAgIODg4CAgUHAgIODgICCwgCAg4OAg4ODg4CDQwCDg4ODgIOBgIODg4OAgQDAg4ODg4CCgICDg4ODgIAAQIODg4NAgICAgICAgICCQcCAgICAgICDg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
|
||||||
"hubs": [],
|
|
||||||
"is_podcast": true,
|
"is_podcast": true,
|
||||||
"is_push": false,
|
|
||||||
"item_count": 20,
|
|
||||||
"last_updated": "2023-09-17T21:04:18+00:00",
|
|
||||||
"score": 12,
|
|
||||||
"self_url": "https://craphound.com/feed/",
|
|
||||||
"site_name": "Cory Doctorow's craphound.com | Cory Doctorow's Literary Works",
|
"site_name": "Cory Doctorow's craphound.com | Cory Doctorow's Literary Works",
|
||||||
"site_url": "https://craphound.com",
|
"site_url": "https://craphound.com",
|
||||||
"title": "Cory Doctorow's craphound.com",
|
"title": "Cory Doctorow's craphound.com",
|
||||||
"url": "https://craphound.com/feed/",
|
"url": "https://craphound.com/feed/",
|
||||||
"velocity": 0.046,
|
"velocity": 0.058
|
||||||
"version": "rss20"
|
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user