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-*
|
||||
/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].
|
||||
|
||||
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)
|
||||
- [my implementation of impermanence](./modules/persist/default.nix)
|
||||
- my way of deploying dotfiles/configuring programs per-user:
|
||||
|
40
TODO.md
40
TODO.md
@@ -1,10 +1,14 @@
|
||||
## 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
|
||||
- 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:
|
||||
|
||||
- fold hosts/common/home/ssh.nix -> hosts/common/users/colin.nix
|
||||
|
||||
### sops/secrets
|
||||
- attach secrets to the thing they're used by (sane.programs)
|
||||
- rework secrets to leverage `sane.fs`
|
||||
@@ -21,7 +25,6 @@
|
||||
- fix lightdm-mobile-greeter for newer libhandy
|
||||
- port zecwallet-lite to a from-source build
|
||||
- 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
|
||||
- gtk: build schemas even on cross compilation: <https://github.com/NixOS/nixpkgs/pull/247844>
|
||||
@@ -30,8 +33,6 @@
|
||||
|
||||
## IMPROVEMENTS:
|
||||
### security/resilience
|
||||
- matrix/ntfy: automatically add the ntfy.uninsane.org push URL as part of synapse launch
|
||||
- ntfy: use a more secure topic
|
||||
- validate duplicity backups!
|
||||
- encrypt more ~ dirs (~/archives, ~/records, ..?)
|
||||
- best to do this after i know for sure i have good backups
|
||||
@@ -49,19 +50,36 @@
|
||||
- e.g. daily email checks; daily backup checks
|
||||
- integrate `nix check` into Gitea actions?
|
||||
|
||||
### faster/better deployments
|
||||
- remove audacity's dependency on webkitgtk (via wxwidgets)
|
||||
|
||||
### user experience
|
||||
#### moby
|
||||
- fix cpuidle (gets better power consumption): <https://xnux.eu/log/077.html>
|
||||
- install apps:
|
||||
- display QR codes for WiFi endpoints: <https://linuxphoneapps.org/apps/noappid.wisperwind.wifi2qr/>
|
||||
- shopping list: <https://linuxphoneapps.org/apps/ro.hume.cosmin.shoppinglist/>
|
||||
- offline Wikipedia
|
||||
- shopping list (not in nixpkgs): <https://linuxphoneapps.org/apps/ro.hume.cosmin.shoppinglist/>
|
||||
- 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:
|
||||
- don't show MPRIS if no players detected
|
||||
- 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
|
||||
- fix colors (red alert) to match overall theme
|
||||
- extend width to 100% of portrait mode
|
||||
- moby: tune GPS
|
||||
- run only geoclue, and not gpsd, to save power?
|
||||
- tune QGPS setting in eg25-control, for less jitter?
|
||||
@@ -81,6 +99,8 @@
|
||||
- phog: remove the gnome-shell runtime dependency to save hella closure size
|
||||
|
||||
#### 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)
|
||||
- Helix: make copy-to-system clipboard be the default
|
||||
- firefox/librewolf: persist history
|
||||
|
34
flake.lock
generated
34
flake.lock
generated
@@ -5,11 +5,11 @@
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1687709756,
|
||||
"narHash": "sha256-Y5wKlQSkgEK2weWdOu4J3riRd+kV/VCgHsqLNTTWQ/0=",
|
||||
"lastModified": 1694529238,
|
||||
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "dbabf0ca0c0c4bce6ea5eaf65af5cb694d2082c7",
|
||||
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -37,11 +37,11 @@
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1698544399,
|
||||
"narHash": "sha256-vhRmPyEyoPkrXF2iykBsWHA05MIaOSmMRLMF7Hul6+s=",
|
||||
"lastModified": 1700905716,
|
||||
"narHash": "sha256-w1vHn2MbGfdC+CrP3xLZ3scsI06N0iQLU7eTHIVEFGw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "d87c5d8c41c9b3b39592563242f3a448b5cc4bc9",
|
||||
"rev": "dfb95385d21475da10b63da74ae96d89ab352431",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -53,16 +53,16 @@
|
||||
},
|
||||
"nixpkgs-unpatched": {
|
||||
"locked": {
|
||||
"lastModified": 1698611440,
|
||||
"narHash": "sha256-jPjHjrerhYDy3q9+s5EAsuhyhuknNfowY6yt6pjn9pc=",
|
||||
"lastModified": 1701180790,
|
||||
"narHash": "sha256-kYWcHsk2A1VUpiOvSo7Pq175WnSVeltspTGM2q+Cr3U=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "0cbe9f69c234a7700596e943bfae7ef27a31b735",
|
||||
"rev": "c9702bf40b036c0f1d3d5b0aaf3eee2bf920124c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"ref": "master",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
@@ -83,11 +83,11 @@
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1698548647,
|
||||
"narHash": "sha256-7c03OjBGqnwDW0FBaBc+NjfEBxMkza+dxZGJPyIzfFE=",
|
||||
"lastModified": 1701127353,
|
||||
"narHash": "sha256-qVNX0wOl0b7+I35aRu78xUphOyELh+mtUp1KBx89K1Q=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "632c3161a6cc24142c8e3f5529f5d81042571165",
|
||||
"rev": "b1edbf5c0464b4cced90a3ba6f999e671f0af631",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -119,11 +119,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1698634059,
|
||||
"narHash": "sha256-+Oyv6vDyCtBzab/5cTG0nUrHD9gj7KgGfD4D1Rn4fCk=",
|
||||
"lastModified": 1699515935,
|
||||
"narHash": "sha256-cJIuVrYorhIzG5pRFZb+ZtaKhTFD92ThC42SaxvSe/E=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "2419750ca98fc04af42c91e50c49a29c68d465d2",
|
||||
"revCount": 210,
|
||||
"rev": "8a4273489d945f21d7e0ca6aac952460c7d4c391",
|
||||
"revCount": 216,
|
||||
"type": "git",
|
||||
"url": "https://git.uninsane.org/colin/uninsane"
|
||||
},
|
||||
|
88
flake.nix
88
flake.nix
@@ -36,13 +36,14 @@
|
||||
# - staging-next merged into master.
|
||||
#
|
||||
# which branch to source from?
|
||||
# - for everyday development, prefer `nixos-unstable` branch, as it provides good caching.
|
||||
# - if need to test bleeding updates (e.g. if submitting code into staging):
|
||||
# - use `staging-next` if it's been cut (i.e. if there's an active staging-next -> master PR)
|
||||
# - use `staging` if no staging-next branch has been cut.
|
||||
# - nixos-unstable: for everyday development; it provides good caching
|
||||
# - master: temporarily if i'm otherwise cherry-picking lots of already-applied patches
|
||||
# - staging-next: if testing stuff that's been PR'd into staging, i.e. base library updates.
|
||||
# - staging: maybe if no staging-next -> master PR has been cut yet?
|
||||
#
|
||||
# <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";
|
||||
|
||||
@@ -111,7 +112,7 @@
|
||||
|
||||
nixpkgsCompiledBy = system: nixpkgs.legacyPackages."${system}";
|
||||
|
||||
evalHost = { name, local, target }: nixpkgs.lib.nixosSystem {
|
||||
evalHost = { name, local, target, light ? false }: nixpkgs.lib.nixosSystem {
|
||||
system = target;
|
||||
modules = [
|
||||
{
|
||||
@@ -124,6 +125,9 @@
|
||||
# nixpkgs.buildPlatform = local; # set by instantiate.nix instead
|
||||
# nixpkgs.config.replaceStdenv = { pkgs }: pkgs.ccacheStdenv;
|
||||
}
|
||||
(optionalAttrs light {
|
||||
sane.enableSlowPrograms = false;
|
||||
})
|
||||
(import ./hosts/instantiate.nix { hostName = name; })
|
||||
self.nixosModules.default
|
||||
self.nixosModules.passthru
|
||||
@@ -141,8 +145,11 @@
|
||||
hosts = {
|
||||
servo = { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
desko = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
desko-light = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; light = true; };
|
||||
lappy = { name = "lappy"; 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.
|
||||
@@ -150,10 +157,7 @@
|
||||
# - but fewer of their packages can be found in upstream caches.
|
||||
cross = mapAttrValues evalHost hosts;
|
||||
emulated = mapAttrValues
|
||||
({name, local, target}: evalHost {
|
||||
inherit name target;
|
||||
local = null;
|
||||
})
|
||||
(args: evalHost (args // { local = null; }))
|
||||
hosts;
|
||||
prefixAttrs = prefix: attrs: mapAttrs'
|
||||
(name: value: {
|
||||
@@ -165,9 +169,9 @@
|
||||
(prefixAttrs "cross-" cross) //
|
||||
(prefixAttrs "emulated-" emulated) // {
|
||||
# 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:
|
||||
inherit (cross) moby;
|
||||
inherit (cross) moby moby-light;
|
||||
};
|
||||
|
||||
# unofficial output
|
||||
@@ -187,6 +191,7 @@
|
||||
imgs = mapAttrValues (host: host.config.system.build.img) self.nixosConfigurations;
|
||||
|
||||
# unofficial output
|
||||
hostConfigs = mapAttrValues (host: host.config) 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;
|
||||
|
||||
@@ -266,9 +271,14 @@
|
||||
# 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 $@
|
||||
'';
|
||||
deployApp = host: addr: action: {
|
||||
type = "app";
|
||||
program = ''${deployScript host addr action}'';
|
||||
};
|
||||
|
||||
# pkg updating.
|
||||
# a cleaner alternative lives here: <https://discourse.nixos.org/t/how-can-i-run-the-updatescript-of-personal-packages/25274/2>
|
||||
# mkUpdater :: [ String ] -> { type = "app"; program = path; }
|
||||
mkUpdater = attrPath: {
|
||||
type = "app";
|
||||
program = let
|
||||
@@ -293,7 +303,7 @@
|
||||
} else {}
|
||||
)
|
||||
(pkgs.lib.getAttrFromPath basePath sanePkgs);
|
||||
mkUpdaters = { ignore ? [] }@opts: basePath:
|
||||
mkUpdaters = { ignore ? [], flakePrefix ? [] }@opts: basePath:
|
||||
let
|
||||
updaters = mkUpdatersNoAliases opts basePath;
|
||||
invokeUpdater = name: pkg:
|
||||
@@ -303,7 +313,7 @@
|
||||
|
||||
# in case `name` has a `.` in it, we have to quote it
|
||||
escapedPath = builtins.map (p: ''"${p}"'') fullPath;
|
||||
updatePath = builtins.concatStringsSep "." ([ "update" "pkgs" ] ++ escapedPath);
|
||||
updatePath = builtins.concatStringsSep "." (flakePrefix ++ escapedPath);
|
||||
in pkgs.lib.optionalString doUpdateByDefault (
|
||||
pkgs.lib.escapeShellArgs [
|
||||
"nix" "run" ".#${updatePath}"
|
||||
@@ -311,8 +321,9 @@
|
||||
);
|
||||
in {
|
||||
type = "app";
|
||||
# top-level app just invokes the updater of everything one layer below it
|
||||
program = builtins.toString (pkgs.writeShellScript
|
||||
(builtins.concatStringsSep "-" (["update"] ++ basePath))
|
||||
(builtins.concatStringsSep "-" (flakePrefix ++ basePath))
|
||||
(builtins.concatStringsSep
|
||||
"\n"
|
||||
(pkgs.lib.mapAttrsToList invokeUpdater updaters)
|
||||
@@ -332,7 +343,7 @@
|
||||
- `nix run '.#update.feeds'`
|
||||
- updates metadata for all feeds
|
||||
- `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'`
|
||||
- make sure all systems build; NUR evaluates
|
||||
|
||||
@@ -346,29 +357,27 @@
|
||||
nix flake show --option allow-import-from-derivation true
|
||||
'');
|
||||
};
|
||||
update.pkgs = mkUpdaters { ignore = [ ["feeds"] ]; } [];
|
||||
update.feeds = mkUpdaters {} [ "feeds" ];
|
||||
# wrangle some names to get package updaters which refer back into the flake, but also conditionally ignore certain paths (e.g. sane.feeds).
|
||||
# TODO: better design
|
||||
update = rec {
|
||||
_impl.pkgs.sane = mkUpdaters { flakePrefix = [ "update" "_impl" "pkgs" ]; ignore = [ [ "sane" "feeds" ] ]; } [ "sane" ];
|
||||
pkgs = _impl.pkgs.sane;
|
||||
_impl.feeds.sane.feeds = mkUpdaters { flakePrefix = [ "update" "_impl" "feeds" ]; } [ "sane" "feeds" ];
|
||||
feeds = _impl.feeds.sane.feeds;
|
||||
};
|
||||
|
||||
init-feed = {
|
||||
type = "app";
|
||||
program = "${pkgs.feeds.init-feed}";
|
||||
};
|
||||
|
||||
deploy-lappy = {
|
||||
type = "app";
|
||||
program = ''${deployScript "lappy" "lappy" "switch"}'';
|
||||
};
|
||||
deploy-moby-test = {
|
||||
type = "app";
|
||||
program = ''${deployScript "moby" "moby-hn" "test"}'';
|
||||
};
|
||||
deploy-moby = {
|
||||
type = "app";
|
||||
program = ''${deployScript "moby" "moby-hn" "switch"}'';
|
||||
};
|
||||
deploy-servo = {
|
||||
type = "app";
|
||||
program = ''${deployScript "servo" "servo" "switch"}'';
|
||||
deploy = {
|
||||
lappy = deployApp "lappy" "lappy" "switch";
|
||||
lappy-light = deployApp "lappy-light" "lappy" "switch";
|
||||
moby = deployApp "moby" "moby" "switch";
|
||||
moby-light = deployApp "moby-light" "moby" "switch";
|
||||
moby-test = deployApp "moby" "moby" "test";
|
||||
servo = deployApp "servo" "servo" "switch";
|
||||
};
|
||||
|
||||
sync-moby = {
|
||||
@@ -427,18 +436,27 @@
|
||||
check.host-configs = {
|
||||
type = "app";
|
||||
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 $@
|
||||
RC_${host}=$?
|
||||
RC_${shellHost}=$?
|
||||
'';
|
||||
in builtins.toString (pkgs.writeShellScript
|
||||
"check-host-configs"
|
||||
''
|
||||
# build minimally-usable hosts first, then their full image.
|
||||
# this gives me a minimal image i can deploy or copy over, early.
|
||||
${checkHost "desko-light"}
|
||||
${checkHost "moby-light"}
|
||||
${checkHost "lappy-light"}
|
||||
|
||||
${checkHost "desko"}
|
||||
${checkHost "lappy"}
|
||||
${checkHost "servo"}
|
||||
${checkHost "moby"}
|
||||
${checkHost "rescue"}
|
||||
|
||||
echo "desko: $RC_desko"
|
||||
echo "lappy: $RC_lappy"
|
||||
echo "servo: $RC_servo"
|
||||
|
@@ -11,23 +11,29 @@
|
||||
|
||||
sops.secrets.colin-passwd.neededForUsers = true;
|
||||
|
||||
sane.ports.openFirewall = true; # for e.g. nix-serve
|
||||
|
||||
sane.roles.build-machine.enable = true;
|
||||
sane.roles.ac = true;
|
||||
sane.roles.client = true;
|
||||
sane.roles.dev-machine = true;
|
||||
sane.roles.pc = true;
|
||||
sane.services.wg-home.enable = true;
|
||||
sane.services.wg-home.ip = config.sane.hosts.by-name."desko".wg-home.ip;
|
||||
sane.services.duplicity.enable = true;
|
||||
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.programs.iphoneUtils.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.signal-desktop.config.autostart = true;
|
||||
sane.programs."gnome.geary".config.autostart = true;
|
||||
|
||||
boot.loader.efi.canTouchEfiVariables = false;
|
||||
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.
|
||||
# a cross-compiled kernel, particularly, will easily use 30+GB of tmp
|
||||
fileSystems."/tmp".options = [ "size=64G" ];
|
||||
|
||||
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";
|
||||
options = [
|
||||
"compress=zstd"
|
||||
@@ -17,8 +16,8 @@
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
sane.roles.client = true;
|
||||
sane.roles.dev-machine = true;
|
||||
sane.roles.pc = true;
|
||||
sane.services.wg-home.enable = true;
|
||||
sane.services.wg-home.ip = config.sane.hosts.by-name."lappy".wg-home.ip;
|
||||
|
||||
@@ -15,11 +16,7 @@
|
||||
boot.loader.efi.canTouchEfiVariables = false;
|
||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||
|
||||
sane.programs.guiApps.suggestedPrograms = [
|
||||
"desktopGuiApps"
|
||||
"stepmania"
|
||||
];
|
||||
sane.programs.consoleUtils.suggestedPrograms = [ "consoleMediaUtils" "desktopConsoleUtils" ];
|
||||
sane.programs.stepmania.enableFor.user.colin = true;
|
||||
|
||||
sops.secrets.colin-passwd.neededForUsers = true;
|
||||
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
sane.persist.root-on-tmpfs = true;
|
||||
|
||||
fileSystems."/nix" = {
|
||||
device = "/dev/disk/by-uuid/75230e56-2c69-4e41-b03e-68475f119980";
|
||||
fsType = "btrfs";
|
||||
|
@@ -33,7 +33,7 @@
|
||||
# and so it just wouldn't handle any button inputs (sxmo_hook_inputhandler.sh not on path)
|
||||
SXMO_DEVICE_NAME = "three_button_touchscreen";
|
||||
};
|
||||
package = (pkgs.sxmo-utils-latest.override { preferSystemd = true; }).overrideAttrs (base: {
|
||||
package = (pkgs.sxmo-utils.override { preferSystemd = true; }).overrideAttrs (base: {
|
||||
postPatch = (base.postPatch or "") + ''
|
||||
# after volume-button navigation mode, restore full keyboard functionality
|
||||
cp ${./xkb_mobile_normal_buttons} ./configs/xkb/xkb_mobile_normal_buttons
|
||||
|
@@ -20,6 +20,7 @@
|
||||
];
|
||||
|
||||
sane.roles.client = true;
|
||||
sane.roles.handheld = true;
|
||||
sane.zsh.showDeadlines = false; # unlikely to act on them when in shell
|
||||
sane.services.wg-home.enable = true;
|
||||
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;
|
||||
@@ -32,15 +33,12 @@
|
||||
sops.secrets.colin-passwd.neededForUsers = true;
|
||||
|
||||
sane.gui.sxmo.enable = true;
|
||||
sane.programs.guiApps.suggestedPrograms = [ "handheldGuiApps" ];
|
||||
# sane.programs.consoleUtils.enableFor.user.colin = false;
|
||||
# sane.programs.guiApps.enableFor.user.colin = false;
|
||||
sane.programs.blueberry.enableFor.user.colin = false; # bluetooth manager: doesn't cross compile!
|
||||
sane.programs.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.sequoia.enableFor.user.colin = false;
|
||||
sane.programs.tuiApps.enableFor.user.colin = false; # visidata, others, don't compile well
|
||||
# disabled for faster deploys
|
||||
sane.programs.soundconverter.enableFor.user.colin = false;
|
||||
sane.programs.nvme-cli.enableFor.system = false; # does not cross compile (libhugetlbfs)
|
||||
|
||||
# enabled for easier debugging
|
||||
sane.programs.eg25-control.enableFor.user.colin = true;
|
||||
@@ -48,6 +46,8 @@
|
||||
|
||||
# sane.programs.ntfy-sh.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.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`
|
||||
sane.programs.firefox.env = lib.mkForce {};
|
||||
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,
|
||||
# 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" = {
|
||||
device = "/dev/disk/by-uuid/1f1271f8-53ce-4081-8a29-60a4a6b5d6f9";
|
||||
fsType = "btrfs";
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
fileSystems."/" = {
|
||||
fileSystems."/nix" = {
|
||||
device = "/dev/disk/by-uuid/44445555-6666-7777-8888-999900001111";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
@@ -14,12 +14,11 @@
|
||||
signaldctl.enableFor.user.colin = true;
|
||||
};
|
||||
|
||||
sane.roles.ac = true;
|
||||
sane.roles.build-machine.enable = true;
|
||||
sane.roles.build-machine.emulation = false;
|
||||
sane.zsh.showDeadlines = false; # ~/knowledge doesn't always exist
|
||||
sane.programs.consoleUtils.suggestedPrograms = [
|
||||
"desktopConsoleUtils"
|
||||
"pcConsoleUtils"
|
||||
"sane-scripts.stop-all-servo"
|
||||
];
|
||||
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.nixcache.substituters.servo = 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
|
||||
|
||||
# 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.
|
||||
# even the stock `nixpkgs.linux` consumes > 16 GB of tmp
|
||||
fileSystems."/tmp".options = [ "size=32G" ];
|
||||
@@ -69,7 +68,7 @@
|
||||
the contents should be a subset of what's in ../media/datasets.
|
||||
'';
|
||||
# make sure large media is stored to the HDD
|
||||
sane.persist.sys.ext = [
|
||||
sane.persist.sys.byStore.ext = [
|
||||
{
|
||||
user = "colin";
|
||||
group = "users";
|
||||
|
@@ -18,6 +18,7 @@
|
||||
./komga.nix
|
||||
./lemmy.nix
|
||||
./matrix
|
||||
./monero.nix
|
||||
./navidrome.nix
|
||||
./nginx.nix
|
||||
./nixserve.nix
|
||||
@@ -26,6 +27,7 @@
|
||||
./pleroma.nix
|
||||
./postgres.nix
|
||||
./prosody
|
||||
./slskd.nix
|
||||
./transmission.nix
|
||||
./trust-dns.nix
|
||||
./wikipedia.nix
|
||||
|
@@ -29,7 +29,7 @@
|
||||
# - `sudo btrfs qgroup limit 20G /mnt/persist/ext/persist/var/export/playground`
|
||||
# to query the quota/status:
|
||||
# - `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"; }
|
||||
];
|
||||
|
||||
|
@@ -13,6 +13,10 @@
|
||||
services.gitea.appName = "Perfectly Sane Git";
|
||||
# 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
|
||||
users.users.git = {
|
||||
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.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
|
||||
services.trust-dns.settings.listen_addrs_ipv6 = [];
|
||||
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;
|
||||
|
||||
sane.ports.ports."53" = {
|
||||
|
@@ -5,6 +5,7 @@
|
||||
./fs.nix
|
||||
./hardware
|
||||
./home
|
||||
./hostnames.nix
|
||||
./hosts.nix
|
||||
./ids.nix
|
||||
./machine-id.nix
|
||||
@@ -21,25 +22,46 @@
|
||||
sane.nixcache.enable-trusted-keys = true;
|
||||
sane.nixcache.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.consoleUtils.enableFor.user.colin = lib.mkDefault true;
|
||||
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
nixpkgs.config.allowBroken = true; # NIXPKGS_ALLOW_BROKEN
|
||||
nixpkgs.config.allowUnfree = true; # NIXPKGS_ALLOW_UNFREE=1
|
||||
nixpkgs.config.allowBroken = true; # NIXPKGS_ALLOW_BROKEN=1
|
||||
|
||||
# time.timeZone = "America/Los_Angeles";
|
||||
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 = ''
|
||||
# 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
|
||||
# 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.
|
||||
# unclear _when_ this occurs. it's not a service.
|
||||
# does the daemon continually scan the nix store?
|
||||
# does the builder use some content-addressed db to efficiently dedupe?
|
||||
nix.settings.auto-optimise-store = true;
|
||||
# TODO: see if i can remove this?
|
||||
nix.settings.trusted-users = [ "root" ];
|
||||
|
||||
services.journald.extraConfig = ''
|
||||
# docs: `man journald.conf`
|
||||
|
@@ -77,6 +77,7 @@ let
|
||||
(fromDb "feeds.simplecast.com/82FI35Px" // pol) # Ezra Klein Show
|
||||
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat) # Econ Talk
|
||||
(fromDb "feeds.simplecast.com/xKJ93w_w" // uncat) # Atlas Obscura
|
||||
(fromDb "feeds.simplecast.com/l2i9YnTd" // tech // pol) # Hard Fork (NYtimes tech)
|
||||
(fromDb "feeds.transistor.fm/acquired" // tech)
|
||||
(fromDb "lexfridman.com/podcast" // rat)
|
||||
(fromDb "mapspodcast.libsyn.com" // uncat) # Multidisciplinary Association for Psychedelic Studies
|
||||
@@ -136,10 +137,12 @@ let
|
||||
# DEVELOPERS
|
||||
(fromDb "blog.jmp.chat" // tech)
|
||||
(fromDb "uninsane.org" // tech)
|
||||
(fromDb "blog.thalheim.io" // tech) # Mic92
|
||||
(fromDb "ascii.textfiles.com" // tech) # Jason Scott
|
||||
(fromDb "xn--gckvb8fzb.com" // tech)
|
||||
(fromDb "amosbbatto.wordpress.com" // tech)
|
||||
(fromDb "fasterthanli.me" // tech)
|
||||
(fromDb "jeffgeerling.com" // tech)
|
||||
(fromDb "mg.lol" // tech)
|
||||
# (fromDb "drewdevault.com" // tech)
|
||||
## Ken Shirriff
|
||||
|
@@ -12,8 +12,9 @@
|
||||
copy_bin_and_libs ${pkgs.util-linux}/bin/{cfdisk,lsblk,lscpu}
|
||||
copy_bin_and_libs ${pkgs.gptfdisk}/bin/{cgdisk,gdisk}
|
||||
copy_bin_and_libs ${pkgs.smartmontools}/bin/smartctl
|
||||
copy_bin_and_libs ${pkgs.nvme-cli}/bin/nvme
|
||||
copy_bin_and_libs ${pkgs.e2fsprogs}/bin/resize2fs
|
||||
'' + lib.optionalString pkgs.stdenv.hostPlatform.isx86_64 ''
|
||||
copy_bin_and_libs ${pkgs.nvme-cli}/bin/nvme # doesn't cross compile
|
||||
'';
|
||||
boot.kernelParams = [
|
||||
"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";
|
||||
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.ntfy-sh.uid = 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.guest.uid = 1100;
|
||||
@@ -63,6 +67,8 @@
|
||||
sane.ids.systemd-oom.uid = 2005;
|
||||
sane.ids.systemd-oom.gid = 2005;
|
||||
sane.ids.wireshark.gid = 2006;
|
||||
sane.ids.nixremote.uid = 2007;
|
||||
sane.ids.nixremote.gid = 2007;
|
||||
|
||||
# found on graphical hosts
|
||||
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
|
||||
@@ -10,4 +10,7 @@
|
||||
# to avoid switching so much during development
|
||||
"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.dev" = declPackageSet [
|
||||
"sane-scripts.clone"
|
||||
"sane-scripts.dev-cargo-loop"
|
||||
"sane-scripts.git-init"
|
||||
];
|
||||
@@ -41,7 +42,6 @@ in
|
||||
"sane-scripts.secrets-unlock"
|
||||
"sane-scripts.secrets-update-keys"
|
||||
"sane-scripts.shutdown"
|
||||
"sane-scripts.ssl-dump"
|
||||
"sane-scripts.sudo-redirect"
|
||||
"sane-scripts.sync-from-servo"
|
||||
"sane-scripts.vpn"
|
||||
@@ -109,6 +109,7 @@ in
|
||||
"util-linux" # lsblk, lscpu, etc
|
||||
"wget"
|
||||
"wirelesstools" # iwlist
|
||||
"xq" # jq for XML
|
||||
];
|
||||
sysadminExtraUtils = declPackageSet [
|
||||
"backblaze-b2"
|
||||
@@ -172,7 +173,7 @@ in
|
||||
"zsh"
|
||||
];
|
||||
|
||||
desktopConsoleUtils = declPackageSet [
|
||||
pcConsoleUtils = declPackageSet [
|
||||
"gh" # MS GitHub cli
|
||||
"nix-index"
|
||||
"nixpkgs-review"
|
||||
@@ -187,11 +188,11 @@ in
|
||||
"yt-dlp"
|
||||
];
|
||||
|
||||
tuiApps = declPackageSet [
|
||||
pcTuiApps = declPackageSet [
|
||||
"aerc" # email client
|
||||
"msmtp" # sendmail
|
||||
"offlineimap" # email mailbox sync
|
||||
"sfeed" # RSS fetcher
|
||||
# "sfeed" # RSS fetcher
|
||||
"visidata" # TUI spreadsheet viewer/editor
|
||||
"w3m" # web browser
|
||||
];
|
||||
@@ -221,6 +222,8 @@ in
|
||||
# creds, but also 200 MB of node modules, etc
|
||||
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.
|
||||
# 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.
|
||||
@@ -237,6 +240,8 @@ in
|
||||
# TODO: we can populate gh's stuff statically; it even lets us use the same oauth across machines
|
||||
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.private = [ ".local/share/maps-places.json" ];
|
||||
|
||||
@@ -253,16 +258,21 @@ in
|
||||
requests
|
||||
]);
|
||||
|
||||
# creds, media
|
||||
signal-desktop.persist.byStore.private = [ ".config/Signal" ];
|
||||
shattered-pixel-dungeon.persist.byStore.plaintext = [ ".local/share/.shatteredpixel/shattered-pixel-dungeon" ];
|
||||
|
||||
# printer/filament settings
|
||||
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" ];
|
||||
|
||||
tokodon.persist.byStore.private = [ ".cache/KDE/tokodon" ];
|
||||
|
||||
vvvvvv.persist.byStore.plaintext = [ ".local/share/VVVVVV" ];
|
||||
|
||||
whalebird.persist.byStore.private = [ ".config/Whalebird" ];
|
||||
|
||||
yarn.persist.byStore.plaintext = [ ".cache/yarn" ];
|
||||
|
@@ -1,14 +1,34 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!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
|
||||
bat_dis=""
|
||||
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() {
|
||||
# args: <battery symbol> <text if ludicrous estimate> <estimated minutes to full/empty>
|
||||
if [[ $3 -gt 1440 ]]; then
|
||||
@@ -27,6 +47,6 @@ if [[ $rate -lt 0 ]]; then
|
||||
elif [[ $rate -gt 0 ]]; then
|
||||
# charging
|
||||
fmt_minutes "$bat_chg" '100%' "$(($full * 60 * $perc_left / (100 * $rate)))"
|
||||
else
|
||||
elif [[ "$perc" != "" ]]; then
|
||||
echo "$bat_dis $perc%"
|
||||
fi
|
||||
|
@@ -2,8 +2,10 @@
|
||||
|
||||
{
|
||||
imports = [
|
||||
./abaddon.nix
|
||||
./aerc.nix
|
||||
./alacritty.nix
|
||||
./animatch.nix
|
||||
./assorted.nix
|
||||
./bemenu.nix
|
||||
./brave.nix
|
||||
@@ -12,6 +14,7 @@
|
||||
./chatty.nix
|
||||
./conky
|
||||
./cozy.nix
|
||||
./dialect.nix
|
||||
./dino.nix
|
||||
./element-desktop.nix
|
||||
./epiphany.nix
|
||||
@@ -31,6 +34,7 @@
|
||||
./gnome-weather.nix
|
||||
./gpodder.nix
|
||||
./gthumb.nix
|
||||
./gtkcord4.nix
|
||||
./helix.nix
|
||||
./imagemagick.nix
|
||||
./jellyfin-media-player.nix
|
||||
@@ -55,16 +59,22 @@
|
||||
./rhythmbox.nix
|
||||
./ripgrep.nix
|
||||
./sfeed.nix
|
||||
./signal-desktop.nix
|
||||
./splatmoji.nix
|
||||
./spot.nix
|
||||
./spotify.nix
|
||||
./steam.nix
|
||||
./stepmania.nix
|
||||
./sublime-music.nix
|
||||
./supertuxkart.nix
|
||||
./sway-autoscaler
|
||||
./swaynotificationcenter.nix
|
||||
./tangram.nix
|
||||
./tor-browser-bundle-bin.nix
|
||||
./tuba.nix
|
||||
./vlc.nix
|
||||
./wike.nix
|
||||
./wine.nix
|
||||
./wireshark.nix
|
||||
./xarchiver.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" ];
|
||||
|
||||
services.dino = {
|
||||
description = "auto-start and maintain dino XMPP connection";
|
||||
description = "dino XMPP client";
|
||||
wantedBy = lib.mkIf cfg.config.autostart [ "default.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.package}/bin/dino";
|
||||
|
@@ -4,9 +4,14 @@
|
||||
# - <https://github.com/vector-im/element-desktop/issues/1029#issuecomment-1632688224>
|
||||
# - `rm -rf ~/.config/Element/GPUCache`
|
||||
# - <https://github.com/NixOS/nixpkgs/issues/244486>
|
||||
{ ... }:
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
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
|
||||
persist.byStore.private = [ ".config/Element" ];
|
||||
|
||||
|
@@ -13,7 +13,14 @@ let
|
||||
mobile-prefs = lib.optionals false pkgs.librewolf-pmos-mobile.extraPrefsFiles;
|
||||
# allow easy switching between firefox and librewolf with `defaultSettings`, below
|
||||
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;
|
||||
libName = "librewolf";
|
||||
dotDir = ".librewolf";
|
||||
@@ -229,7 +236,8 @@ in
|
||||
// scrollbar configuration, see: <https://artemis.sh/2023/10/12/scrollbars.html>
|
||||
// style=4 gives rectangular scrollbars
|
||||
// could also enable "always show scrollbars" in about:preferences -- not sure what the actual pref name for that is
|
||||
defaultPref("widget.non-native-theme.scrollbar.size.override", 50);
|
||||
// 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);
|
||||
'';
|
||||
fs."${cfg.browser.dotDir}/default".dir = {};
|
||||
|
@@ -41,6 +41,7 @@ in
|
||||
# XXX by default fractal stores its state in ~/.local/share/<build-profile>/<UUID>.
|
||||
".local/share/hack" # for debug-like builds
|
||||
".local/share/stable" # for normal releases
|
||||
".local/share/fractal" # for version 5+, i think?
|
||||
];
|
||||
|
||||
suggestedPrograms = [ "gnome-keyring" ];
|
||||
|
@@ -3,9 +3,23 @@
|
||||
# - it uses webkitgtk_4_1, which is expensive to build.
|
||||
# could be upgraded to webkitgtk latest if upgraded to gtk4
|
||||
# <https://gitlab.gnome.org/GNOME/geary/-/issues/1212>
|
||||
{ ... }:
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.sane.programs."gnome.geary";
|
||||
in
|
||||
{
|
||||
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 = [
|
||||
# attachments, and email -- contained in a sqlite db
|
||||
".local/share/geary"
|
||||
@@ -51,5 +65,18 @@
|
||||
transport_security=transport
|
||||
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-fresh;
|
||||
|
||||
slowToBuild = true;
|
||||
|
||||
# disable first-run stuff
|
||||
fs.".config/libreoffice/4/user/registrymodifications.xcu".symlink.text = ''
|
||||
<?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.associations."audio/flac" = "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."video/mp4" = "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;
|
||||
in
|
||||
{
|
||||
# private because there could be sensitive things in the swap
|
||||
sane.programs.neovim = {
|
||||
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";
|
||||
};
|
||||
|
||||
programs.neovim = mkIf config.sane.programs.neovim.enabled {
|
||||
# neovim: https://github.com/neovim/neovim
|
||||
enable = true;
|
||||
# package = config.programs.neovim.finalPackage;
|
||||
package = pkgs.wrapNeovimUnstable pkgs.neovim-unwrapped (pkgs.neovimUtils.makeNeovimConfig {
|
||||
withRuby = false; #< doesn't cross-compile w/o binfmt
|
||||
viAlias = true;
|
||||
vimAlias = true;
|
||||
configure = {
|
||||
packages.plugins = {
|
||||
start = plugin-packages;
|
||||
};
|
||||
plugins = plugin-packages;
|
||||
customRC = ''
|
||||
" 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>
|
||||
@@ -147,6 +133,16 @@ in
|
||||
${plugin-config-lua}
|
||||
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: {
|
||||
# allow toggle buttons:
|
||||
patches = (upstream.patches or []) ++ [
|
||||
# (pkgs.fetchpatch {
|
||||
# url = "https://github.com/ErikReider/SwayNotificationCenter/pull/304.patch";
|
||||
# name = "Add toggle button";
|
||||
# hash = "sha256-bove2EXc5FZ5nN1X1FYOn3czCgHG03ibIAupJNoctiM=";
|
||||
# })
|
||||
(pkgs.fetchpatch {
|
||||
url = "https://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";
|
||||
hash = "sha256-bove2EXc5FZ5nN1X1FYOn3czCgHG03ibIAupJNoctiM=";
|
||||
})
|
||||
@@ -145,11 +152,14 @@ in
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
button {
|
||||
.widget-buttons-grid>flowbox>flowboxchild>button.toggle {
|
||||
/* text color for inactive buttons, and "Clear All" button.*/
|
||||
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);
|
||||
background-color: rgb(0, 110, 190);
|
||||
}
|
||||
@@ -208,12 +218,18 @@ in
|
||||
# - SWAYNC_REPLACES_ID
|
||||
# - SWAYNC_ID
|
||||
# - SWAYNC_SUMMARY
|
||||
incoming-im = {
|
||||
incoming-im-known-app-name = {
|
||||
# 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
|
||||
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 = {
|
||||
app-name = "Dino";
|
||||
body = "^Incoming call$";
|
||||
@@ -318,22 +334,22 @@ in
|
||||
lib.optionals config.sane.programs.eg25-control.enabled [
|
||||
{
|
||||
type = "toggle";
|
||||
label = "gps";
|
||||
label = ""; # GPS services; other icons: 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";
|
||||
}
|
||||
{
|
||||
type = "toggle";
|
||||
label = "5g";
|
||||
label = ""; # icons: 5g, 📡, 📱, ᯤ, ⚡, , 🌐, 📶, 🗼, , , ,
|
||||
# modem and NetworkManager auto-establishes a connection when powered.
|
||||
# though some things like `wg-home` VPN tunnel will remain routed over the old interface.
|
||||
command = "/run/wrappers/bin/sudo ${systemctl-toggle}/bin/systemctl-toggle eg25-control-powered";
|
||||
active = "${pkgs.systemd}/bin/systemctl is-active eg25-control-powered.service";
|
||||
}
|
||||
] ++ [
|
||||
] ++ lib.optionals false [
|
||||
{
|
||||
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";
|
||||
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";
|
||||
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 [
|
||||
{
|
||||
type = "toggle";
|
||||
|
@@ -27,6 +27,8 @@ in
|
||||
'' + (upstream.preFixup or "");
|
||||
});
|
||||
|
||||
slowToBuild = true; # only true for cross-compiled tangram
|
||||
|
||||
persist.byStore.private = [
|
||||
".cache/Tangram"
|
||||
".local/share/Tangram"
|
||||
|
@@ -1,26 +1,6 @@
|
||||
{ pkgs, ... }:
|
||||
{ ... }:
|
||||
{
|
||||
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" ];
|
||||
};
|
||||
}
|
||||
|
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, ... }:
|
||||
{
|
||||
sane.programs.wireshark.slowToBuild = true;
|
||||
|
||||
programs.wireshark.enable = config.sane.programs.wireshark.enabled;
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ in {
|
||||
sane.programs.zeal = {
|
||||
# package = pkgs.zeal-qt6; #< TODO: upgrade system to qt6 versions of everything (i.e. jellyfin-media-player, nheko)
|
||||
package = pkgs.zeal-qt5;
|
||||
slowToBuild = true;
|
||||
persist.byStore.plaintext = [
|
||||
".cache/Zeal"
|
||||
".local/share/Zeal"
|
||||
|
@@ -67,6 +67,8 @@ in
|
||||
'' + ''
|
||||
|
||||
HISTFILE="$HOME/.local/share/zsh/history"
|
||||
HISTSIZE=1000000
|
||||
SAVEHIST=1000000
|
||||
|
||||
# auto-cd into any of these dirs by typing them and pressing 'enter':
|
||||
hash -d 3rd="/home/colin/dev/3rd"
|
||||
@@ -105,18 +107,19 @@ in
|
||||
# common typos
|
||||
"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`
|
||||
"l" = "eza --oneline"; # show one entry per line
|
||||
"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 = [
|
||||
# docs: `man zshoptions`
|
||||
# nixos defaults:
|
||||
"HIST_FCNTL_LOCK"
|
||||
"HIST_IGNORE_DUPS"
|
||||
"HIST_EXPIRE_DUPS_FIRST"
|
||||
"SHARE_HISTORY"
|
||||
# customizations:
|
||||
"AUTO_CD" # type directory name to go there
|
||||
@@ -148,6 +151,11 @@ in
|
||||
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() {
|
||||
sudo nixos-rebuild --flake . switch --keep-going;
|
||||
}
|
||||
|
@@ -1,45 +1,25 @@
|
||||
{ config, lib, sane-data, sane-lib, ... }:
|
||||
{ config, lib, sane-lib, ... }:
|
||||
|
||||
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
|
||||
{
|
||||
sane.ssh.pubkeys =
|
||||
let
|
||||
# path is a DNS-style path like [ "org" "uninsane" "root" ]
|
||||
keyNameForPath = path:
|
||||
let
|
||||
rev = lib.reverseList path;
|
||||
name = head rev;
|
||||
host = lib.concatStringsSep "." (tail rev);
|
||||
in
|
||||
"${name}@${host}";
|
||||
sane.ssh.pubkeys = lib.mkMerge (hostKeys ++ [
|
||||
{
|
||||
"root@uninsane.org" = config.sane.hosts.by-name.servo.ssh.host_pubkey;
|
||||
"root@git.uninsane.org" = config.sane.hosts.by-name.servo.ssh.host_pubkey;
|
||||
|
||||
# [{ path :: [String], value :: String }] for the keys we want to install
|
||||
globalKeys = sane-lib.flattenAttrs sane-data.keys;
|
||||
|
||||
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)
|
||||
);
|
||||
# documented here: <https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints>
|
||||
# Github actually uses multiple keys -- one per format
|
||||
"root@github.com" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl";
|
||||
}
|
||||
]);
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
|
@@ -6,8 +6,6 @@
|
||||
# sets group to "users" (?)
|
||||
isNormalUser = true;
|
||||
home = "/home/colin";
|
||||
createHome = true;
|
||||
homeMode = "0700";
|
||||
# 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.
|
||||
subUidRanges = [
|
||||
|
@@ -1,4 +1,4 @@
|
||||
{ ... }:
|
||||
{ config, ... }:
|
||||
{
|
||||
sane.persist.sys.byStore.cryptClearOnBoot = [
|
||||
# when running commands as root, some things may create ~/.cache entries.
|
||||
|
@@ -4,7 +4,6 @@
|
||||
imports = [
|
||||
./derived-secrets
|
||||
./gui
|
||||
./hostnames.nix
|
||||
./hosts.nix
|
||||
./nixcache.nix
|
||||
./roles
|
||||
|
@@ -1,4 +1,10 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
declPackageSet = pkgs: {
|
||||
package = null;
|
||||
suggestedPrograms = pkgs;
|
||||
};
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./gnome.nix
|
||||
@@ -10,24 +16,51 @@
|
||||
./theme
|
||||
];
|
||||
|
||||
sane.programs.guiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = lib.optionals (pkgs.system == "x86_64-linux") [
|
||||
"x86GuiApps"
|
||||
] ++ [
|
||||
sane.programs.gameApps = declPackageSet [
|
||||
"animatch"
|
||||
"gnome-2048"
|
||||
"gnome.hitori" # like sudoku
|
||||
"superTux" # keyboard-only controls
|
||||
"superTuxKart" # poor FPS on pinephone
|
||||
];
|
||||
sane.programs.pcGameApps = declPackageSet [
|
||||
# "andyetitmoves" # TODO: fix build!
|
||||
# "armagetronad" # tron/lightcycles; WAN and LAN multiplayer
|
||||
# "cutemaze" # meh: trivial maze game; qt6 and keyboard-only
|
||||
# "cuyo" # trivial puyo-puyo clone
|
||||
"endless-sky" # space merchantilism/exploration
|
||||
# "factorio"
|
||||
"frozen-bubble" # WAN + LAN + 1P/2P bubble bobble
|
||||
"hase" # WAN worms game
|
||||
# "hedgewars" # WAN + LAN worms game (5~10 people online at any moment; <https://hedgewars.org>)
|
||||
# "libremines" # meh: trivial minesweeper; qt6
|
||||
# "mario0" # SMB + portal
|
||||
# "mindustry"
|
||||
# "minesweep-rs" # CLI minesweeper
|
||||
# "nethack"
|
||||
# "osu-lazer"
|
||||
# "pinball" # 3d pinball; kb/mouse. old sourceforge project
|
||||
# "powermanga" # STYLISH space invaders derivative (keyboard-only)
|
||||
"shattered-pixel-dungeon" # doesn't cross compile
|
||||
"space-cadet-pinball" # LMB/RMB controls (bindable though. volume buttons?)
|
||||
"tumiki-fighters" # keyboard-only
|
||||
"vvvvvv" # keyboard-only controls
|
||||
"wine"
|
||||
];
|
||||
|
||||
sane.programs.guiApps = declPackageSet [
|
||||
# package sets
|
||||
"tuiApps"
|
||||
] ++ [
|
||||
"gameApps"
|
||||
"guiBaseApps"
|
||||
];
|
||||
|
||||
sane.programs.guiBaseApps = declPackageSet [
|
||||
"abaddon" # discord client
|
||||
"alacritty" # terminal emulator
|
||||
"calls" # gnome calls (dialer/handler)
|
||||
# "celluloid" # mpv frontend
|
||||
"chatty" # matrix/xmpp/irc client
|
||||
"cozy" # audiobook player
|
||||
"dialect" # language translation
|
||||
"dino" # XMPP client
|
||||
# "emote"
|
||||
"epiphany" # gnome's web browser
|
||||
"evince" # works on phosh
|
||||
"firefox"
|
||||
# "flare-signal" # gtk4 signal client
|
||||
# "foliate" # e-book reader
|
||||
"fractal" # matrix client
|
||||
@@ -35,16 +68,17 @@
|
||||
# "gnome.cheese"
|
||||
# "gnome-feeds" # RSS reader (with claimed mobile support)
|
||||
# "gnome.file-roller"
|
||||
"gnome.geary" # adaptive e-mail client
|
||||
"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"
|
||||
"gpodder"
|
||||
"gthumb"
|
||||
"komikku"
|
||||
"koreader"
|
||||
# "gtkcord4" # Discord client. 2023/11/21: disabled because it leaks memory
|
||||
"lemoa" # lemmy app
|
||||
# "lollypop"
|
||||
"mate.engrampa" # archive manager
|
||||
@@ -56,9 +90,9 @@
|
||||
"pavucontrol"
|
||||
# "picard" # music tagging
|
||||
# "libsForQt5.plasmatube" # Youtube player
|
||||
"soundconverter"
|
||||
"signal-desktop"
|
||||
"spot" # Gnome Spotfy client
|
||||
# "sublime-music"
|
||||
"tangram" # web browser
|
||||
# "tdesktop" # broken on phosh
|
||||
# "tokodon"
|
||||
"tuba" # mastodon/pleroma client (stores pw in keyring)
|
||||
@@ -66,18 +100,38 @@
|
||||
"xdg-terminal-exec"
|
||||
"xterm" # broken on phosh
|
||||
];
|
||||
};
|
||||
|
||||
sane.programs.desktopGuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = [
|
||||
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"
|
||||
"blanket" # ambient noise generator
|
||||
"brave" # for the integrated wallet -- as a backup
|
||||
# "cantata" # music player (mpd frontend)
|
||||
# "chromium" # chromium takes hours to build. brave is chromium-based, distributed in binary form, so prefer it.
|
||||
"discord" # x86-only
|
||||
"electrum"
|
||||
"element-desktop"
|
||||
"firefox"
|
||||
"font-manager"
|
||||
# "gajim" # XMPP client. cross build tries to import host gobject-introspection types (2023/09/01)
|
||||
"gimp" # broken on phosh
|
||||
@@ -87,50 +141,29 @@
|
||||
"gnome.nautilus" # file browser
|
||||
# "gnome.totem" # video player, supposedly supports UPnP
|
||||
"handbrake"
|
||||
"hase"
|
||||
"inkscape"
|
||||
# "jellyfin-media-player"
|
||||
"kdenlive"
|
||||
"kid3" # audio tagging
|
||||
"krita"
|
||||
"libreoffice" # TODO: replace with an office suite that uses saner packaging?
|
||||
"losslesscut-bin" # x86-only
|
||||
"makemkv" # x86-only
|
||||
"monero-gui" # x86-only
|
||||
"mumble"
|
||||
"nheko"
|
||||
# "nheko" # Matrix chat client
|
||||
# "obsidian"
|
||||
# "rhythmbox" # local music player
|
||||
"slic3r"
|
||||
"soundconverter"
|
||||
"spotify" # x86-only
|
||||
"steam"
|
||||
"tor-browser-bundle-bin" # x86-only
|
||||
"vlc"
|
||||
"wireshark" # could maybe ship the cli as sysadmin pkg
|
||||
];
|
||||
};
|
||||
|
||||
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"
|
||||
];
|
||||
};
|
||||
"zecwallet-lite" # x86-only
|
||||
]
|
||||
);
|
||||
|
||||
sane.persist.sys.byStore.plaintext = lib.mkIf config.sane.programs.guiApps.enabled [
|
||||
"/var/lib/alsa" # preserve output levels, default devices
|
||||
|
@@ -14,7 +14,7 @@ let
|
||||
echo "launching sway-session (sway.desktop)..." | ${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.
|
||||
extraSessionCommands = scfg.extraSessionCommands;
|
||||
extraOptions = scfg.extraOptions;
|
||||
@@ -22,7 +22,7 @@ let
|
||||
withGtkWrapper = scfg.wrapperFeatures.gtk;
|
||||
isNixOS = true;
|
||||
# TODO: `enableXWayland = ...`?
|
||||
});
|
||||
};
|
||||
desktop-file = pkgs.runCommand "sway-desktop-wrapper" {} ''
|
||||
mkdir -p $out/share/wayland-sessions
|
||||
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
|
||||
brightness_down_cmd = mkOption {
|
||||
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";
|
||||
};
|
||||
brightness_up_cmd = mkOption {
|
||||
|
@@ -142,20 +142,30 @@ bar {
|
||||
for_window [app_id="pinentry-.*"] floating true
|
||||
for_window [app_id="foot" title=".*sxmo/modem/.*/draft.txt.*"] resize set height 25
|
||||
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="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
|
||||
## DESKTOP
|
||||
output "Samsung Electric Company S22C300 0x00007F35" {
|
||||
output "Goldstar Company Ltd LG ULTRAWIDE 0x00004E94" {
|
||||
pos 0,0
|
||||
res 3440x1440
|
||||
}
|
||||
output "Samsung Electric Company S22C300 0x00007F35" {
|
||||
pos 3440,0
|
||||
res 1920x1080
|
||||
}
|
||||
output "Goldstar Company Ltd LG ULTRAWIDE 0x00004E94" {
|
||||
pos 1920,0
|
||||
res 3440x1440
|
||||
# projector
|
||||
output "MS Telematica TV 0x00000001" {
|
||||
pos 5360,0
|
||||
res 1920x1080
|
||||
}
|
||||
|
||||
## 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
|
||||
# - daemon based (lisgsd, idle_locker, statusbar_periodics)
|
||||
# - auto-started at login
|
||||
# - managable by `sxmo_daemons.sh`
|
||||
# - list available daemons: `sxmo_daemons.sh list`
|
||||
# - query if a daemon is active: `sxmo_daemons.sh running <my-daemon>`
|
||||
# - start daemon: `sxmo_daemons.sh start <my-daemon>`
|
||||
# - managable by `sxmo_jobs.sh`
|
||||
# - list available daemons: `sxmo_jobs.sh list`
|
||||
# - query if a daemon is active: `sxmo_jobs.sh running <my-daemon>`
|
||||
# - start daemon: `sxmo_jobs.sh start <my-daemon>`
|
||||
# - managable by `superctl`
|
||||
# - `superctl status`
|
||||
# - user hooks:
|
||||
@@ -70,7 +70,7 @@ let
|
||||
hookPkgs = {
|
||||
inputhandler = pkgs.static-nix-shell.mkBash {
|
||||
pname = "sxmo_hook_inputhandler.sh";
|
||||
pkgs = [ "coreutils" ];
|
||||
pkgs = [ "coreutils" "playerctl" "pulseaudio" ];
|
||||
src = ./hooks;
|
||||
};
|
||||
postwake = pkgs.static-nix-shell.mkBash {
|
||||
@@ -130,7 +130,7 @@ in
|
||||
};
|
||||
sane.gui.sxmo.package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.sxmo-utils-latest.override { preferSystemd = true; };
|
||||
default = pkgs.sxmo-utils.override { preferSystemd = true; };
|
||||
description = ''
|
||||
sxmo base scripts and hooks collection.
|
||||
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_UNLOCK_IDLE_TIME = mkSettingsOpt "300" "how many seconds of inactivity before locking the screen"; # lock -> screenoff happens 8s later, not configurable
|
||||
# SXMO_WM = mkSettingsOpt "sway" "sway or dwm. ordinarily initialized by sxmo_{x,w}init.sh";
|
||||
SXMO_NO_AUDIO = mkSettingsOpt "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 = {};
|
||||
@@ -250,6 +253,10 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
imports = [
|
||||
./bonsai.nix
|
||||
];
|
||||
|
||||
config = lib.mkMerge [
|
||||
{
|
||||
sane.programs.sxmoApps = {
|
||||
@@ -259,11 +266,14 @@ in
|
||||
"bemenu" # specifically to import its theming
|
||||
"sfeed" # want this here so that the user's ~/.sfeed/sfeedrc gets created
|
||||
# "superd" # make superctl (used by sxmo) be on PATH
|
||||
# "sway-autoscaler"
|
||||
];
|
||||
|
||||
persist.byStore.cryptClearOnBoot = [
|
||||
# builds to be 10's of MB per day
|
||||
# ".local/state/superd/logs"
|
||||
".local/share/sxmo/modem" # SMS
|
||||
".local/share/sxmo/notifications" # so i can see new SMS messages. not sure actually if this needs persisting or if it'll re-hydrate from modem.
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -297,7 +307,7 @@ in
|
||||
# these could be added, but i don't see much benefit.
|
||||
font = "pango:monospace 10";
|
||||
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";
|
||||
|
||||
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
|
||||
echo "sxmo_init: killing stale daemons (if active)"
|
||||
sxmo_daemons.sh stop all
|
||||
sxmo_jobs.sh stop all
|
||||
pkill bemenu
|
||||
pkill wvkbd
|
||||
pkill superd
|
||||
@@ -376,6 +386,8 @@ in
|
||||
|
||||
sane.programs.sxmoApps.enableFor.user.colin = true;
|
||||
|
||||
sane.programs.sway-autoscaler.config.defaultScale = builtins.fromJSON cfg.settings.SXMO_SWAY_SCALE;
|
||||
|
||||
# sxmo internally uses doas instead of sudo
|
||||
security.doas.enable = true;
|
||||
security.doas.wheelNeedsPassword = false;
|
||||
@@ -403,6 +415,81 @@ in
|
||||
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:
|
||||
# - profile.d/sxmo_init.sh
|
||||
# - appcfg/
|
||||
@@ -424,6 +511,7 @@ in
|
||||
# the fallout of this is that during intense lag (e.g. OOM or swapping) it can
|
||||
# start the service many times.
|
||||
# see <repo:craftyguy/superd:internal/cmd/cmd.go>
|
||||
# startTimerDuration = 100 * time.Millisecond
|
||||
# TODO: better fix may be to patch `sxmo_hook_lisgdstart.sh` and force it to behave as a singleton
|
||||
# systemd.services."dedupe-sxmo-lisgd" = {
|
||||
# description = "kill duplicate lisgd processes started by superd";
|
||||
@@ -534,18 +622,8 @@ in
|
||||
sxmo_wob = sxmoService "wob";
|
||||
sxmo-x11-status = sxmoService "status_xsetroot";
|
||||
|
||||
bonsaid = {
|
||||
description = "programmable input dispatcher";
|
||||
path = sxmoPath;
|
||||
script = ''
|
||||
${sxmoEnvSetup}
|
||||
${pkgs.coreutils}/bin/rm -f $XDG_RUNTIME_DIR/bonsai
|
||||
exec ${pkgs.bonsai}/bin/bonsaid -t $XDG_CONFIG_HOME/sxmo/bonsai_tree.json
|
||||
'';
|
||||
serviceConfig.Type = "simple";
|
||||
serviceConfig.Restart = "always";
|
||||
serviceConfig.RestartSec = "5s";
|
||||
};
|
||||
bonsaid.path = sxmoPath;
|
||||
bonsaid.script = lib.mkBefore sxmoEnvSetup;
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p coreutils
|
||||
#!nix-shell -i bash -p coreutils -p playerctl -p pulseaudio
|
||||
|
||||
# input map considerations
|
||||
# - using compound actions causes delays.
|
||||
@@ -12,28 +12,33 @@
|
||||
#
|
||||
# proposed future design:
|
||||
# - when unlocked:
|
||||
# - volup1 -> app menu
|
||||
# - voldown1 -> toggle keyboard
|
||||
# - pow1 -> volup1 -> volume up
|
||||
# - pow1 -> voldown1 -> volume down
|
||||
# - pow2 -> screen off
|
||||
# - pow3 -> kill app
|
||||
# - when locked:
|
||||
# - volup1 -> volume up
|
||||
# - voldown1 -> volume down
|
||||
# - pow1 -> screen on
|
||||
# - pow2 -> toggle player
|
||||
# benefits
|
||||
# - volup-release -> app menu
|
||||
# - volup-hold -> WM menu
|
||||
# - voldown-release -> toggle keyboard
|
||||
# - voldown-hold -> terminal
|
||||
# - pow-volup xN -> volume up
|
||||
# - pow-voldown xN -> volume down
|
||||
# - pow-x2 -> screen off
|
||||
# - pow-hold -> kill app
|
||||
# - when screenoff:
|
||||
# - volup -> volume up
|
||||
# - voldown -> volume down
|
||||
# - 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
|
||||
# - which means faster vkbd, menus, volume adjustment (when locked)
|
||||
# limitations
|
||||
# - terminal is unmapped. that could be mapped to pow1?
|
||||
# - wm menu is unmapped. but i never used that much anyway
|
||||
# - less mental load than the chording-based approach (where i hold power to adjust volume)
|
||||
# - less risk due to not chording the power button
|
||||
# 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
|
||||
VOL_INCR_1=5
|
||||
VOL_INCR_2=10
|
||||
VOL_INCR_3=15
|
||||
|
||||
# replicating the naming from upstream sxmo_hook_inputhandler.sh...
|
||||
ACTION="$1"
|
||||
@@ -53,9 +58,9 @@ handle_with() {
|
||||
# # probably not handling proximity* correctly here
|
||||
# case "$STATE" in
|
||||
# *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
|
||||
# }
|
||||
|
||||
@@ -69,7 +74,7 @@ if [ "$STATE" = "unlock" ]; then
|
||||
case "$ACTION" in
|
||||
# powerbutton_one: intentional default to no-op
|
||||
# powerbutton_two: intentional default to screenoff
|
||||
"powerbutton_three")
|
||||
"powerhold")
|
||||
# power thrice: kill active window
|
||||
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
|
||||
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")
|
||||
# volume down once: toggle keyboard
|
||||
handle_with sxmo_keyboard.sh toggle
|
||||
;;
|
||||
# voldown_two: intentionally defaulted for volume control
|
||||
"voldown_three")
|
||||
# volume down thrice: launch terminal
|
||||
|
||||
"powertoggle_volup")
|
||||
# power -> volume up: DE menu
|
||||
handle_with sxmo_wmmenu.sh
|
||||
;;
|
||||
"powertoggle_voldown")
|
||||
# power -> volume down: launch terminal
|
||||
handle_with sxmo_terminal.sh
|
||||
;;
|
||||
esac
|
||||
@@ -102,9 +106,17 @@ if [ "$STATE" = "screenoff" ]; then
|
||||
# power twice => toggle media player
|
||||
handle_with playerctl play-pause
|
||||
;;
|
||||
"powerbutton_three")
|
||||
# power once during deep sleep often gets misread as power three, so treat these same
|
||||
handle_with sxmo_state_switch.sh set unlock
|
||||
"powerhold")
|
||||
# power toggle during deep sleep often gets misread as power hold, so treat same
|
||||
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
|
||||
fi
|
||||
@@ -113,32 +125,27 @@ fi
|
||||
case "$ACTION" in
|
||||
"powerbutton_one")
|
||||
# power once => unlock
|
||||
handle_with sxmo_state_switch.sh set unlock
|
||||
handle_with sxmo_state.sh set unlock
|
||||
;;
|
||||
"powerbutton_two")
|
||||
# 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
|
||||
|
||||
"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")
|
||||
handle_with sxmo_audio.sh vol up "$VOL_INCR_2"
|
||||
;;
|
||||
"volup_three")
|
||||
handle_with sxmo_audio.sh vol up "$VOL_INCR_3"
|
||||
"voldown_one")
|
||||
handle_with pactl set-sink-volume @DEFAULT_SINK@ -"$VOL_INCR_1%"
|
||||
;;
|
||||
|
||||
"voldown_one")
|
||||
handle_with sxmo_audio.sh vol down "$VOL_INCR_1"
|
||||
# HOLD power button and tap volup/down to adjust volume
|
||||
"powerhold_volup")
|
||||
handle_with pactl set-sink-volume @DEFAULT_SINK@ +"$VOL_INCR_1%"
|
||||
;;
|
||||
"voldown_two")
|
||||
handle_with sxmo_audio.sh vol down "$VOL_INCR_2"
|
||||
;;
|
||||
"voldown_three")
|
||||
handle_with sxmo_audio.sh vol down "$VOL_INCR_3"
|
||||
"powerhold_voldown")
|
||||
handle_with pactl set-sink-volume @DEFAULT_SINK@ -"$VOL_INCR_1%"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@@ -11,7 +11,7 @@ swaymsg mode default
|
||||
sxmo_wm.sh dpms on
|
||||
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
|
||||
|
||||
|
@@ -7,11 +7,11 @@
|
||||
# Create xdg user directories, such as ~/Pictures
|
||||
xdg-user-dirs-update
|
||||
|
||||
sxmo_daemons.sh start daemon_manager
|
||||
sxmo_jobs.sh start daemon_manager
|
||||
|
||||
# Periodically update some status bar components
|
||||
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
|
||||
|
||||
# TODO: start these externally, via `wantedBy` in nix
|
||||
@@ -24,7 +24,7 @@ systemctl --user start bonsaid
|
||||
# swaymsg output '*' bg "$SXMO_BG_IMG" fill
|
||||
|
||||
# To setup initial lock state
|
||||
sxmo_state_switch.sh set unlock
|
||||
sxmo_state.sh set unlock
|
||||
|
||||
# Turn on auto-suspend
|
||||
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
|
||||
if [ -n "$SXMO_AUTOROTATE" ]; then
|
||||
# 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
|
||||
|
||||
# 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 {
|
||||
type = types.str;
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
ssh pubkey that the primary user of this machine will use when connecting to other machines.
|
||||
e.g. "ssh-ed25519 AAAA<base64>".
|
||||
|
@@ -2,6 +2,12 @@
|
||||
# if one of these hosts is offline, instead manually specify just cachix:
|
||||
# - `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:
|
||||
# - apply for community arm build box:
|
||||
# - <https://github.com/nix-community/aarch64-build-box>
|
||||
@@ -36,6 +42,18 @@ in
|
||||
nixos = 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 = {
|
||||
@@ -55,5 +73,44 @@ in
|
||||
"desko:Q7mjjqoBMgNQ5P0e63sLur65A+D4f3Sv4QiycDIKxiI="
|
||||
"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;
|
||||
# serve packages to other machines that ask for them
|
||||
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.
|
||||
# default is 32 build users, limiting us to that many concurrent jobs.
|
||||
|
@@ -1,10 +1,11 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
imports = [
|
||||
./ac.nix
|
||||
./build-machine.nix
|
||||
./client
|
||||
./dev-machine.nix
|
||||
./handheld.nix
|
||||
./pc.nix
|
||||
];
|
||||
|
||||
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;
|
||||
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.",
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [
|
||||
"https://pubsubhubbub.appspot.com/"
|
||||
],
|
||||
"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_url": "https://feeds.transistor.fm",
|
||||
"title": "ACQ2 by Acquired",
|
||||
"url": "https://feeds.transistor.fm/acq2",
|
||||
"velocity": 0.052,
|
||||
"version": "rss20"
|
||||
"velocity": 0.052
|
||||
}
|
@@ -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.",
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [],
|
||||
"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_url": "https://allinchamathjason.libsyn.com",
|
||||
"title": "All-In with Chamath, Jason, Sacks & Friedberg",
|
||||
"url": "https://allinchamathjason.libsyn.com/rss",
|
||||
"velocity": 0.124,
|
||||
"version": "rss20"
|
||||
"velocity": 0.124
|
||||
}
|
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.",
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [
|
||||
"https://pubsubhubbub.appspot.com/"
|
||||
],
|
||||
"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_url": "",
|
||||
"title": "Civboot",
|
||||
"url": "https://anchor.fm/s/34c7232c/podcast/rss",
|
||||
"velocity": 0.006,
|
||||
"version": "rss20"
|
||||
"velocity": 0.006
|
||||
}
|
@@ -1,21 +1,9 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 208377,
|
||||
"content_type": "application/xml; charset=utf-8",
|
||||
"description": "applieddivinitystudies@gmail.com",
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [],
|
||||
"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_url": "https://applieddivinitystudies.com",
|
||||
"title": "Applied Divinity Studies",
|
||||
"url": "https://www.applieddivinitystudies.com/atom.xml",
|
||||
"velocity": 0.054,
|
||||
"version": "atom10"
|
||||
"velocity": 0.048
|
||||
}
|
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",
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [],
|
||||
"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_url": "https://austinvernon.site",
|
||||
"title": "Austin Vernon",
|
||||
"url": "https://austinvernon.site/rss.xml",
|
||||
"velocity": 0.059,
|
||||
"version": "rss20"
|
||||
"velocity": 0.058
|
||||
}
|
@@ -1,21 +1,9 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 592815,
|
||||
"content_type": "application/xml; charset=utf-8",
|
||||
"description": "A free newsletter by Balaji.",
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [],
|
||||
"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_url": "https://balajis.com",
|
||||
"title": "balajis.com",
|
||||
"url": "https://balajis.com/feed",
|
||||
"velocity": 0.022,
|
||||
"version": "rss20"
|
||||
"velocity": 0.027
|
||||
}
|
@@ -1,21 +1,9 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 328802,
|
||||
"content_type": "application/rss+xml; charset=utf-8",
|
||||
"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_push": false,
|
||||
"item_count": 20,
|
||||
"last_updated": "2023-08-27T13:29:00+00:00",
|
||||
"score": 8,
|
||||
"self_url": "",
|
||||
"site_name": "Benedict Evans",
|
||||
"site_url": "https://www.ben-evans.com",
|
||||
"title": "Essays - Benedict Evans",
|
||||
"url": "https://www.ben-evans.com/benedictevans?format=rss",
|
||||
"velocity": 0.027,
|
||||
"version": "rss20"
|
||||
"velocity": 0.026
|
||||
}
|
@@ -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.",
|
||||
"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_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_url": "https://bitbashing.io",
|
||||
"title": "Bit Bashing",
|
||||
"url": "https://bitbashing.io/feed.xml",
|
||||
"velocity": 0.003,
|
||||
"version": "rss20"
|
||||
"velocity": 0.004
|
||||
}
|
@@ -1,21 +1,9 @@
|
||||
{
|
||||
"bozo": 1,
|
||||
"content_length": 436175,
|
||||
"content_type": "text/xml; charset=utf-8",
|
||||
"description": null,
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [],
|
||||
"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_url": "https://blog.danieljanus.pl",
|
||||
"title": "code \u00b7 words \u00b7 emotions: Daniel Janus\u2019s blog",
|
||||
"url": "https://blog.danieljanus.pl/atom.xml",
|
||||
"velocity": 0.01,
|
||||
"version": "atom10"
|
||||
"velocity": 0.01
|
||||
}
|
@@ -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.",
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [
|
||||
"http://pubsubhubbub.appspot.com/"
|
||||
],
|
||||
"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_url": "https://blog.dshr.org",
|
||||
"title": "DSHR's Blog",
|
||||
"url": "https://blog.dshr.org/feeds/posts/default",
|
||||
"velocity": 0.308,
|
||||
"version": "atom10"
|
||||
"velocity": 0.333
|
||||
}
|
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.",
|
||||
"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_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_url": "https://blog.rust-lang.org",
|
||||
"title": "Rust Blog",
|
||||
"url": "https://blog.rust-lang.org/feed.xml",
|
||||
"velocity": 0.114,
|
||||
"version": "atom10"
|
||||
"velocity": 0.125
|
||||
}
|
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",
|
||||
"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_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_url": "https://www.bunniestudios.com",
|
||||
"title": "bunnie's blog",
|
||||
"url": "https://www.bunniestudios.com/blog/?feed=rss2",
|
||||
"velocity": 0.076,
|
||||
"version": "rss20"
|
||||
"velocity": 0.108
|
||||
}
|
@@ -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",
|
||||
"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_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_url": "https://www.capitolhillseattle.com",
|
||||
"title": "CHS Capitol Hill Seattle News",
|
||||
"url": "https://www.capitolhillseattle.com/feed/",
|
||||
"velocity": 5.393,
|
||||
"version": "rss20"
|
||||
"velocity": 4.071
|
||||
}
|
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",
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [],
|
||||
"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_url": "https://feeds.libsyn.com",
|
||||
"title": "Congressional Dish",
|
||||
"url": "https://feeds.libsyn.com/39908/rss",
|
||||
"velocity": 0.07,
|
||||
"version": "rss20"
|
||||
"velocity": 0.07
|
||||
}
|
@@ -1,21 +1,9 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 74156,
|
||||
"content_type": "application/rss+xml; charset=utf-8",
|
||||
"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_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_url": "https://craphound.com",
|
||||
"title": "Cory Doctorow's craphound.com",
|
||||
"url": "https://craphound.com/feed/",
|
||||
"velocity": 0.046,
|
||||
"version": "rss20"
|
||||
"velocity": 0.058
|
||||
}
|
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user