Compare commits
315 Commits
staging/li
...
staging/gt
Author | SHA1 | Date | |
---|---|---|---|
cce87eb6fb | |||
9777e5f83c | |||
154711432f | |||
b8460b7524 | |||
fa427ad7ea | |||
7be7d5d938 | |||
7c5ab7d253 | |||
48adaa832e | |||
38b44a31e4 | |||
9ad72af979 | |||
2a2ce34bd8 | |||
b2e70c0210 | |||
3d4cbbf005 | |||
b18bdc4e3e | |||
2f88ba92d1 | |||
f25dbdd4d2 | |||
3da58f1d41 | |||
e519c1c629 | |||
3df165593c | |||
daabe09bb4 | |||
dfbfae90a5 | |||
ef9f62ed13 | |||
2c49dfa642 | |||
6ddc943a39 | |||
5c50243d23 | |||
556600e54b | |||
5db9c4f558 | |||
e22fb2f4f5 | |||
71971a050c | |||
ac97accd32 | |||
f391e467c2 | |||
fa5d4c467c | |||
4c5333c9ed | |||
6fdb7059e3 | |||
28f7823077 | |||
9e972d21b4 | |||
42f194f447 | |||
dbd312e9bd | |||
9be5604c40 | |||
97ce93cac6 | |||
56c637d4d3 | |||
89160f68e8 | |||
316eb59071 | |||
c19a0af6d7 | |||
038d252f7d | |||
68cda2006b | |||
ddf79e54e9 | |||
ac5e2cc023 | |||
48eece548f | |||
8e16cd6d32 | |||
6676935ee1 | |||
c09b2d0d63 | |||
f12672b197 | |||
8717a91467 | |||
b43b8a3a22 | |||
c1df32695b | |||
b98eca1d84 | |||
7bc718bf15 | |||
dbb1d16617 | |||
771f482d84 | |||
40ec4d6ce0 | |||
b90bc1058d | |||
0fcddf8970 | |||
cffb54c293 | |||
36c181c147 | |||
cdbd3c2fd8 | |||
530163c853 | |||
516459b351 | |||
05e37a4557 | |||
4006765387 | |||
db0ce6eadd | |||
f188229379 | |||
f0d7d6877b | |||
a8025550d5 | |||
acd803d5bc | |||
59111b95b3 | |||
b5feeb1792 | |||
325398ec28 | |||
9b3ee537a8 | |||
7aa0c5e3ea | |||
8c586bd0db | |||
ec0e8ce38b | |||
be0d5fd7c2 | |||
e7fadbe965 | |||
054af010bd | |||
ee5a2ff986 | |||
cb7f84e2b7 | |||
e5124fd0d6 | |||
0751e748ea | |||
afce50b56d | |||
71e0942cc2 | |||
049ded2a0d | |||
4854b8b409 | |||
55e90f531b | |||
3a6bb5a787 | |||
aae5e40e92 | |||
5d464b3c64 | |||
9b389416cd | |||
bd57bb7934 | |||
db2d4ca78e | |||
3812d935a7 | |||
bc993d1139 | |||
ec62b5f664 | |||
71e96fff18 | |||
33eaa00957 | |||
a5af1e0893 | |||
be21ac57f8 | |||
63a773d8a9 | |||
505fcf5111 | |||
f0e76ef11f | |||
cb721ac70e | |||
aae783876b | |||
5e3a8cf702 | |||
d9b9349572 | |||
b6b0e65ef6 | |||
a723d1274b | |||
d41ad9db01 | |||
d6720f3601 | |||
0b0d453916 | |||
59adddafc7 | |||
50fa70ca56 | |||
86855b0c40 | |||
931838fb0d | |||
ec3a7067b6 | |||
8cb236b0a9 | |||
5f47372f6a | |||
afe27fd9cb | |||
e8265807a9 | |||
85ecaf64e9 | |||
33b33a9237 | |||
fecd2fa7d3 | |||
74ec65c8a9 | |||
21a060d856 | |||
6249f7553c | |||
96c976a3b0 | |||
d48d3a979f | |||
ab8ee51321 | |||
74891fb2f0 | |||
f62bd83eb8 | |||
c977665214 | |||
b3a605c76b | |||
2cbd44b2b3 | |||
689c63a905 | |||
ed2480f48c | |||
7aad3a62ba | |||
1583b213f1 | |||
db851d960c | |||
fb7cb091e3 | |||
048dbc5809 | |||
bb1a2c9dcb | |||
86c8fe1466 | |||
95f6fd7082 | |||
5fb52ba38e | |||
4f8d0023ef | |||
280c4aa2e8 | |||
fd270dd0b8 | |||
8e17e2beb2 | |||
d68704474d | |||
0fa5b5bf52 | |||
9caa2a0a17 | |||
023e28fb03 | |||
bed33fae60 | |||
3b958ba356 | |||
adb6ff4c66 | |||
931c76c2e7 | |||
d95042ab65 | |||
0605094461 | |||
4eb6c1fd7d | |||
c553e74cd6 | |||
4eb6f59b01 | |||
9f55a8288d | |||
feb299eb22 | |||
b21c79a0b4 | |||
c819bc2d95 | |||
21006e52dc | |||
5562d60cbb | |||
17041384e9 | |||
9eb36441e1 | |||
0d0a9fce6a | |||
847e618dee | |||
c4e345e2e7 | |||
c75719e751 | |||
7a57cf5327 | |||
b81642ccc9 | |||
57ca3e67b3 | |||
bcca6b6096 | |||
79772d4e3d | |||
339c0a47ab | |||
b1be78529b | |||
cce53b968b | |||
1d55b98cd1 | |||
e9d45c3b31 | |||
32dde42ee2 | |||
b60986cfb8 | |||
60ef232bc0 | |||
7f7bc33be5 | |||
f52f56a34c | |||
425de71583 | |||
0bd87077c1 | |||
601bf567eb | |||
4f74078423 | |||
f170351de7 | |||
bee9dab513 | |||
16c3d4289e | |||
21e0c0d00f | |||
fdf85156bc | |||
79a7daca12 | |||
3996e1be08 | |||
8b1dbd42da | |||
a2c7edf340 | |||
9b365d1771 | |||
8cf3402be4 | |||
a92fa489cb | |||
837f20e892 | |||
3d56117d65 | |||
1724ac60e5 | |||
bf168c7f0f | |||
37cafcf610 | |||
27d2f756d2 | |||
3ab33956e4 | |||
0b71712208 | |||
f31619d9e9 | |||
61838a589f | |||
c10c887650 | |||
6df61525a1 | |||
e5ce7c02ef | |||
88e5efd1f3 | |||
e9200ffcdf | |||
ab78a36354 | |||
c92f216a5b | |||
eacd3c88d1 | |||
487fbf2236 | |||
97f93e8ec0 | |||
e1eac4ae46 | |||
44d0b4efd4 | |||
9ab85167c3 | |||
9730659f32 | |||
b45981e870 | |||
95c9b5d6a2 | |||
05f10f0115 | |||
86b15d381f | |||
ecaab07bce | |||
4fd4efa22f | |||
527585e7eb | |||
481110fefb | |||
c44f69a01f | |||
adbc2a76c3 | |||
34ed201aff | |||
4d63b81b05 | |||
e1a18cdae1 | |||
2a1d87650b | |||
4a18dfeef3 | |||
ff1aece1ed | |||
05cf5e376a | |||
855a66499f | |||
b9cc581736 | |||
0a8eee8af0 | |||
a40fc7e112 | |||
6bbb5669a6 | |||
c8d5411462 | |||
af4cfc29b1 | |||
9942025a2f | |||
04f7287781 | |||
14ae501433 | |||
46edc56a32 | |||
7907623887 | |||
c542e120ef | |||
7fcff0b6a2 | |||
32671201a4 | |||
4d2268b5f1 | |||
e5fe7c093a | |||
162f3a291c | |||
31740befbf | |||
0c610c8f1c | |||
e9dc22c1f2 | |||
75e6393680 | |||
9ca6857f4d | |||
8c30b87a94 | |||
6ffd6693cb | |||
e11fe929f4 | |||
3dcd5629a7 | |||
4cf4c38da3 | |||
e0e3c36d1b | |||
108c1d9d60 | |||
c6e16ebc13 | |||
aa60838551 | |||
d6bde02dfe | |||
d07bb03936 | |||
1ab2f42ff4 | |||
e0d20cb62a | |||
f8944c8379 | |||
ca38bb4aec | |||
287817056f | |||
5cc7ced859 | |||
4dc5378b3e | |||
fe7e440997 | |||
e4262cb0bc | |||
35c9f2bf60 | |||
13794e9eaa | |||
a33950da62 | |||
37995e23c2 | |||
66156829d9 | |||
3c40fa6982 | |||
c1ddddddc0 | |||
aae118b476 | |||
7e402ce974 | |||
5b80308074 | |||
e5c94b410f | |||
209c18cb38 | |||
616a2dd19f | |||
5b0f898c62 | |||
a541e866a1 | |||
d3eb0bee26 | |||
2ca0f6ea62 | |||
66be38bfbf |
46
TODO.md
46
TODO.md
@@ -1,4 +1,9 @@
|
||||
## BUGS
|
||||
- why i need to manually restart `wireguard-wg-ovpns` on servo periodically
|
||||
- else DNS fails
|
||||
|
||||
## REFACTORING:
|
||||
|
||||
### sops/secrets
|
||||
- attach secrets to the thing they're used by (sane.programs)
|
||||
- rework secrets to leverage `sane.fs`
|
||||
@@ -9,10 +14,15 @@
|
||||
- will make it easier to test new services?
|
||||
|
||||
### upstreaming
|
||||
- split out a trust-dns module
|
||||
- see: <https://github.com/NixOS/nixpkgs/pull/205866#issuecomment-1575753054>
|
||||
- split out a sxmo module usable by NUR consumers
|
||||
- bump nodejs version in lemmy-ui
|
||||
- add updateScripts to all my packages in nixpkgs
|
||||
- fix lightdm-mobile-greeter for newer libhandy
|
||||
- port zecwallet-lite to a from-source build
|
||||
- fix or abandon Whalebird
|
||||
- REVIEW/integrate jellyfin dataDir config: <https://github.com/NixOS/nixpkgs/pull/233617>
|
||||
- remove `libsForQt5.callPackage` broadly: <https://github.com/NixOS/nixpkgs/issues/180841>
|
||||
|
||||
|
||||
## IMPROVEMENTS:
|
||||
@@ -23,31 +33,39 @@
|
||||
- have `sane.programs` be wrapped such that they run in a cgroup?
|
||||
- at least, only give them access to the portion of the fs they *need*.
|
||||
- Android takes approach of giving each app its own user: could hack that in here.
|
||||
- **systemd-run** takes a command and runs it in a temporary scope (cgroup)
|
||||
- presumably uses the same options as systemd services
|
||||
- see e.g. <https://github.com/NixOS/nixpkgs/issues/113903#issuecomment-857296349>
|
||||
- flatpak does this, somehow
|
||||
- apparmor? SElinux? (desktop) "portals"?
|
||||
- see Spectrum OS; Alyssa Ross; etc
|
||||
- canaries for important services
|
||||
- e.g. daily email checks; daily backup checks
|
||||
- integrate `nix check` into Gitea actions?
|
||||
|
||||
### user experience
|
||||
- neovim: set up language server (lsp; rnix-lsp; nvim-lspconfig)
|
||||
- firefox/librewolf: don't show browserpass/sponsorblock/metamask "first run" on every boot
|
||||
- moby: improve gPodder launch time
|
||||
- moby: replace jellyfin-desktop with jellyfin-vue?
|
||||
- allows (maybe) to cache media for offline use
|
||||
- "newer" jellyfin client
|
||||
- not packaged for nix
|
||||
- find a nice desktop ActivityPub client
|
||||
- moby: theme GTK apps (i.e. non-adwaita styles)
|
||||
- especially, make the menubar collapsible
|
||||
- package Nix/NixOS docs for Zeal
|
||||
- install [doc-browser](https://github.com/qwfy/doc-browser)
|
||||
- this supports both dash (zeal) *and* the datasets from <https://devdocs.io> (which includes nix!)
|
||||
- install [devhelp](https://wiki.gnome.org/Apps/Devhelp) (gnome)
|
||||
- auto-mount servo
|
||||
- have xdg-open parse `<repo:...> URIs (or adjust them so that it _can_ parse)
|
||||
- `sane.programs`: auto-populate defaults with everything from `pkgs`
|
||||
- zsh: disable "command not found" corrections
|
||||
- sxmo: allow rotation to the upside-down position
|
||||
- see: <repo:mil/sxmo-utils:scripts/core/sxmo_autorotate.sh>
|
||||
- all orientations *except* upside down are supported
|
||||
- sxmo: launch with auto-rotation enabled
|
||||
- `sane.persist`: auto-create parent dirs in ~/private
|
||||
- currently if the application doesn't autocreate dirs leading to its destination, then ~/private storage fails
|
||||
- this might be why librewolf on mobile is still amnesiac
|
||||
- sane-bt-search: show details like 5.1 vs stereo, h264 vs h265
|
||||
- uninsane.org: make URLs relative to allow local use (and as offline homepage)
|
||||
- email: fix so that local mail doesn't go to junk
|
||||
- git sendmail flow adds the DKIM signatures, but gets delivered locally w/o having the sig checked, so goes into Junk
|
||||
- could change junk filter from "no DKIM success" to explicit "DKIM failed"
|
||||
|
||||
### perf
|
||||
- why does zsh take so long to init?
|
||||
- why does nixos-rebuild switch take 5 minutes when net is flakey?
|
||||
- trying to auto-mount servo?
|
||||
- something to do with systemd services restarting/stalling
|
||||
@@ -56,13 +74,13 @@
|
||||
- these use significant /tmp space.
|
||||
- either place /tmp on encrypted-cleared-at-boot storage
|
||||
- which probably causes each CPU load for the encryption
|
||||
- or have nix builds use a subdir of /tmp like /tmp/nix/...
|
||||
- and place that on non-encrypted clear-on-boot (with very lax writeback/swappiness to minimize writes)
|
||||
- **or set up encrypted swap**
|
||||
- encrypted swap could remove the need for my encrypted-cleared-at-boot stuff
|
||||
|
||||
|
||||
## NEW FEATURES:
|
||||
- add a FTP-accessible file share to servo
|
||||
- just /var/www?
|
||||
- migrate MAME cabinet to nix
|
||||
- boot it from PXE from servo?
|
||||
- enable IPv6
|
||||
|
58
flake.lock
generated
58
flake.lock
generated
@@ -1,12 +1,15 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1678901627,
|
||||
"narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=",
|
||||
"lastModified": 1687709756,
|
||||
"narHash": "sha256-Y5wKlQSkgEK2weWdOu4J3riRd+kV/VCgHsqLNTTWQ/0=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6",
|
||||
"rev": "dbabf0ca0c0c4bce6ea5eaf65af5cb694d2082c7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -36,11 +39,11 @@
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1684319086,
|
||||
"narHash": "sha256-5wwlkWqP1cQUPXp/PJsi09FkgAule5yBghngRZZbUQg=",
|
||||
"lastModified": 1687251388,
|
||||
"narHash": "sha256-E9cVlgeCvzPbA/G3mCDCzz8TdRwXyGYzIjmwcvIfghg=",
|
||||
"owner": "edolstra",
|
||||
"repo": "nix-serve",
|
||||
"rev": "e6e3d09438e803daa5374ad8edf1271289348456",
|
||||
"rev": "d6df5bd8584f37e22cff627db2fc4058a4aab5ee",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -66,27 +69,27 @@
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1684025543,
|
||||
"narHash": "sha256-hGe7S+i5je+8E/b2mOXVI9nmr038Dw+bV8e1P8xHSe0=",
|
||||
"lastModified": 1687031877,
|
||||
"narHash": "sha256-yMFcVeI+kZ6KD2QBrFPNsvBrLq2Gt//D0baHByMrjFY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c6d2f3dc0d3efd4285eebe4f8a36a47ba438138e",
|
||||
"rev": "e2e2059d19668dab1744301b8b0e821e3aae9c99",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "release-22.11",
|
||||
"ref": "release-23.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-unpatched": {
|
||||
"locked": {
|
||||
"lastModified": 1684385584,
|
||||
"narHash": "sha256-O7y0gK8OLIDqz+LaHJJyeu09IGiXlZIS3+JgEzGmmJA=",
|
||||
"lastModified": 1688049487,
|
||||
"narHash": "sha256-100g4iaKC9MalDjUW9iN6Jl/OocTDtXdeAj7pEGIRh4=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "48a0fb7aab511df92a17cf239c37f2bd2ec9ae3a",
|
||||
"rev": "4bc72cae107788bf3f24f30db2e2f685c9298dc9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -113,11 +116,11 @@
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1684032930,
|
||||
"narHash": "sha256-ueeSYDii2e5bkKrsSdP12JhkW9sqgYrUghLC8aDfYGQ=",
|
||||
"lastModified": 1687398569,
|
||||
"narHash": "sha256-e/umuIKFcFtZtWeX369Hbdt9r+GQ48moDmlTcyHWL28=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "a376127bb5277cd2c337a9458744f370aaf2e08d",
|
||||
"rev": "2ff6973350682f8d16371f8c071a304b8067f192",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -126,6 +129,21 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"uninsane-dot-org": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
@@ -134,11 +152,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1684528780,
|
||||
"narHash": "sha256-QdYxjcTCCLPv++1v9tJBL98nn/AFx0fmzlgzcLK6KRE=",
|
||||
"lastModified": 1687821285,
|
||||
"narHash": "sha256-pw0UYKG8yhW1H3nPgAhVYCzYFXYtamMh2DmF8YhtRec=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "f3747a1dad3d34880613821faf26357ba432d3d7",
|
||||
"revCount": 194,
|
||||
"rev": "ae27eb61b55b6c6d83c25384fb163df398a80265",
|
||||
"revCount": 201,
|
||||
"type": "git",
|
||||
"url": "https://git.uninsane.org/colin/uninsane"
|
||||
},
|
||||
|
36
flake.nix
36
flake.nix
@@ -23,9 +23,6 @@
|
||||
# preferably, i would rewrite the human-readable https URLs to nix-specific github: URLs with a helper,
|
||||
# but `inputs` is required to be a strict attrset: not an expression.
|
||||
inputs = {
|
||||
# <https://github.com/nixos/nixpkgs/tree/nixos-22.11>
|
||||
# nixpkgs-stable.url = "github:nixos/nixpkgs?ref=nixos-22.11";
|
||||
|
||||
# branch workflow:
|
||||
# - daily:
|
||||
# - nixos-unstable cut from master after enough packages have been built in caches.
|
||||
@@ -180,12 +177,6 @@
|
||||
optimizations = final: prev: import ./overlays/optimizations.nix final prev;
|
||||
passthru = final: prev:
|
||||
let
|
||||
stable =
|
||||
if inputs ? "nixpkgs-stable" then (
|
||||
final': prev': {
|
||||
stable = inputs.nixpkgs-stable.legacyPackages."${prev'.stdenv.hostPlatform.system}";
|
||||
}
|
||||
) else (final': prev': {});
|
||||
mobile = (import "${mobile-nixos}/overlay/overlay.nix");
|
||||
uninsane = uninsane-dot-org.overlay;
|
||||
# nix-serve' = nix-serve.overlay;
|
||||
@@ -196,11 +187,10 @@
|
||||
inherit (nix-serve.packages."${next.system}") nix-serve;
|
||||
};
|
||||
in
|
||||
(stable final prev)
|
||||
// (mobile final prev)
|
||||
// (uninsane final prev)
|
||||
// (nix-serve' final prev)
|
||||
;
|
||||
(mobile final prev)
|
||||
// (uninsane final prev)
|
||||
// (nix-serve' final prev)
|
||||
;
|
||||
};
|
||||
|
||||
nixosModules = rec {
|
||||
@@ -252,7 +242,7 @@
|
||||
deployScript = action: pkgs.writeShellScript "deploy-moby" ''
|
||||
nixos-rebuild --flake '.#moby' build $@
|
||||
sudo nix sign-paths -r -k /run/secrets/nix_serve_privkey $(readlink ./result)
|
||||
nixos-rebuild --flake '.#moby' ${action} --target-host colin@moby-hn --use-remote-sudo $@
|
||||
nixos-rebuild --flake '.#moby' ${action} --target-host colin@moby --use-remote-sudo $@
|
||||
'';
|
||||
in {
|
||||
update-feeds = {
|
||||
@@ -276,6 +266,22 @@
|
||||
type = "app";
|
||||
program = ''${deployScript "switch"}'';
|
||||
};
|
||||
|
||||
check-nur = {
|
||||
# `nix run '.#check-nur'`
|
||||
# validates that my repo can be included in the Nix User Repository
|
||||
type = "app";
|
||||
program = builtins.toString (pkgs.writeShellScript "check-nur" ''
|
||||
cd ${./.}/integrations/nur
|
||||
NIX_PATH= NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1 nix-env -f . -qa \* --meta --xml \
|
||||
--allowed-uris https://static.rust-lang.org \
|
||||
--option restrict-eval true \
|
||||
--option allow-import-from-derivation true \
|
||||
--drv-path --show-trace \
|
||||
-I nixpkgs=$(nix-instantiate --find-file nixpkgs) \
|
||||
-I ../../
|
||||
'');
|
||||
};
|
||||
};
|
||||
|
||||
templates = {
|
||||
|
@@ -4,6 +4,12 @@
|
||||
./fs.nix
|
||||
];
|
||||
|
||||
sane.guest.enable = true;
|
||||
|
||||
# TODO: make sure this plays nice with impermanence
|
||||
services.distccd.enable = true;
|
||||
sane.programs.distcc.enableFor.user.guest = true;
|
||||
|
||||
sops.secrets.colin-passwd.neededForUsers = true;
|
||||
|
||||
sane.roles.build-machine.enable = true;
|
||||
@@ -19,6 +25,7 @@
|
||||
sane.programs.iphoneUtils.enableFor.user.colin = true;
|
||||
|
||||
sane.programs.guiApps.suggestedPrograms = [ "desktopGuiApps" ];
|
||||
sane.programs.consoleUtils.suggestedPrograms = [ "consoleMediaUtils" ];
|
||||
|
||||
boot.loader.efi.canTouchEfiVariables = false;
|
||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||
|
@@ -19,6 +19,7 @@
|
||||
"desktopGuiApps"
|
||||
"stepmania"
|
||||
];
|
||||
sane.programs.consoleUtils.suggestedPrograms = [ "consoleMediaUtils" ];
|
||||
|
||||
sops.secrets.colin-passwd.neededForUsers = true;
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# doesn't actually *enable* anything,
|
||||
# but sets up any modules such that if they *were* enabled, they'll act as expected.
|
||||
{ ... }:
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
sane.gui.sxmo = {
|
||||
greeter = "sway";
|
||||
@@ -28,5 +28,11 @@
|
||||
# see <repo:mil/sxmo-utils:scripts/deviceprofiles>
|
||||
# SXMO_DEVICE_NAME = "pine64,pinephone-1.2";
|
||||
};
|
||||
package = pkgs.sxmo-utils.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
|
||||
'';
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@@ -33,11 +33,15 @@
|
||||
".config/pulse" # persist pulseaudio volume
|
||||
];
|
||||
|
||||
sane.gui.phosh.enable = true;
|
||||
sane.gui.sxmo.enable = true;
|
||||
# sane.programs.consoleUtils.enableFor.user.colin = false;
|
||||
# sane.programs.guiApps.enableFor.user.colin = false;
|
||||
sane.programs.sequoia.enableFor.user.colin = false;
|
||||
sane.programs.tuiApps.enableFor.user.colin = false; # visidata, others, don't compile well
|
||||
# disabled for faster deploys (gthumb depends on webkitgtk, particularly)
|
||||
sane.programs.soundconverter.enableFor.user.colin = false;
|
||||
sane.programs.jellyfin-media-player.enableFor.user.colin = false;
|
||||
# sane.programs.mpv.enableFor.user.colin = true;
|
||||
|
||||
boot.loader.efi.canTouchEfiVariables = false;
|
||||
# /boot space is at a premium. default was 20.
|
||||
@@ -77,14 +81,30 @@
|
||||
# enable rotation sensor
|
||||
hardware.sensor.iio.enable = true;
|
||||
|
||||
# from https://gitlab.manjaro.org/manjaro-arm/packages/community/phosh/alsa-ucm-pinephone
|
||||
# mobile-nixos does this same thing, with *slightly different settings*.
|
||||
# i trust manjaro more because the guy maintaining that is actively trying to upstream into alsa-ucm-conf.
|
||||
# an alternative may be to build a custom alsa with the PinePhone config patch applied:
|
||||
# - <https://github.com/alsa-project/alsa-ucm-conf/pull/134>
|
||||
# that would make this be not device-specific
|
||||
environment.variables.ALSA_CONFIG_UCM2 = "${./ucm2}";
|
||||
systemd.services.pulseaudio.environment.ALSA_CONFIG_UCM2 = "${./ucm2}";
|
||||
# inject specialized alsa configs via the environment.
|
||||
# specifically, this gets the pinephone headphones & internal earpiece working.
|
||||
# see pkgs/patched/alsa-ucm-conf for more info.
|
||||
environment.variables.ALSA_CONFIG_UCM2 = "/run/current-system/sw/share/alsa/ucm2";
|
||||
environment.pathsToLink = [ "/share/alsa/ucm2" ];
|
||||
environment.systemPackages = [ pkgs.alsa-ucm-conf-sane ];
|
||||
systemd =
|
||||
let ucm-env = config.environment.variables.ALSA_CONFIG_UCM2;
|
||||
in {
|
||||
# cribbed from <repo:nixos/mobile-nixos:modules/quirks/audio.nix>
|
||||
|
||||
# pulseaudio
|
||||
user.services.pulseaudio.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
||||
services.pulseaudio.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
||||
|
||||
# pipewire
|
||||
user.services.pipewire.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
||||
user.services.pipewire-pulse.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
||||
user.services.wireplumber.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
||||
services.pipewire.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
||||
services.pipewire-pulse.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
||||
services.wireplumber.environment.ALSA_CONFIG_UCM2 = ucm-env;
|
||||
};
|
||||
|
||||
|
||||
hardware.opengl.driSupport = true;
|
||||
}
|
||||
|
@@ -1,23 +1,26 @@
|
||||
{ sane-lib, ... }:
|
||||
{ pkgs, sane-lib, ... }:
|
||||
{
|
||||
sane.gui.sxmo = {
|
||||
settings = {
|
||||
# touch screen
|
||||
SXMO_LISGD_INPUT_DEVICE = "/dev/input/by-path/platform-1c2ac00.i2c-event";
|
||||
# vol and power are detected correctly by upstream
|
||||
|
||||
# preferences
|
||||
# N.B. some deviceprofiles explicitly set SXMO_SWAY_SCALE, overwriting what we put here.
|
||||
SXMO_SWAY_SCALE = "1.5";
|
||||
SXMO_ROTATION_GRAVITY = "12800";
|
||||
SXMO_LOCK_IDLE_TIME = "15"; # how long between screenoff -> lock -> back to screenoff
|
||||
DEFAULT_COUNTRY = "US";
|
||||
BROWSWER = "librewolf";
|
||||
};
|
||||
package = pkgs.sxmo-utils.overrideAttrs (base: {
|
||||
postPatch = (base.postPatch or "") + ''
|
||||
cat <<EOF >> ./configs/default_hooks/sxmo_hook_start.sh
|
||||
# rotate UI based on physical display angle by default
|
||||
sxmo_daemons.sh start autorotate sxmo_autorotate.sh
|
||||
EOF
|
||||
'';
|
||||
});
|
||||
};
|
||||
# TODO: only populate this if sxmo is enabled?
|
||||
sane.user.fs.".config/sxmo/profile" = sane-lib.fs.wantedText ''
|
||||
# sourced by sxmo_init.sh
|
||||
. sxmo_common.sh
|
||||
|
||||
export SXMO_SWAY_SCALE=1.5
|
||||
export SXMO_ROTATION_GRAVITY=12800
|
||||
|
||||
export DEFAULT_COUNTRY=US
|
||||
export BROWSER=librewolf
|
||||
|
||||
export SXMO_BG_IMG="$(xdg_data_path sxmo/background.jpg)"
|
||||
'';
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@
|
||||
sane.zsh.showDeadlines = false; # ~/knowledge doesn't always exist
|
||||
sane.services.dyn-dns.enable = true;
|
||||
sane.services.wg-home.enable = true;
|
||||
sane.services.wg-home.enableWan = true;
|
||||
sane.services.wg-home.ip = config.sane.hosts.by-name."servo".wg-home.ip;
|
||||
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade
|
||||
|
||||
|
@@ -3,6 +3,12 @@
|
||||
{
|
||||
networking.domain = "uninsane.org";
|
||||
|
||||
sane.ports.openFirewall = true;
|
||||
sane.ports.openUpnp = true;
|
||||
|
||||
# view refused packets with: `sudo journalctl -k`
|
||||
# networking.firewall.logRefusedPackets = true;
|
||||
|
||||
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
|
||||
# Per-interface useDHCP will be mandatory in the future, so this generated config
|
||||
# replicates the default behaviour.
|
||||
@@ -11,9 +17,6 @@
|
||||
# XXX colin: probably don't need this. wlan0 won't be populated unless i touch a value in networking.interfaces.wlan0
|
||||
networking.wireless.enable = false;
|
||||
|
||||
# networking.firewall.enable = false;
|
||||
networking.firewall.enable = true;
|
||||
|
||||
# this is needed to forward packets from the VPN to the host
|
||||
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
|
||||
|
||||
@@ -153,9 +156,9 @@
|
||||
|
||||
# we also bridge DNS traffic
|
||||
${in-ns} ${iptables} -A PREROUTING -t nat -p udp --dport 53 -m iprange --dst-range ${vpn-ip} \
|
||||
-j DNAT --to-destination ${veth-host-ip}:53
|
||||
-j DNAT --to-destination ${veth-host-ip}
|
||||
${in-ns} ${iptables} -A PREROUTING -t nat -p tcp --dport 53 -m iprange --dst-range ${vpn-ip} \
|
||||
-j DNAT --to-destination ${veth-host-ip}:53
|
||||
-j DNAT --to-destination ${veth-host-ip}
|
||||
|
||||
# in order to access DNS in this netns, we need to route it to the VPN's nameservers
|
||||
# - alternatively, we could fix DNS servers like 1.1.1.1.
|
||||
|
@@ -30,5 +30,5 @@ lib.mkIf false
|
||||
proxyPass = "http://${ip}:${builtins.toString port}";
|
||||
};
|
||||
};
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."calibre" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."calibre" = "native";
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@
|
||||
./email
|
||||
./ejabberd.nix
|
||||
./freshrss.nix
|
||||
./ftp
|
||||
./gitea.nix
|
||||
./goaccess.nix
|
||||
./ipfs.nix
|
||||
@@ -17,6 +18,7 @@
|
||||
./lemmy.nix
|
||||
./matrix
|
||||
./navidrome.nix
|
||||
./nfs.nix
|
||||
./nixserve.nix
|
||||
./nginx.nix
|
||||
./pict-rs.nix
|
||||
|
@@ -22,20 +22,60 @@
|
||||
sane.persist.sys.plaintext = [
|
||||
{ user = "ejabberd"; group = "ejabberd"; directory = "/var/lib/ejabberd"; }
|
||||
];
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
3478 # STUN/TURN
|
||||
5222 # XMPP client -> server
|
||||
5223 # XMPPS client -> server (XMPP over TLS)
|
||||
5269 # XMPP server -> server
|
||||
5270 # XMPPS server -> server (XMPP over TLS)
|
||||
5280 # bosh
|
||||
5281 # bosh (https) ??
|
||||
5349 # STUN/TURN (TLS)
|
||||
5443 # web services (file uploads, websockets, admin)
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
3478 # STUN/TURN
|
||||
];
|
||||
sane.ports.ports."3478" = {
|
||||
protocol = [ "tcp" "udp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-xmpp-stun-turn";
|
||||
};
|
||||
sane.ports.ports."5222" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-xmpp-client-to-server";
|
||||
};
|
||||
sane.ports.ports."5223" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-xmpps-client-to-server"; # XMPP over TLS
|
||||
};
|
||||
sane.ports.ports."5269" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.wan = true;
|
||||
description = "colin-xmpp-server-to-server";
|
||||
};
|
||||
sane.ports.ports."5270" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.wan = true;
|
||||
description = "colin-xmpps-server-to-server"; # XMPP over TLS
|
||||
};
|
||||
sane.ports.ports."5280" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-xmpp-bosh";
|
||||
};
|
||||
sane.ports.ports."5281" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-xmpp-bosh-https";
|
||||
};
|
||||
sane.ports.ports."5349" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-xmpp-stun-turn-over-tls";
|
||||
};
|
||||
sane.ports.ports."5443" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-xmpp-web-services"; # file uploads, websockets, admin
|
||||
};
|
||||
|
||||
# TODO: forward these TURN ports!
|
||||
networking.firewall.allowedTCPPortRanges = [{
|
||||
from = 49152; # TURN
|
||||
to = 49408;
|
||||
@@ -75,9 +115,9 @@
|
||||
useACMEHost = "uninsane.org";
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
sane.dns.zones."uninsane.org".inet = {
|
||||
# XXX: SRV records have to point to something with a A/AAAA record; no CNAMEs
|
||||
A."xmpp" = "%NATIVE%";
|
||||
A."xmpp" = "%ANATIVE%";
|
||||
CNAME."muc.xmpp" = "xmpp";
|
||||
CNAME."pubsub.xmpp" = "xmpp";
|
||||
CNAME."upload.xmpp" = "xmpp";
|
||||
@@ -234,7 +274,7 @@
|
||||
use_turn: true
|
||||
turn_min_port: 49152
|
||||
turn_max_port: 65535
|
||||
turn_ipv4_address: %NATIVE%
|
||||
turn_ipv4_address: %ANATIVE%
|
||||
-
|
||||
# STUN+TURN UDP
|
||||
port: 3478
|
||||
@@ -243,7 +283,7 @@
|
||||
use_turn: true
|
||||
turn_min_port: 49152
|
||||
turn_max_port: 65535
|
||||
turn_ipv4_address: %NATIVE%
|
||||
turn_ipv4_address: %ANATIVE%
|
||||
-
|
||||
# STUN+TURN TLS over TCP
|
||||
port: 5349
|
||||
@@ -254,7 +294,7 @@
|
||||
use_turn: true
|
||||
turn_min_port: 49152
|
||||
turn_max_port: 65535
|
||||
turn_ipv4_address: %NATIVE%
|
||||
turn_ipv4_address: %ANATIVE%
|
||||
|
||||
# TODO: enable mod_fail2ban
|
||||
# TODO(low): look into mod_http_fileserver for serving macros?
|
||||
@@ -387,7 +427,7 @@
|
||||
# config is 444 (not 644), so we want to write out-of-place and then atomically move
|
||||
# TODO: factor this out into `sane-woop` helper?
|
||||
rm -f /var/lib/ejabberd/ejabberd.yaml.new
|
||||
${sed} "s/%NATIVE%/$ip/" ${config-in} > /var/lib/ejabberd/ejabberd.yaml.new
|
||||
${sed} "s/%ANATIVE%/$ip/" ${config-in} > /var/lib/ejabberd/ejabberd.yaml.new
|
||||
mv /var/lib/ejabberd/ejabberd.yaml{.new,}
|
||||
'';
|
||||
|
||||
|
@@ -6,18 +6,25 @@
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
# exposed over non-vpn imap.uninsane.org
|
||||
143 # IMAP
|
||||
993 # IMAPS
|
||||
];
|
||||
sane.ports.ports."143" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-imap-imap.uninsane.org";
|
||||
};
|
||||
sane.ports.ports."993" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-imaps-imap.uninsane.org";
|
||||
};
|
||||
|
||||
# exists only to manage certs for dovecot
|
||||
services.nginx.virtualHosts."imap.uninsane.org" = {
|
||||
enableACME = true;
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
sane.dns.zones."uninsane.org".inet = {
|
||||
CNAME."imap" = "native";
|
||||
};
|
||||
|
||||
|
@@ -28,12 +28,21 @@ in
|
||||
# "/var/lib/dovecot"
|
||||
];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
# exposed over vpn mx.uninsane.org
|
||||
25 # SMTP
|
||||
465 # SMTPS
|
||||
587 # SMTPS/submission
|
||||
];
|
||||
sane.ports.ports."25" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.ovpn = true;
|
||||
description = "colin-smtp-mx.uninsane.org";
|
||||
};
|
||||
sane.ports.ports."465" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.ovpn = true;
|
||||
description = "colin-smtps-mx.uninsane.org";
|
||||
};
|
||||
sane.ports.ports."587" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.ovpn = true;
|
||||
description = "colin-smtps-submission-mx.uninsane.org";
|
||||
};
|
||||
|
||||
# exists only to manage certs for Postfix
|
||||
services.nginx.virtualHosts."mx.uninsane.org" = {
|
||||
@@ -41,7 +50,7 @@ in
|
||||
};
|
||||
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
sane.dns.zones."uninsane.org".inet = {
|
||||
MX."@" = "10 mx.uninsane.org.";
|
||||
# XXX: RFC's specify that the MX record CANNOT BE A CNAME
|
||||
A."mx" = "185.157.162.178";
|
||||
|
@@ -59,5 +59,5 @@
|
||||
# the routing is handled by services.freshrss.virtualHost
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."rss" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."rss" = "native";
|
||||
}
|
||||
|
70
hosts/by-name/servo/services/ftp/default.nix
Normal file
70
hosts/by-name/servo/services/ftp/default.nix
Normal file
@@ -0,0 +1,70 @@
|
||||
# docs:
|
||||
# - <https://github.com/drakkan/sftpgo>
|
||||
# - config options: <https://github.com/drakkan/sftpgo/blob/main/docs/full-configuration.md>
|
||||
# - config defaults: <https://github.com/drakkan/sftpgo/blob/main/sftpgo.json>
|
||||
# - nixos options: <repo:nixos/nixpkgs:nixos/modules/services/web-apps/sftpgo.nix>
|
||||
#
|
||||
# sftpgo is a FTP server that also supports WebDAV, SFTP, and web clients.
|
||||
|
||||
|
||||
{ lib, pkgs, sane-lib, ... }:
|
||||
let
|
||||
authProgram = pkgs.static-nix-shell.mkBash {
|
||||
pname = "sftpgo_external_auth_hook";
|
||||
src = ./.;
|
||||
};
|
||||
in
|
||||
{
|
||||
# Client initiates a FTP "control connection" on port 21.
|
||||
# - this handles the client -> server commands, and the server -> client status, but not the actual data
|
||||
# - file data, directory listings, etc need to be transferred on an ephemeral "data port".
|
||||
# - 50000-50100 is a common port range for this.
|
||||
sane.ports.ports = {
|
||||
"21" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-FTP server";
|
||||
};
|
||||
} // (sane-lib.mapToAttrs
|
||||
(port: {
|
||||
name = builtins.toString port;
|
||||
value = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-FTP server data port range";
|
||||
};
|
||||
})
|
||||
(lib.range 50000 50100)
|
||||
);
|
||||
|
||||
services.sftpgo = {
|
||||
enable = true;
|
||||
settings = {
|
||||
ftpd = {
|
||||
bindings = [{
|
||||
address = "10.0.10.5";
|
||||
port = 21;
|
||||
debug = true;
|
||||
}];
|
||||
|
||||
# active mode is susceptible to "bounce attacks", without much benefit over passive mode
|
||||
disable_active_mode = true;
|
||||
hash_support = true;
|
||||
passive_port_range = {
|
||||
start = 50000;
|
||||
end = 50100;
|
||||
};
|
||||
|
||||
banner = ''
|
||||
Welcome, friends, to Colin's read-only FTP server! Also available via NFS on the same host.
|
||||
Please let me know if anything's broken or not as it should be. Otherwise, browse and DL freely :)
|
||||
'';
|
||||
|
||||
};
|
||||
data_provider = {
|
||||
driver = "memory";
|
||||
external_auth_hook = "${authProgram}/bin/sftpgo_external_auth_hook";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
55
hosts/by-name/servo/services/ftp/sftpgo_external_auth_hook
Executable file
55
hosts/by-name/servo/services/ftp/sftpgo_external_auth_hook
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash
|
||||
# vim: set filetype=bash :
|
||||
#
|
||||
# available environment variables:
|
||||
# - SFTPGO_AUTHD_USERNAME
|
||||
# - SFTPGO_AUTHD_USER
|
||||
# - SFTPGO_AUTHD_IP
|
||||
# - SFTPGO_AUTHD_PROTOCOL = { "DAV", "FTP", "HTTP", "SSH" }
|
||||
# - SFTPGO_AUTHD_PASSWORD
|
||||
# - SFTPGO_AUTHD_PUBLIC_KEY
|
||||
# - SFTPGO_AUTHD_KEYBOARD_INTERACTIVE
|
||||
# - SFTPGO_AUTHD_TLS_CERT
|
||||
#
|
||||
# user permissions:
|
||||
# - see <repo:drakkan/sftpgo:internal/dataprovider/user.go>
|
||||
# - "*" = grant all permissions
|
||||
# - read-only perms:
|
||||
# - "list" = list files and directories
|
||||
# - "download"
|
||||
# - rw perms:
|
||||
# - "upload"
|
||||
# - "overwrite" = allow uploads to replace existing files
|
||||
# - "delete" = delete files and directories
|
||||
# - "delete_files"
|
||||
# - "delete_dirs"
|
||||
# - "rename" = rename files and directories
|
||||
# - "rename_files"
|
||||
# - "rename_dirs"
|
||||
# - "create_dirs"
|
||||
# - "create_symlinks"
|
||||
# - "chmod"
|
||||
# - "chown"
|
||||
# - "chtimes" = change atime/mtime (access and modification times)
|
||||
#
|
||||
# home_dir:
|
||||
# - it seems (empirically) that a user can't cd above their home directory.
|
||||
# though i don't have a reference for that in the docs.
|
||||
# TODO: don't reuse /var/nfs/export here. formalize this some other way.
|
||||
|
||||
|
||||
if [ "$SFTPGO_AUTHD_USERNAME" = "anonymous" ]; then
|
||||
echo '{'
|
||||
echo ' "status":1,'
|
||||
echo ' "username":"anonymous","expiration_date":0,'
|
||||
echo ' "home_dir":"/var/nfs/export","uid":65534,"gid":65534,"max_sessions":0,"quota_size":0,"quota_files":100000,'
|
||||
echo ' "permissions":{'
|
||||
echo ' "/":["list", "download"]'
|
||||
echo ' },'
|
||||
echo ' "upload_bandwidth":0,"download_bandwidth":0,'
|
||||
echo ' "filters":{"allowed_ip":[],"denied_ip":[]},"public_keys":[]'
|
||||
echo '}'
|
||||
else
|
||||
echo '{"username":""}'
|
||||
fi
|
@@ -98,5 +98,12 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."git" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."git" = "native";
|
||||
|
||||
sane.ports.ports."22" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-git@git.uninsane.org";
|
||||
};
|
||||
}
|
||||
|
@@ -64,5 +64,5 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."sink" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."sink" = "native";
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@ lib.mkIf false # i don't actively use ipfs anymore
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."ipfs" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."ipfs" = "native";
|
||||
|
||||
# services.ipfs.enable = true;
|
||||
services.kubo.localDiscovery = true;
|
||||
|
@@ -24,9 +24,10 @@
|
||||
locations."/" = {
|
||||
# proxyPass = "http://ovpns.uninsane.org:9117";
|
||||
proxyPass = "http://10.0.1.6:9117";
|
||||
recommendedProxySettings = true;
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jackett" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."jackett" = "native";
|
||||
}
|
||||
|
||||
|
@@ -16,17 +16,30 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
# identical to:
|
||||
# services.jellyfin.openFirewall = true;
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
# https://jellyfin.org/docs/general/networking/index.html
|
||||
1900 # UPnP service discovery
|
||||
7359 # Jellyfin-specific (?) client discovery
|
||||
];
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
8096 # HTTP (for the LAN)
|
||||
8920 # HTTPS (for the LAN)
|
||||
];
|
||||
# https://jellyfin.org/docs/general/networking/index.html
|
||||
sane.ports.ports."1900" = {
|
||||
protocol = [ "udp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-upnp-for-jellyfin";
|
||||
};
|
||||
sane.ports.ports."7359" = {
|
||||
protocol = [ "udp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-jellyfin-specific-client-discovery";
|
||||
# ^ not sure if this is necessary: copied this port from nixos jellyfin.openFirewall
|
||||
};
|
||||
# not sure if 8096/8920 get used either:
|
||||
sane.ports.ports."8096" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-jellyfin-http-lan";
|
||||
};
|
||||
sane.ports.ports."8920" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-jellyfin-https-lan";
|
||||
};
|
||||
|
||||
sane.persist.sys.plaintext = [
|
||||
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; directory = "/var/lib/jellyfin"; }
|
||||
];
|
||||
@@ -108,7 +121,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jelly" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."jelly" = "native";
|
||||
|
||||
services.jellyfin.enable = true;
|
||||
}
|
||||
|
@@ -13,5 +13,5 @@
|
||||
locations."/".proxyPass = "http://127.0.0.1:8013";
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."w" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."w" = "native";
|
||||
}
|
||||
|
@@ -18,5 +18,5 @@ in
|
||||
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
||||
};
|
||||
};
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."komga" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."komga" = "native";
|
||||
}
|
||||
|
@@ -14,8 +14,8 @@ in {
|
||||
services.lemmy = {
|
||||
enable = true;
|
||||
settings.hostname = "lemmy.uninsane.org";
|
||||
settings.federation.enabled = true;
|
||||
# federation.debug forces outbound federation queries to be run synchronously
|
||||
# N.B.: this option might not be read for 0.17.0+? <https://github.com/LemmyNet/lemmy/blob/c32585b03429f0f76d1e4ff738786321a0a9df98/RELEASES.md#upgrade-instructions>
|
||||
# settings.federation.debug = true;
|
||||
settings.port = backendPort;
|
||||
ui.port = uiPort;
|
||||
@@ -32,6 +32,7 @@ in {
|
||||
systemd.services.lemmy.environment = {
|
||||
RUST_BACKTRACE = "full";
|
||||
# RUST_LOG = "debug";
|
||||
# RUST_LOG = "trace";
|
||||
# upstream defaults LEMMY_DATABASE_URL = "postgres:///lemmy?host=/run/postgresql";
|
||||
# - Postgres complains that we didn't specify a user
|
||||
# lemmy formats the url as:
|
||||
@@ -54,5 +55,5 @@ in {
|
||||
enableACME = true;
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."lemmy" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."lemmy" = "native";
|
||||
}
|
||||
|
@@ -132,7 +132,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
sane.dns.zones."uninsane.org".inet = {
|
||||
CNAME."matrix" = "native";
|
||||
CNAME."web.matrix" = "native";
|
||||
};
|
||||
|
@@ -1,4 +1,9 @@
|
||||
{ lib, ... }:
|
||||
|
||||
# XXX mx-discord-puppet uses nodejs_14 which is EOL
|
||||
# - mx-discord-puppet is abandoned upstream _and_ in nixpkgs
|
||||
# - recommended to use mautrix-discord: <https://github.com/NixOS/nixpkgs/pull/200462>
|
||||
lib.mkIf false
|
||||
{
|
||||
sane.persist.sys.plaintext = [
|
||||
{ user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/mx-puppet-discord"; }
|
||||
|
@@ -5,12 +5,11 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
ircServer = { name, additionalAddresses ? [], sasl ? true }: let
|
||||
ircServer = { name, additionalAddresses ? [], sasl ? true, port ? 6697 }: let
|
||||
lowerName = lib.toLower name;
|
||||
in {
|
||||
# XXX sasl: appservice doesn't support NickServ identification (only SASL, or PASS if sasl = false)
|
||||
inherit name additionalAddresses sasl;
|
||||
port = 6697;
|
||||
inherit name additionalAddresses sasl port;
|
||||
ssl = true;
|
||||
botConfig = {
|
||||
# bot has no presence in IRC channel; only real Matrix users
|
||||
@@ -108,6 +107,12 @@ in
|
||||
{ user = "matrix-appservice-irc"; group = "matrix-appservice-irc"; directory = "/var/lib/matrix-appservice-irc"; }
|
||||
];
|
||||
|
||||
# XXX: matrix-appservice-irc PreStart tries to chgrp the registration.yml to matrix-synapse,
|
||||
# which requires matrix-appservice-irc to be of that group
|
||||
users.users.matrix-appservice-irc.extraGroups = [ "matrix-synapse" ];
|
||||
# weird race conditions around registration.yml mean we want matrix-synapse to be of matrix-appservice-irc group too.
|
||||
users.users.matrix-synapse.extraGroups = [ "matrix-appservice-irc" ];
|
||||
|
||||
services.matrix-synapse.settings.app_service_config_files = [
|
||||
"/var/lib/matrix-appservice-irc/registration.yml" # auto-created by irc appservice
|
||||
];
|
||||
@@ -145,6 +150,7 @@ in
|
||||
};
|
||||
"irc.oftc.net" = ircServer {
|
||||
name = "oftc";
|
||||
sasl = false;
|
||||
# notable channels:
|
||||
# - #sxmo
|
||||
# - #sxmo-offtopic
|
||||
@@ -153,4 +159,10 @@ in
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.matrix-appservice-irc.serviceConfig = {
|
||||
# XXX 2023/06/20: nixos specifies this + @aio and @memlock as forbidden
|
||||
# the service actively uses at least one of these, and both of them are fairly innocuous
|
||||
SystemCallFilter = lib.mkForce "~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @setuid @swap";
|
||||
};
|
||||
}
|
||||
|
@@ -36,5 +36,5 @@
|
||||
locations."/".proxyPass = "http://127.0.0.1:4533";
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."music" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."music" = "native";
|
||||
}
|
||||
|
67
hosts/by-name/servo/services/nfs.nix
Normal file
67
hosts/by-name/servo/services/nfs.nix
Normal file
@@ -0,0 +1,67 @@
|
||||
# docs:
|
||||
# - <https://nixos.wiki/wiki/NFS>
|
||||
# - <https://wiki.gentoo.org/wiki/Nfs-utils>
|
||||
|
||||
{ ... }:
|
||||
{
|
||||
services.nfs.server.enable = true;
|
||||
|
||||
# see which ports NFS uses with:
|
||||
# - `rpcinfo -p`
|
||||
sane.ports.ports."111" = {
|
||||
protocol = [ "tcp" "udp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "NFS server portmapper";
|
||||
};
|
||||
sane.ports.ports."2049" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "NFS server";
|
||||
};
|
||||
sane.ports.ports."4000" = {
|
||||
protocol = [ "udp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "NFS server status daemon";
|
||||
};
|
||||
sane.ports.ports."4001" = {
|
||||
protocol = [ "tcp" "udp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "NFS server lock daemon";
|
||||
};
|
||||
sane.ports.ports."4002" = {
|
||||
protocol = [ "tcp" "udp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "NFS server mount daemon";
|
||||
};
|
||||
|
||||
# NFS4 allows these to float, but NFS3 mandates specific ports, so fix them for backwards compat.
|
||||
services.nfs.server.lockdPort = 4001;
|
||||
services.nfs.server.mountdPort = 4002;
|
||||
services.nfs.server.statdPort = 4000;
|
||||
|
||||
# format:
|
||||
# fspoint visibility(options)
|
||||
# options:
|
||||
# - see: <https://wiki.gentoo.org/wiki/Nfs-utils#Exports>
|
||||
# - see [man 5 exports](https://linux.die.net/man/5/exports)
|
||||
# - insecure: require clients use src port > 1024
|
||||
# - rw, ro (default)
|
||||
# - async, sync (default)
|
||||
# - no_subtree_check (default), subtree_check: verify not just that files requested by the client live
|
||||
# in the expected fs, but also that they live under whatever subdirectory of that fs is exported.
|
||||
# - no_root_squash, root_squash (default): map requests from uid 0 to user `nobody`.
|
||||
# - crossmnt: reveal filesystems that are mounted under this endpoint
|
||||
# - fsid: must be zero for the root export
|
||||
# - mountpoint[=/path]: only export the directory if it's a mountpoint. used to avoid exporting failed mounts.
|
||||
#
|
||||
# 10.0.0.0/8 to export (readonly) both to LAN (unencrypted) and wg vpn (encrypted)
|
||||
services.nfs.server.exports = ''
|
||||
/var/nfs/export 10.78.79.0/22(ro,crossmnt,fsid=0,subtree_check) 10.0.10.0/24(rw,no_root_squash,crossmnt,fsid=0,subtree_check)
|
||||
'';
|
||||
|
||||
fileSystems."/var/nfs/export/media" = {
|
||||
# everything in here could be considered publicly readable (based on the viewer's legal jurisdiction)
|
||||
device = "/var/lib/uninsane/media";
|
||||
options = [ "rbind" ];
|
||||
};
|
||||
}
|
@@ -13,7 +13,19 @@ let
|
||||
in
|
||||
{
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
sane.ports.ports."80" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
visibleTo.ovpn = true; # so that letsencrypt can procure a cert for the mx record
|
||||
description = "colin-http-uninsane.org";
|
||||
};
|
||||
sane.ports.ports."443" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-https-uninsane.org";
|
||||
};
|
||||
|
||||
services.nginx.enable = true;
|
||||
services.nginx.appendConfig = ''
|
||||
|
@@ -14,7 +14,7 @@
|
||||
'';
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."nixcache" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."nixcache" = "native";
|
||||
|
||||
sane.services.nixserve.enable = true;
|
||||
sane.services.nixserve.secretKeyFile = config.sops.secrets.nix_serve_privkey.path;
|
||||
|
@@ -3,6 +3,8 @@
|
||||
# - https://docs.pleroma.social/backend/configuration/cheatsheet/
|
||||
#
|
||||
# to run it in a oci-container: https://github.com/barrucadu/nixfiles/blob/master/services/pleroma.nix
|
||||
#
|
||||
# admin frontend: <https://fed.uninsane.org/pleroma/admin>
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
@@ -100,6 +102,8 @@
|
||||
# level: :debug
|
||||
|
||||
# XXX colin: not sure if this actually _does_ anything
|
||||
# better to steal emoji from other instances?
|
||||
# - <https://docs.pleroma.social/backend/configuration/cheatsheet/#mrf_steal_emoji>
|
||||
config :pleroma, :emoji,
|
||||
shortcode_globs: ["/emoji/**/*.png"],
|
||||
groups: [
|
||||
@@ -182,7 +186,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."fed" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."fed" = "native";
|
||||
|
||||
sops.secrets."pleroma_secrets" = {
|
||||
owner = config.users.users.pleroma.name;
|
||||
|
@@ -12,12 +12,29 @@ lib.mkIf false
|
||||
sane.persist.sys.plaintext = [
|
||||
{ user = "prosody"; group = "prosody"; directory = "/var/lib/prosody"; }
|
||||
];
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
5222 # XMPP client -> server
|
||||
5269 # XMPP server -> server
|
||||
5280 # bosh
|
||||
5281 # Prosody HTTPS port (necessary?)
|
||||
];
|
||||
sane.ports.ports."5222" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-xmpp-client-to-server";
|
||||
};
|
||||
sane.ports.ports."5269" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.wan = true;
|
||||
description = "colin-xmpp-server-to-server";
|
||||
};
|
||||
sane.ports.ports."5280" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-xmpp-bosh";
|
||||
};
|
||||
sane.ports.ports."5281" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-xmpp-prosody-https"; # necessary?
|
||||
};
|
||||
|
||||
# provide access to certs
|
||||
users.users.prosody.extraGroups = [ "nginx" ];
|
||||
|
@@ -75,6 +75,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."bt" = "native";
|
||||
sane.dns.zones."uninsane.org".inet.CNAME."bt" = "native";
|
||||
}
|
||||
|
||||
|
@@ -1,17 +1,25 @@
|
||||
{ config, pkgs, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
sane.services.trust-dns.enable = true;
|
||||
|
||||
sane.services.trust-dns.listenAddrsIPv4 = [
|
||||
sane.services.trust-dns.settings.listen_addrs_ipv4 = [
|
||||
# specify each address explicitly, instead of using "*".
|
||||
# this ensures responses are sent from the address at which the request was received.
|
||||
config.sane.hosts.by-name."servo".lan-ip
|
||||
"10.0.1.5"
|
||||
];
|
||||
sane.services.trust-dns.quiet = true;
|
||||
# sane.services.trust-dns.debug = true;
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".TTL = 900;
|
||||
sane.ports.ports."53" = {
|
||||
protocol = [ "udp" "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = true;
|
||||
description = "colin-dns-hosting";
|
||||
};
|
||||
|
||||
sane.dns.zones."uninsane.org".TTL = 900;
|
||||
|
||||
# SOA record structure: <https://en.wikipedia.org/wiki/SOA_record#Structure>
|
||||
# SOA MNAME RNAME (... rest)
|
||||
@@ -21,7 +29,7 @@
|
||||
# Refresh = how frequently secondary NS should query master
|
||||
# Retry = how long secondary NS should wait until re-querying master after a failure (must be < Refresh)
|
||||
# Expire = how long secondary NS should continue to reply to queries after master fails (> Refresh + Retry)
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
sane.dns.zones."uninsane.org".inet = {
|
||||
SOA."@" = ''
|
||||
ns1.uninsane.org. admin-dns.uninsane.org. (
|
||||
2022122101 ; Serial
|
||||
@@ -30,17 +38,20 @@
|
||||
7d ; Expire
|
||||
5m) ; Negative response TTL
|
||||
'';
|
||||
TXT."rev" = "2022122101";
|
||||
TXT."rev" = "2023052901";
|
||||
|
||||
CNAME."native" = "%CNAMENATIVE%";
|
||||
A."@" = "%ANATIVE%";
|
||||
A."wan" = "%AWAN%";
|
||||
A."servo.lan" = config.sane.hosts.by-name."servo".lan-ip;
|
||||
|
||||
# XXX NS records must also not be CNAME
|
||||
# it's best that we keep this identical, or a superset of, what org. lists as our NS.
|
||||
# so, org. can specify ns2/ns3 as being to the VPN, with no mention of ns1. we provide ns1 here.
|
||||
A."ns1" = "%NATIVE%";
|
||||
A."ns1" = "%ANATIVE%";
|
||||
A."ns2" = "185.157.162.178";
|
||||
A."ns3" = "185.157.162.178";
|
||||
A."ovpns" = "185.157.162.178";
|
||||
A."native" = "%NATIVE%";
|
||||
A."@" = "%NATIVE%";
|
||||
NS."@" = [
|
||||
"ns1.uninsane.org."
|
||||
"ns2.uninsane.org."
|
||||
@@ -48,20 +59,73 @@
|
||||
];
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".file =
|
||||
"/var/lib/trust-dns/uninsane.org.zone";
|
||||
# we need trust-dns to load our zone by relative path instead of /nix/store path
|
||||
# because we generate it at runtime.
|
||||
sane.services.trust-dns.settings.zones = [
|
||||
{
|
||||
zone = "uninsane.org";
|
||||
}
|
||||
];
|
||||
|
||||
systemd.services.trust-dns.preStart = let
|
||||
sed = "${pkgs.gnused}/bin/sed";
|
||||
zone-dir = "/var/lib/trust-dns";
|
||||
zone-out = "${zone-dir}/uninsane.org.zone";
|
||||
zone-template = pkgs.writeText "uninsane.org.zone.in" config.sane.services.trust-dns.generatedZones."uninsane.org";
|
||||
in ''
|
||||
# make WAN records available to trust-dns
|
||||
mkdir -p ${zone-dir}
|
||||
ip=$(cat '${config.sane.services.dyn-dns.ipPath}')
|
||||
${sed} s/%NATIVE%/$ip/ ${zone-template} > ${zone-out}
|
||||
'';
|
||||
sane.services.trust-dns.package =
|
||||
let
|
||||
sed = "${pkgs.gnused}/bin/sed";
|
||||
zone-dir = "/var/lib/trust-dns";
|
||||
zone-wan = "${zone-dir}/wan/uninsane.org.zone";
|
||||
zone-lan = "${zone-dir}/lan/uninsane.org.zone";
|
||||
zone-template = pkgs.writeText "uninsane.org.zone.in" config.sane.dns.zones."uninsane.org".rendered;
|
||||
in pkgs.writeShellScriptBin "named" ''
|
||||
# compute wan/lan values
|
||||
mkdir -p ${zone-dir}/{ovpn,wan,lan}
|
||||
wan=$(cat '${config.sane.services.dyn-dns.ipPath}')
|
||||
lan=${config.sane.hosts.by-name."servo".lan-ip}
|
||||
|
||||
# create specializations that resolve native.uninsane.org to different CNAMEs
|
||||
${sed} s/%AWAN%/$wan/ ${zone-template} \
|
||||
| ${sed} s/%CNAMENATIVE%/wan/ \
|
||||
| ${sed} s/%ANATIVE%/$wan/ \
|
||||
> ${zone-wan}
|
||||
${sed} s/%AWAN%/$wan/ ${zone-template} \
|
||||
| ${sed} s/%CNAMENATIVE%/servo.lan/ \
|
||||
| ${sed} s/%ANATIVE%/$lan/ \
|
||||
> ${zone-lan}
|
||||
|
||||
# launch the different interfaces, separately
|
||||
${pkgs.trust-dns}/bin/named --port 53 --zonedir ${zone-dir}/wan/ $@ &
|
||||
WANPID=$!
|
||||
${pkgs.trust-dns}/bin/named --port 1053 --zonedir ${zone-dir}/lan/ $@ &
|
||||
LANPID=$!
|
||||
|
||||
# wait until any of the processes exits, then kill them all and exit error
|
||||
while kill -0 $WANPID $LANPID ; do
|
||||
sleep 5
|
||||
done
|
||||
kill $WANPID $LANPID
|
||||
exit 1
|
||||
'';
|
||||
|
||||
sane.services.dyn-dns.restartOnChange = [ "trust-dns.service" ];
|
||||
|
||||
networking.nat.enable = true;
|
||||
networking.nat.extraCommands = ''
|
||||
# redirect incoming DNS requests from LAN addresses
|
||||
# to the LAN-specialized DNS service
|
||||
# N.B.: use the `nixos-*` chains instead of e.g. PREROUTING
|
||||
# because they get cleanly reset across activations or `systemctl restart firewall`
|
||||
# instead of accumulating cruft
|
||||
iptables -t nat -A nixos-nat-pre -p udp --dport 53 \
|
||||
-m iprange --src-range 10.78.76.0-10.78.79.255 \
|
||||
-j DNAT --to-destination :1053
|
||||
iptables -t nat -A nixos-nat-pre -p tcp --dport 53 \
|
||||
-m iprange --src-range 10.78.76.0-10.78.79.255 \
|
||||
-j DNAT --to-destination :1053
|
||||
'';
|
||||
|
||||
sane.ports.ports."1053" = {
|
||||
# because the NAT above redirects in nixos-nat-pre, LAN requests behave as though they arrived on the external interface at the redirected port.
|
||||
# TODO: try nixos-nat-post instead?
|
||||
protocol = [ "udp" "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
description = "colin-redirected-dns-for-lan-namespace";
|
||||
};
|
||||
}
|
||||
|
@@ -8,11 +8,12 @@
|
||||
./ids.nix
|
||||
./machine-id.nix
|
||||
./net.nix
|
||||
./nix-path
|
||||
./persist.nix
|
||||
./programs
|
||||
./secrets.nix
|
||||
./ssh.nix
|
||||
./users.nix
|
||||
./users
|
||||
./vpn.nix
|
||||
];
|
||||
|
||||
@@ -36,17 +37,30 @@
|
||||
nix.extraOptions = ''
|
||||
experimental-features = nix-command flakes
|
||||
'';
|
||||
# allow `nix-shell` (and probably nix-index?) to locate our patched and custom packages
|
||||
nix.nixPath = [
|
||||
"nixpkgs=${pkgs.path}"
|
||||
"nixpkgs-overlays=${../..}/overlays"
|
||||
];
|
||||
# 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;
|
||||
|
||||
systemd.services.nix-daemon.serviceConfig = {
|
||||
# the nix-daemon manages nix builders
|
||||
# kill nix-daemon subprocesses when systemd-oomd detects an out-of-memory condition
|
||||
# see:
|
||||
# - nixos PR that enabled systemd-oomd: <https://github.com/NixOS/nixpkgs/pull/169613>
|
||||
# - systemd's docs on these properties: <https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html#ManagedOOMSwap=auto%7Ckill>
|
||||
#
|
||||
# systemd's docs warn that without swap, systemd-oomd might not be able to react quick enough to save the system.
|
||||
# see `man oomd.conf` for further tunables that may help.
|
||||
#
|
||||
# alternatively, apply this more broadly with `systemd.oomd.enableSystemSlice = true` or `enableRootSlice`
|
||||
# TODO: also apply this to the guest user's slice (user-1100.slice)
|
||||
# TODO: also apply this to distccd
|
||||
ManagedOOMMemoryPressure = "kill";
|
||||
ManagedOOMSwap = "kill";
|
||||
};
|
||||
|
||||
# TODO: move this to gui machines only
|
||||
fonts = {
|
||||
enableDefaultFonts = true;
|
||||
fonts = with pkgs; [ font-awesome noto-fonts-emoji hack-font ];
|
||||
@@ -75,19 +89,6 @@
|
||||
# disable non-required packages like nano, perl, rsync, strace
|
||||
environment.defaultPackages = [];
|
||||
|
||||
# programs.vim.defaultEditor = true;
|
||||
environment.variables = {
|
||||
EDITOR = "vim";
|
||||
# git claims it should use EDITOR, but it doesn't!
|
||||
GIT_EDITOR = "vim";
|
||||
# TODO: these should be moved to `home.sessionVariables` (home-manager)
|
||||
# Electron apps should use native wayland backend:
|
||||
# https://nixos.wiki/wiki/Slack#Wayland
|
||||
# Discord under sway crashes with this.
|
||||
# NIXOS_OZONE_WL = "1";
|
||||
# LIBGL_ALWAYS_SOFTWARE = "1";
|
||||
};
|
||||
|
||||
# dconf docs: <https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/desktop_migration_and_administration_guide/profiles>
|
||||
# find keys/values with `dconf dump /`
|
||||
programs.dconf.enable = true;
|
||||
|
@@ -1,3 +1,6 @@
|
||||
# where to find good stuff?
|
||||
# - podcast rec thread: <https://lemmy.ml/post/1565858>
|
||||
#
|
||||
# candidates:
|
||||
# - The Nonlinear Library (podcast): <https://forum.effectivealtruism.org/posts/JTZTBienqWEAjGDRv/listen-to-more-ea-content-with-the-nonlinear-library>
|
||||
# - has ~10 posts per day, text-to-speech; i would need better tagging before adding this
|
||||
@@ -76,15 +79,17 @@ let
|
||||
## Multidisciplinary Association for Psychedelic Studies
|
||||
(fromDb "mapspodcast.libsyn.com" // uncat)
|
||||
(fromDb "allinchamathjason.libsyn.com" // pol)
|
||||
(fromDb "acquired.libsyn.com" // tech)
|
||||
(fromDb "feeds.transistor.fm/acquired" // tech)
|
||||
## ACQ2 - more "Acquired" episodes
|
||||
(fromDb "acquiredlpbonussecretsecret.libsyn.com" // tech)
|
||||
# The Intercept - Deconstructed; also available: <rss.acast.com/deconstructed>
|
||||
(fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol)
|
||||
# The Intercept - Deconstructed
|
||||
(fromDb "rss.acast.com/deconstructed")
|
||||
# (fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol) #< possible URL rot
|
||||
## The Daily
|
||||
(mkPod "https://feeds.simplecast.com/54nAGcIl" // pol // daily)
|
||||
# The Intercept - Intercepted; also available: <https://rss.acast.com/intercepted-with-jeremy-scahill>
|
||||
(fromDb "rss.prod.firstlook.media/intercepted/podcast.rss" // pol)
|
||||
# The Intercept - Intercepted
|
||||
(fromDb "rss.acast.com/intercepted-with-jeremy-scahill")
|
||||
# (fromDb "rss.prod.firstlook.media/intercepted/podcast.rss" // pol) #< possible URL rot
|
||||
(fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
|
||||
## Eric Weinstein
|
||||
(fromDb "rss.art19.com/the-portal" // rat)
|
||||
@@ -102,6 +107,8 @@ let
|
||||
(fromDb "feeds.megaphone.fm/recodedecode" // tech)
|
||||
## Matrix (chat) Live
|
||||
(fromDb "feed.podbean.com/matrixlive/feed.xml" // tech)
|
||||
(fromDb "cast.postmarketos.org" // tech)
|
||||
(fromDb "podcast.thelinuxexp.com" // tech)
|
||||
## Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232>
|
||||
(fromDb "rss.art19.com/your-welcome" // pol)
|
||||
(fromDb "seattlenice.buzzsprout.com" // pol)
|
||||
|
@@ -1,72 +1,131 @@
|
||||
{ pkgs, ... }:
|
||||
# docs
|
||||
# - x-systemd options: <https://www.freedesktop.org/software/systemd/man/systemd.mount.html>
|
||||
|
||||
let sshOpts = rec {
|
||||
fsType = "fuse.sshfs";
|
||||
optionsBase = [
|
||||
"x-systemd.automount"
|
||||
{ pkgs, sane-lib, ... }:
|
||||
|
||||
let fsOpts = rec {
|
||||
common = [
|
||||
"_netdev"
|
||||
"user"
|
||||
"noatime"
|
||||
"user" # allow any user with access to the device to mount the fs
|
||||
"x-systemd.requires=network-online.target"
|
||||
"x-systemd.after=network-online.target"
|
||||
"x-systemd.mount-timeout=10s" # how long to wait for mount **and** how long to wait for unmount
|
||||
];
|
||||
auto = [ "x-systemd.automount" ];
|
||||
noauto = [ "noauto" ]; # don't mount as part of remote-fs.target
|
||||
wg = [
|
||||
"x-systemd.requires=wireguard-wg-home.service"
|
||||
"x-systemd.after=wireguard-wg-home.service"
|
||||
];
|
||||
|
||||
ssh = common ++ [
|
||||
"identityfile=/home/colin/.ssh/id_ed25519"
|
||||
"allow_other"
|
||||
"default_permissions"
|
||||
];
|
||||
optionsColin = optionsBase ++ [
|
||||
sshColin = ssh ++ [
|
||||
"transform_symlinks"
|
||||
"idmap=user"
|
||||
"uid=1000"
|
||||
"gid=100"
|
||||
];
|
||||
|
||||
optionsRoot = optionsBase ++ [
|
||||
sshRoot = ssh ++ [
|
||||
# we don't transform_symlinks because that breaks the validity of remote /nix stores
|
||||
"sftp_server=/run/wrappers/bin/sudo\\040/run/current-system/sw/libexec/sftp-server"
|
||||
];
|
||||
# in the event of hunt NFS mounts, consider:
|
||||
# - <https://unix.stackexchange.com/questions/31979/stop-broken-nfs-mounts-from-locking-a-directory>
|
||||
|
||||
# NFS options: <https://linux.die.net/man/5/nfs>
|
||||
# actimeo=n = how long (in seconds) to cache file/dir attributes (default: 3-60s)
|
||||
# bg = retry failed mounts in the background
|
||||
# retry=n = for how many minutes `mount` will retry NFS mount operation
|
||||
# soft = on "major timeout", report I/O error to userspace
|
||||
# retrans=n = how many times to retry a NFS request before giving userspace a "server not responding" error (default: 3)
|
||||
# timeo=n = number of *deciseconds* to wait for a response before retrying it (default: 600)
|
||||
# note: client uses a linear backup, so the second request will have double this timeout, then triple, etc.
|
||||
nfs = common ++ [
|
||||
# "actimeo=10"
|
||||
"bg"
|
||||
"retrans=4"
|
||||
"retry=0"
|
||||
"soft"
|
||||
"timeo=15"
|
||||
"nofail" # don't fail remote-fs.target when this mount fails (not an option for sshfs else would be common)
|
||||
];
|
||||
};
|
||||
in
|
||||
{
|
||||
# fileSystems."/mnt/servo-nfs" = {
|
||||
# device = "servo-hn:/";
|
||||
# noCheck = true;
|
||||
# fsType = "nfs";
|
||||
# options = fsOpts.nfs ++ fsOpts.auto ++ fsOpts.wg;
|
||||
# };
|
||||
fileSystems."/mnt/servo-nfs/media" = {
|
||||
device = "servo-hn:/media";
|
||||
noCheck = true;
|
||||
fsType = "nfs";
|
||||
options = fsOpts.nfs ++ fsOpts.auto ++ fsOpts.wg;
|
||||
};
|
||||
# fileSystems."/mnt/servo-media-nfs" = {
|
||||
# device = "servo-hn:/media";
|
||||
# noCheck = true;
|
||||
# fsType = "nfs";
|
||||
# options = fsOpts.common ++ fsOpts.auto;
|
||||
# };
|
||||
sane.fs."/mnt/servo-media" = sane-lib.fs.wantedSymlinkTo "/mnt/servo-nfs/media";
|
||||
|
||||
fileSystems."/mnt/servo-media-wan" = {
|
||||
device = "colin@uninsane.org:/var/lib/uninsane/media";
|
||||
fsType = "fuse.sshfs";
|
||||
options = fsOpts.sshColin ++ fsOpts.noauto;
|
||||
noCheck = true;
|
||||
};
|
||||
sane.fs."/mnt/servo-media-wan" = sane-lib.fs.wantedDir;
|
||||
fileSystems."/mnt/servo-media-lan" = {
|
||||
device = "colin@servo:/var/lib/uninsane/media";
|
||||
fsType = "fuse.sshfs";
|
||||
options = fsOpts.sshColin ++ fsOpts.noauto;
|
||||
noCheck = true;
|
||||
};
|
||||
sane.fs."/mnt/servo-media-lan" = sane-lib.fs.wantedDir;
|
||||
fileSystems."/mnt/servo-root-wan" = {
|
||||
device = "colin@uninsane.org:/";
|
||||
fsType = "fuse.sshfs";
|
||||
options = fsOpts.sshRoot ++ fsOpts.noauto;
|
||||
noCheck = true;
|
||||
};
|
||||
sane.fs."/mnt/servo-root-wan" = sane-lib.fs.wantedDir;
|
||||
fileSystems."/mnt/servo-root-lan" = {
|
||||
device = "colin@servo:/";
|
||||
fsType = "fuse.sshfs";
|
||||
options = fsOpts.sshRoot ++ fsOpts.noauto;
|
||||
noCheck = true;
|
||||
};
|
||||
sane.fs."/mnt/servo-root-lan" = sane-lib.fs.wantedDir;
|
||||
fileSystems."/mnt/desko-home" = {
|
||||
device = "colin@desko:/home/colin";
|
||||
fsType = "fuse.sshfs";
|
||||
options = fsOpts.sshColin ++ fsOpts.noauto;
|
||||
noCheck = true;
|
||||
};
|
||||
sane.fs."/mnt/desko-home" = sane-lib.fs.wantedDir;
|
||||
fileSystems."/mnt/desko-root" = {
|
||||
device = "colin@desko:/";
|
||||
fsType = "fuse.sshfs";
|
||||
options = fsOpts.sshRoot ++ fsOpts.noauto;
|
||||
noCheck = true;
|
||||
};
|
||||
sane.fs."/mnt/desko-root" = sane-lib.fs.wantedDir;
|
||||
|
||||
environment.pathsToLink = [
|
||||
# needed to achieve superuser access for user-mounted filesystems (see optionsRoot above)
|
||||
# we can only link whole directories here, even though we're only interested in pkgs.openssh
|
||||
"/libexec"
|
||||
];
|
||||
|
||||
fileSystems."/mnt/servo-media-wan" = {
|
||||
device = "colin@uninsane.org:/var/lib/uninsane/media";
|
||||
inherit (sshOpts) fsType;
|
||||
options = sshOpts.optionsColin;
|
||||
noCheck = true;
|
||||
};
|
||||
fileSystems."/mnt/servo-media-lan" = {
|
||||
device = "colin@servo:/var/lib/uninsane/media";
|
||||
inherit (sshOpts) fsType;
|
||||
options = sshOpts.optionsColin;
|
||||
noCheck = true;
|
||||
};
|
||||
fileSystems."/mnt/servo-root-wan" = {
|
||||
device = "colin@uninsane.org:/";
|
||||
inherit (sshOpts) fsType;
|
||||
options = sshOpts.optionsRoot;
|
||||
noCheck = true;
|
||||
};
|
||||
fileSystems."/mnt/servo-root-lan" = {
|
||||
device = "colin@servo:/";
|
||||
inherit (sshOpts) fsType;
|
||||
options = sshOpts.optionsRoot;
|
||||
noCheck = true;
|
||||
};
|
||||
fileSystems."/mnt/desko-home" = {
|
||||
device = "colin@desko:/home/colin";
|
||||
inherit (sshOpts) fsType;
|
||||
options = sshOpts.optionsColin;
|
||||
noCheck = true;
|
||||
};
|
||||
fileSystems."/mnt/desko-root" = {
|
||||
device = "colin@desko:/";
|
||||
inherit (sshOpts) fsType;
|
||||
options = sshOpts.optionsRoot;
|
||||
noCheck = true;
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.sshfs-fuse
|
||||
];
|
||||
|
@@ -7,5 +7,6 @@
|
||||
generated.script.script = builtins.readFile ../../../scripts/init-keyring;
|
||||
# TODO: is this `wantedBy` needed? can we inherit it?
|
||||
wantedBy = [ config.sane.fs."/home/colin/private".unit ];
|
||||
wantedBeforeBy = [ ]; # don't created this as part of `multi-user.target`
|
||||
};
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
{ config, sane-lib, ...}:
|
||||
|
||||
let
|
||||
# TODO: should move all of this into `sane.programs` to not ship broken associations
|
||||
www = config.sane.programs.web-browser.config.browser.desktop;
|
||||
pdf = "org.gnome.Evince.desktop";
|
||||
md = "obsidian.desktop";
|
||||
@@ -8,6 +9,7 @@ let
|
||||
video = "vlc.desktop";
|
||||
# audio = "mpv.desktop";
|
||||
audio = "vlc.desktop";
|
||||
email = "aerc.desktop";
|
||||
in
|
||||
{
|
||||
|
||||
@@ -39,5 +41,6 @@ in
|
||||
# RICH-TEXT DOCUMENTS
|
||||
"application/pdf" = pdf;
|
||||
"text/markdown" = md;
|
||||
"x-scheme-handler/mailto" = email;
|
||||
};
|
||||
}
|
||||
|
@@ -40,6 +40,8 @@
|
||||
sane.ids.lemmy.gid = 2408;
|
||||
sane.ids.pict-rs.uid = 2409;
|
||||
sane.ids.pict-rs.gid = 2409;
|
||||
sane.ids.sftpgo.uid = 2410;
|
||||
sane.ids.sftpgo.gid = 2410;
|
||||
|
||||
sane.ids.colin.uid = 1000;
|
||||
sane.ids.guest.uid = 1100;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
# the default backend is "wpa_supplicant".
|
||||
@@ -20,4 +20,22 @@
|
||||
General.RoamThreshold = "-52"; # default -70
|
||||
General.RoamThreshold5G = "-52"; # default -76
|
||||
};
|
||||
|
||||
# plugins mostly add support for establishing different VPN connections.
|
||||
# the default plugin set includes mostly proprietary VPNs:
|
||||
# - fortisslvpn (Fortinet)
|
||||
# - iodine (DNS tunnels)
|
||||
# - l2tp
|
||||
# - openconnect (Cisco Anyconnect / Juniper / ocserv)
|
||||
# - openvpn
|
||||
# - vpnc (Cisco VPN)
|
||||
# - sstp
|
||||
#
|
||||
# i don't use these, and notably they drag in huge dependency sets and don't cross compile well.
|
||||
# e.g. openconnect drags in webkitgtk (for SSO)!
|
||||
networking.networkmanager.plugins = lib.mkForce [];
|
||||
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
1900 # to received UPnP advertisements. required by sane-ip-check-upnp
|
||||
];
|
||||
}
|
||||
|
13
hosts/common/nix-path/default.nix
Normal file
13
hosts/common/nix-path/default.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
# allow `nix-shell` (and probably nix-index?) to locate our patched and custom packages
|
||||
nix.nixPath = [
|
||||
"nixpkgs=${pkgs.path}"
|
||||
# note the import starts at repo root: this allows `./overlay/default.nix` to access the stuff at the root
|
||||
# "nixpkgs-overlays=${../../..}/hosts/common/nix-path/overlay"
|
||||
# as long as my system itself doesn't rely on NIXPKGS at runtime, we can point the overlays to git
|
||||
# to avoid switching so much during development
|
||||
"nixpkgs-overlays=/home/colin/dev/nixos/hosts/common/nix-path/overlay"
|
||||
];
|
||||
}
|
4
hosts/common/nix-path/overlay/default.nix
Normal file
4
hosts/common/nix-path/overlay/default.nix
Normal file
@@ -0,0 +1,4 @@
|
||||
# XXX: NIX_PATH=...:nixpkgs-overlays=... will import every overlay in the directory
|
||||
# so we prefer to give it a directory with just this *one* overlay, otherwise it imports conflicting overlays
|
||||
# and gets stuck in a loop until it OOMs
|
||||
import ../../../../overlays/all.nix
|
392
hosts/common/programs/assorted.nix
Normal file
392
hosts/common/programs/assorted.nix
Normal file
@@ -0,0 +1,392 @@
|
||||
{ lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (builtins) attrNames;
|
||||
|
||||
flattenedPkgs = pkgs // (with pkgs; {
|
||||
# XXX can't `inherit` a nested attr, so we move them to the toplevel
|
||||
"cacert.unbundled" = pkgs.cacert.unbundled;
|
||||
"gnome.cheese" = gnome.cheese;
|
||||
"gnome.dconf-editor" = gnome.dconf-editor;
|
||||
"gnome.file-roller" = gnome.file-roller;
|
||||
"gnome.gnome-disk-utility" = gnome.gnome-disk-utility;
|
||||
"gnome.gnome-maps" = gnome.gnome-maps;
|
||||
"gnome.nautilus" = gnome.nautilus;
|
||||
"gnome.gnome-system-monitor" = gnome.gnome-system-monitor;
|
||||
"gnome.gnome-terminal" = gnome.gnome-terminal;
|
||||
"gnome.gnome-weather" = gnome.gnome-weather;
|
||||
"gnome.totem" = gnome.totem;
|
||||
"libsForQt5.plasmatube" = libsForQt5.plasmatube;
|
||||
});
|
||||
|
||||
sysadminPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
btrfs-progs
|
||||
"cacert.unbundled" # some services require unbundled /etc/ssl/certs
|
||||
cryptsetup
|
||||
dig
|
||||
efibootmgr
|
||||
fatresize
|
||||
fd
|
||||
file
|
||||
gawk
|
||||
git
|
||||
gptfdisk
|
||||
hdparm
|
||||
htop
|
||||
iftop
|
||||
inetutils # for telnet
|
||||
iotop
|
||||
iptables
|
||||
jq
|
||||
killall
|
||||
lsof
|
||||
miniupnpc
|
||||
nano
|
||||
neovim
|
||||
netcat
|
||||
nethogs
|
||||
nmap
|
||||
openssl
|
||||
parted
|
||||
pciutils
|
||||
powertop
|
||||
pstree
|
||||
ripgrep
|
||||
screen
|
||||
smartmontools
|
||||
socat
|
||||
strace
|
||||
subversion
|
||||
tcpdump
|
||||
tree
|
||||
usbutils
|
||||
wget
|
||||
wirelesstools # iwlist
|
||||
;
|
||||
};
|
||||
sysadminExtraPkgs = {
|
||||
# application-specific packages
|
||||
inherit (pkgs)
|
||||
backblaze-b2
|
||||
duplicity
|
||||
sqlite # to debug sqlite3 databases
|
||||
;
|
||||
};
|
||||
|
||||
iphonePkgs = {
|
||||
inherit (pkgs)
|
||||
ifuse
|
||||
ipfs
|
||||
libimobiledevice
|
||||
;
|
||||
};
|
||||
|
||||
tuiPkgs = {
|
||||
inherit (pkgs)
|
||||
aerc # email client
|
||||
msmtp # sendmail
|
||||
offlineimap # email mailox sync
|
||||
sfeed # RSS fetcher
|
||||
visidata # TUI spreadsheet viewer/editor
|
||||
w3m
|
||||
;
|
||||
};
|
||||
|
||||
consoleMediaPkgs = {
|
||||
inherit (pkgs)
|
||||
ffmpeg
|
||||
imagemagick
|
||||
sox
|
||||
yt-dlp
|
||||
;
|
||||
};
|
||||
# TODO: split these into smaller groups.
|
||||
# - moby doesn't want a lot of these.
|
||||
# - categories like
|
||||
# - dev?
|
||||
# - debugging?
|
||||
consolePkgs = {
|
||||
inherit (pkgs)
|
||||
alsaUtils # for aplay, speaker-test
|
||||
# cdrtools
|
||||
clinfo
|
||||
dmidecode
|
||||
efivar
|
||||
# flashrom
|
||||
fwupd
|
||||
gh # MS GitHub cli
|
||||
git # needed as a user package, for config.
|
||||
# gnupg
|
||||
# gocryptfs
|
||||
# gopass
|
||||
# gopass-jsonapi
|
||||
kitty # TODO: move to GUI, but `ssh servo` from kitty sets `TERM=xterm-kitty` in the remove and breaks things
|
||||
libsecret # for managing user keyrings. TODO: what needs this? lift into the consumer
|
||||
lm_sensors # for sensors-detect. TODO: what needs this? lift into the consumer
|
||||
lshw
|
||||
# memtester
|
||||
neovim # needed as a user package, for swap persistence
|
||||
# nettools
|
||||
# networkmanager
|
||||
nix-index
|
||||
nixpkgs-review
|
||||
# nixos-generators
|
||||
nmon
|
||||
# node2nix
|
||||
# oathToolkit # for oathtool
|
||||
# ponymix
|
||||
pulsemixer
|
||||
python3
|
||||
ripgrep # needed as a user package so that its user-level config file can be installed
|
||||
rsync
|
||||
# python3Packages.eyeD3 # music tagging
|
||||
sane-scripts
|
||||
sequoia
|
||||
snapper
|
||||
sops
|
||||
speedtest-cli
|
||||
# ssh-to-age
|
||||
sudo
|
||||
# tageditor # music tagging
|
||||
unar
|
||||
wireguard-tools
|
||||
xdg-terminal-exec
|
||||
xdg-utils # for xdg-open
|
||||
# yarn
|
||||
zsh
|
||||
;
|
||||
};
|
||||
|
||||
guiPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
# celluloid # mpv frontend
|
||||
cozy # audiobook player
|
||||
# emote
|
||||
evince # works on phosh
|
||||
|
||||
# { pkg = fluffychat-moby; persist.plaintext = [ ".local/share/chat.fluffy.fluffychat" ]; } # TODO: ship normal fluffychat on non-moby?
|
||||
|
||||
# foliate # e-book reader
|
||||
|
||||
# XXX by default fractal stores its state in ~/.local/share/<UUID>.
|
||||
# after logging in, manually change ~/.local/share/keyrings/... to point it to some predictable subdir.
|
||||
# then reboot (so that libsecret daemon re-loads the keyring...?)
|
||||
# { pkg = fractal-latest; persist.private = [ ".local/share/fractal" ]; }
|
||||
# { pkg = fractal-next; persist.private = [ ".local/share/fractal" ]; }
|
||||
|
||||
# "gnome.cheese"
|
||||
# gnome-feeds # RSS reader (with claimed mobile support)
|
||||
"gnome.file-roller"
|
||||
# "gnome.gnome-maps" # works on phosh
|
||||
"gnome.nautilus"
|
||||
# gnome-podcasts
|
||||
# "gnome.gnome-system-monitor"
|
||||
# "gnome.gnome-terminal" # works on phosh
|
||||
# "gnome.gnome-weather"
|
||||
gpodder
|
||||
gthumb
|
||||
jellyfin-media-player
|
||||
komikku
|
||||
koreader
|
||||
lemoa # lemmy app
|
||||
# lollypop
|
||||
mepo # maps viewer
|
||||
# mpv
|
||||
# networkmanagerapplet
|
||||
# newsflash
|
||||
nheko
|
||||
pavucontrol
|
||||
# picard # music tagging
|
||||
# "libsForQt5.plasmatube" # Youtube player
|
||||
soundconverter
|
||||
# sublime-music
|
||||
# tdesktop # broken on phosh
|
||||
# tokodon
|
||||
tuba # mastodon/pleroma client (stores pw in keyring)
|
||||
vlc
|
||||
# pleroma client (Electron). input is broken on phosh. TODO(2023/02/02): fix electron19 input (insecure)
|
||||
# whalebird
|
||||
xterm # broken on phosh
|
||||
;
|
||||
};
|
||||
desktopGuiPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
audacity
|
||||
brave # for the integrated wallet -- as a backup
|
||||
chromium
|
||||
dino
|
||||
electrum
|
||||
element-desktop
|
||||
# font-manager #< depends on webkitgtk4_0 (expensive to build)
|
||||
gajim # XMPP client
|
||||
gimp # broken on phosh
|
||||
"gnome.dconf-editor"
|
||||
"gnome.gnome-disk-utility"
|
||||
# "gnome.totem" # video player, supposedly supports UPnP
|
||||
handbrake
|
||||
hase
|
||||
inkscape
|
||||
kdenlive
|
||||
kid3 # audio tagging
|
||||
krita
|
||||
libreoffice-fresh
|
||||
mumble
|
||||
obsidian
|
||||
slic3r
|
||||
steam
|
||||
wireshark # could maybe ship the cli as sysadmin pkg
|
||||
;
|
||||
};
|
||||
x86GuiPkgs = {
|
||||
inherit (pkgs)
|
||||
discord
|
||||
|
||||
# kaiteki # Pleroma client
|
||||
# gnome.zenity # for kaiteki (it will use qarma, kdialog, or zenity)
|
||||
# gpt2tc # XXX: unreliable mirror
|
||||
|
||||
# logseq # Personal Knowledge Management
|
||||
losslesscut-bin
|
||||
makemkv
|
||||
monero-gui
|
||||
signal-desktop
|
||||
spotify
|
||||
tor-browser-bundle-bin
|
||||
zecwallet-lite
|
||||
;
|
||||
};
|
||||
|
||||
# packages not part of any package set; not enabled by default
|
||||
otherPkgs = {
|
||||
inherit (pkgs)
|
||||
lemmy-server
|
||||
mx-sanebot
|
||||
stepmania
|
||||
;
|
||||
};
|
||||
|
||||
# define -- but don't enable -- the packages in some attrset.
|
||||
declarePkgs = pkgsAsAttrs: lib.mapAttrs (_n: p: {
|
||||
# no need to actually define the package here: it's defaulted
|
||||
# package = mkDefault p;
|
||||
}) pkgsAsAttrs;
|
||||
in
|
||||
{
|
||||
sane.programs = lib.mkMerge [
|
||||
(declarePkgs consoleMediaPkgs)
|
||||
(declarePkgs consolePkgs)
|
||||
(declarePkgs desktopGuiPkgs)
|
||||
(declarePkgs guiPkgs)
|
||||
(declarePkgs iphonePkgs)
|
||||
(declarePkgs sysadminPkgs)
|
||||
(declarePkgs sysadminExtraPkgs)
|
||||
(declarePkgs tuiPkgs)
|
||||
(declarePkgs x86GuiPkgs)
|
||||
(declarePkgs otherPkgs)
|
||||
{
|
||||
# link the various package sets into their own meta packages
|
||||
consoleMediaUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames consoleMediaPkgs;
|
||||
};
|
||||
consoleUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames consolePkgs;
|
||||
};
|
||||
desktopGuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames desktopGuiPkgs;
|
||||
};
|
||||
guiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = (attrNames guiPkgs)
|
||||
++ [ "web-browser" ]
|
||||
++ [ "tuiApps" ]
|
||||
++ lib.optional (pkgs.system == "x86_64-linux") "x86GuiApps";
|
||||
};
|
||||
iphoneUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames iphonePkgs;
|
||||
};
|
||||
sysadminUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames sysadminPkgs;
|
||||
};
|
||||
sysadminExtraUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames sysadminExtraPkgs;
|
||||
};
|
||||
tuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames tuiPkgs;
|
||||
};
|
||||
x86GuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames x86GuiPkgs;
|
||||
};
|
||||
}
|
||||
{
|
||||
# nontrivial package definitions
|
||||
|
||||
dino.persist.private = [ ".local/share/dino" ];
|
||||
|
||||
# creds, but also 200 MB of node modules, etc
|
||||
discord.persist.private = [ ".config/discord" ];
|
||||
|
||||
# creds/session keys, etc
|
||||
element-desktop.persist.private = [ ".config/Element" ];
|
||||
|
||||
# `emote` will show a first-run dialog based on what's in this directory.
|
||||
# mostly, it just keeps a LRU of previously-used emotes to optimize display order.
|
||||
# TODO: package [smile](https://github.com/mijorus/smile) for probably a better mobile experience.
|
||||
emote.persist.plaintext = [ ".local/share/Emote" ];
|
||||
|
||||
# MS GitHub stores auth token in .config
|
||||
# TODO: we can populate gh's stuff statically; it even lets us use the same oauth across machines
|
||||
gh.persist.private = [ ".config/gh" ];
|
||||
|
||||
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
|
||||
# XXX: is it really safe to persist this? it doesn't have info that could de-anonymize if captured?
|
||||
monero-gui.persist.plaintext = [ ".bitmonero" ];
|
||||
|
||||
mumble.persist.private = [ ".local/share/Mumble" ];
|
||||
|
||||
# not strictly necessary, but allows caching articles; offline use, etc.
|
||||
nheko.persist.private = [
|
||||
".config/nheko" # config file (including client token)
|
||||
".cache/nheko" # media cache
|
||||
".local/share/nheko" # per-account state database
|
||||
];
|
||||
|
||||
# settings (electron app)
|
||||
obsidian.persist.plaintext = [ ".config/obsidian" ];
|
||||
|
||||
# creds, media
|
||||
signal-desktop.persist.private = [ ".config/Signal" ];
|
||||
|
||||
# printer/filament settings
|
||||
slic3r.persist.plaintext = [ ".Slic3r" ];
|
||||
|
||||
# creds, widevine .so download. TODO: could easily manage these statically.
|
||||
spotify.persist.plaintext = [ ".config/spotify" ];
|
||||
|
||||
tdesktop.persist.private = [ ".local/share/TelegramDesktop" ];
|
||||
|
||||
tokodon.persist.private = [ ".cache/KDE/tokodon" ];
|
||||
|
||||
# hardenedMalloc solves a crash at startup
|
||||
# TODO 2023/02/02: is this safe to remove yet?
|
||||
tor-browser-bundle-bin.package = pkgs.tor-browser-bundle-bin.override {
|
||||
useHardenedMalloc = false;
|
||||
};
|
||||
|
||||
whalebird.persist.private = [ ".config/Whalebird" ];
|
||||
|
||||
yarn.persist.plaintext = [ ".cache/yarn" ];
|
||||
|
||||
# zcash coins. safe to delete, just slow to regenerate (10-60 minutes)
|
||||
zecwallet-lite.persist.private = [ ".zcash" ];
|
||||
}
|
||||
];
|
||||
}
|
11
hosts/common/programs/cozy.nix
Normal file
11
hosts/common/programs/cozy.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
sane.programs.cozy = {
|
||||
# cozy uses a sqlite db for its config and exposes no CLI options other than --help and --debug
|
||||
persist.plaintext = [
|
||||
".local/share/cozy" # sqlite db (config & index?)
|
||||
".cache/cozy" # offline cache
|
||||
];
|
||||
};
|
||||
}
|
@@ -1,274 +1,32 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (builtins) attrNames concatLists;
|
||||
inherit (lib) mapAttrs mapAttrsToList mkDefault mkIf mkMerge optional;
|
||||
|
||||
flattenedPkgs = pkgs // (with pkgs; {
|
||||
# XXX can't `inherit` a nested attr, so we move them to the toplevel
|
||||
"cacert.unbundled" = pkgs.cacert.unbundled;
|
||||
"gnome.cheese" = gnome.cheese;
|
||||
"gnome.dconf-editor" = gnome.dconf-editor;
|
||||
"gnome.file-roller" = gnome.file-roller;
|
||||
"gnome.gnome-disk-utility" = gnome.gnome-disk-utility;
|
||||
"gnome.gnome-maps" = gnome.gnome-maps;
|
||||
"gnome.nautilus" = gnome.nautilus;
|
||||
"gnome.gnome-system-monitor" = gnome.gnome-system-monitor;
|
||||
"gnome.gnome-terminal" = gnome.gnome-terminal;
|
||||
"gnome.gnome-weather" = gnome.gnome-weather;
|
||||
"gnome.totem" = gnome.totem;
|
||||
"libsForQt5.plasmatube" = libsForQt5.plasmatube;
|
||||
});
|
||||
|
||||
sysadminPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
btrfs-progs
|
||||
"cacert.unbundled" # some services require unbundled /etc/ssl/certs
|
||||
cryptsetup
|
||||
dig
|
||||
efibootmgr
|
||||
fatresize
|
||||
fd
|
||||
file
|
||||
gawk
|
||||
git
|
||||
gptfdisk
|
||||
hdparm
|
||||
htop
|
||||
iftop
|
||||
inetutils # for telnet
|
||||
iotop
|
||||
iptables
|
||||
jq
|
||||
killall
|
||||
lsof
|
||||
nano
|
||||
netcat
|
||||
nethogs
|
||||
nmap
|
||||
openssl
|
||||
parted
|
||||
pciutils
|
||||
powertop
|
||||
pstree
|
||||
ripgrep
|
||||
screen
|
||||
smartmontools
|
||||
socat
|
||||
strace
|
||||
subversion
|
||||
tcpdump
|
||||
tree
|
||||
usbutils
|
||||
wget
|
||||
;
|
||||
};
|
||||
sysadminExtraPkgs = {
|
||||
# application-specific packages
|
||||
inherit (pkgs)
|
||||
backblaze-b2
|
||||
duplicity
|
||||
sqlite # to debug sqlite3 databases
|
||||
;
|
||||
};
|
||||
|
||||
iphonePkgs = {
|
||||
inherit (pkgs)
|
||||
ifuse
|
||||
ipfs
|
||||
libimobiledevice
|
||||
;
|
||||
};
|
||||
|
||||
tuiPkgs = {
|
||||
inherit (pkgs)
|
||||
aerc # email client
|
||||
offlineimap # email mailox sync
|
||||
visidata # TUI spreadsheet viewer/editor
|
||||
w3m
|
||||
;
|
||||
};
|
||||
|
||||
# TODO: split these into smaller groups.
|
||||
# - transcoders (ffmpeg, imagemagick) only wanted on desko/lappy ("powerutils"?)
|
||||
consolePkgs = {
|
||||
inherit (pkgs)
|
||||
cdrtools
|
||||
dmidecode
|
||||
efivar
|
||||
flashrom
|
||||
fwupd
|
||||
gh # MS GitHub cli
|
||||
git # needed as a user package, for config.
|
||||
gnupg
|
||||
gocryptfs
|
||||
gopass # TODO: shouldn't be needed here
|
||||
gopass-jsonapi
|
||||
imagemagick
|
||||
kitty # TODO: move to GUI, but `ssh servo` from kitty sets `TERM=xterm-kitty` in the remove and breaks things
|
||||
libsecret # for managing user keyrings
|
||||
lm_sensors # for sensors-detect
|
||||
lshw
|
||||
ffmpeg
|
||||
memtester
|
||||
neovim
|
||||
# nettools
|
||||
# networkmanager
|
||||
nixpkgs-review
|
||||
# nixos-generators
|
||||
nmon
|
||||
# node2nix
|
||||
# oathToolkit # for oathtool
|
||||
# ponymix
|
||||
pulsemixer
|
||||
python3
|
||||
ripgrep # needed as a user package, for config.
|
||||
rsync
|
||||
# python3Packages.eyeD3 # music tagging
|
||||
sane-scripts
|
||||
sequoia
|
||||
snapper
|
||||
sops
|
||||
sox
|
||||
speedtest-cli
|
||||
# ssh-to-age
|
||||
sudo
|
||||
# tageditor # music tagging
|
||||
unar
|
||||
wireguard-tools
|
||||
xdg-utils # for xdg-open
|
||||
# yarn
|
||||
# youtube-dl
|
||||
yt-dlp
|
||||
zsh
|
||||
;
|
||||
};
|
||||
|
||||
guiPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
# celluloid # mpv frontend
|
||||
clinfo
|
||||
emote
|
||||
evince # works on phosh
|
||||
|
||||
# { pkg = fluffychat-moby; persist.plaintext = [ ".local/share/chat.fluffy.fluffychat" ]; } # TODO: ship normal fluffychat on non-moby?
|
||||
|
||||
# foliate # e-book reader
|
||||
|
||||
# XXX by default fractal stores its state in ~/.local/share/<UUID>.
|
||||
# after logging in, manually change ~/.local/share/keyrings/... to point it to some predictable subdir.
|
||||
# then reboot (so that libsecret daemon re-loads the keyring...?)
|
||||
# { pkg = fractal-latest; persist.private = [ ".local/share/fractal" ]; }
|
||||
# { pkg = fractal-next; persist.private = [ ".local/share/fractal" ]; }
|
||||
|
||||
# "gnome.cheese"
|
||||
"gnome.dconf-editor"
|
||||
# gnome-feeds # RSS reader (with claimed mobile support)
|
||||
"gnome.file-roller"
|
||||
# "gnome.gnome-maps" # works on phosh
|
||||
"gnome.nautilus"
|
||||
# gnome-podcasts
|
||||
"gnome.gnome-system-monitor"
|
||||
# "gnome.gnome-terminal" # works on phosh
|
||||
# "gnome.gnome-weather"
|
||||
gpodder
|
||||
gthumb
|
||||
jellyfin-media-player
|
||||
# lollypop
|
||||
# mpv
|
||||
networkmanagerapplet
|
||||
# newsflash
|
||||
nheko
|
||||
pavucontrol
|
||||
# picard # music tagging
|
||||
playerctl
|
||||
# "libsForQt5.plasmatube" # Youtube player
|
||||
soundconverter
|
||||
sublime-music
|
||||
# tdesktop # broken on phosh
|
||||
# tokodon
|
||||
vlc
|
||||
# pleroma client (Electron). input is broken on phosh. TODO(2023/02/02): fix electron19 input (insecure)
|
||||
# whalebird
|
||||
xterm # broken on phosh
|
||||
;
|
||||
};
|
||||
desktopGuiPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
audacity
|
||||
brave # for the integrated wallet -- as a backup
|
||||
chromium
|
||||
dino
|
||||
electrum
|
||||
element-desktop
|
||||
font-manager
|
||||
gajim # XMPP client
|
||||
gimp # broken on phosh
|
||||
"gnome.gnome-disk-utility"
|
||||
# "gnome.totem" # video player, supposedly supports UPnP
|
||||
handbrake
|
||||
hase
|
||||
inkscape
|
||||
kdenlive
|
||||
kid3 # audio tagging
|
||||
krita
|
||||
libreoffice-fresh
|
||||
mumble
|
||||
obsidian
|
||||
slic3r
|
||||
steam
|
||||
wireshark # could maybe ship the cli as sysadmin pkg
|
||||
;
|
||||
};
|
||||
x86GuiPkgs = {
|
||||
inherit (pkgs)
|
||||
discord
|
||||
|
||||
# kaiteki # Pleroma client
|
||||
# gnome.zenity # for kaiteki (it will use qarma, kdialog, or zenity)
|
||||
# gpt2tc # XXX: unreliable mirror
|
||||
|
||||
# logseq # Personal Knowledge Management
|
||||
losslesscut-bin
|
||||
makemkv
|
||||
monero-gui
|
||||
signal-desktop
|
||||
spotify
|
||||
tor-browser-bundle-bin
|
||||
zecwallet-lite
|
||||
;
|
||||
};
|
||||
|
||||
# packages not part of any package set; not enabled by default
|
||||
otherPkgs = {
|
||||
inherit (pkgs)
|
||||
lemmy-server
|
||||
mx-sanebot
|
||||
stepmania
|
||||
;
|
||||
};
|
||||
|
||||
# define -- but don't enable -- the packages in some attrset.
|
||||
declarePkgs = pkgsAsAttrs: mapAttrs (_n: p: {
|
||||
# no need to actually define the package here: it's defaulted
|
||||
# package = mkDefault p;
|
||||
}) pkgsAsAttrs;
|
||||
in
|
||||
{
|
||||
|
||||
imports = [
|
||||
./aerc.nix
|
||||
./assorted.nix
|
||||
./cozy.nix
|
||||
./git.nix
|
||||
./gnome-feeds.nix
|
||||
./gpodder.nix
|
||||
./gthumb.nix
|
||||
./imagemagick.nix
|
||||
./jellyfin-media-player.nix
|
||||
./kitty
|
||||
./komikku.nix
|
||||
./koreader
|
||||
./libreoffice.nix
|
||||
./lemoa.nix
|
||||
./mepo.nix
|
||||
./mpv.nix
|
||||
./msmtp.nix
|
||||
./neovim.nix
|
||||
./newsflash.nix
|
||||
./nix-index.nix
|
||||
./offlineimap.nix
|
||||
./ripgrep.nix
|
||||
./sfeed.nix
|
||||
./splatmoji.nix
|
||||
./steam.nix
|
||||
./sublime-music.nix
|
||||
./vlc.nix
|
||||
./web-browser.nix
|
||||
@@ -278,146 +36,8 @@ in
|
||||
];
|
||||
|
||||
config = {
|
||||
sane.programs = mkMerge [
|
||||
(declarePkgs consolePkgs)
|
||||
(declarePkgs desktopGuiPkgs)
|
||||
(declarePkgs guiPkgs)
|
||||
(declarePkgs iphonePkgs)
|
||||
(declarePkgs sysadminPkgs)
|
||||
(declarePkgs sysadminExtraPkgs)
|
||||
(declarePkgs tuiPkgs)
|
||||
(declarePkgs x86GuiPkgs)
|
||||
(declarePkgs otherPkgs)
|
||||
{
|
||||
# link the various package sets into their own meta packages
|
||||
consoleUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames consolePkgs;
|
||||
};
|
||||
desktopGuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames desktopGuiPkgs;
|
||||
};
|
||||
guiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = (attrNames guiPkgs)
|
||||
++ [ "web-browser" ]
|
||||
++ [ "tuiApps" ]
|
||||
++ optional (pkgs.system == "x86_64-linux") "x86GuiApps";
|
||||
};
|
||||
iphoneUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames iphonePkgs;
|
||||
};
|
||||
sysadminUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames sysadminPkgs;
|
||||
};
|
||||
sysadminExtraUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames sysadminExtraPkgs;
|
||||
};
|
||||
tuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames tuiPkgs;
|
||||
};
|
||||
x86GuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames x86GuiPkgs;
|
||||
};
|
||||
}
|
||||
{
|
||||
# nontrivial package definitions
|
||||
|
||||
dino.persist.private = [ ".local/share/dino" ];
|
||||
|
||||
# creds, but also 200 MB of node modules, etc
|
||||
discord.persist.private = [ ".config/discord" ];
|
||||
|
||||
# creds/session keys, etc
|
||||
element-desktop.persist.private = [ ".config/Element" ];
|
||||
|
||||
# `emote` will show a first-run dialog based on what's in this directory.
|
||||
# mostly, it just keeps a LRU of previously-used emotes to optimize display order.
|
||||
# TODO: package [smile](https://github.com/mijorus/smile) for probably a better mobile experience.
|
||||
emote.persist.plaintext = [ ".local/share/Emote" ];
|
||||
|
||||
# MS GitHub stores auth token in .config
|
||||
# TODO: we can populate gh's stuff statically; it even lets us use the same oauth across machines
|
||||
gh.persist.private = [ ".config/gh" ];
|
||||
|
||||
ghostscript = {}; # used by imagemagick
|
||||
|
||||
imagemagick = {
|
||||
package = pkgs.imagemagick.override {
|
||||
ghostscriptSupport = true;
|
||||
};
|
||||
suggestedPrograms = [ "ghostscript" ];
|
||||
};
|
||||
|
||||
# jellyfin stores things in a bunch of directories: this one persists auth info.
|
||||
# it *might* be possible to populate this externally (it's Qt stuff), but likely to
|
||||
# be fragile and take an hour+ to figure out.
|
||||
jellyfin-media-player.persist.plaintext = [ ".local/share/Jellyfin Media Player" ];
|
||||
|
||||
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
|
||||
# XXX: is it really safe to persist this? it doesn't have info that could de-anonymize if captured?
|
||||
monero-gui.persist.plaintext = [ ".bitmonero" ];
|
||||
|
||||
mumble.persist.private = [ ".local/share/Mumble" ];
|
||||
|
||||
# not strictly necessary, but allows caching articles; offline use, etc.
|
||||
nheko.persist.private = [
|
||||
".config/nheko" # config file (including client token)
|
||||
".cache/nheko" # media cache
|
||||
".local/share/nheko" # per-account state database
|
||||
];
|
||||
|
||||
# settings (electron app)
|
||||
obsidian.persist.plaintext = [ ".config/obsidian" ];
|
||||
|
||||
# creds, media
|
||||
signal-desktop.persist.private = [ ".config/Signal" ];
|
||||
|
||||
# printer/filament settings
|
||||
slic3r.persist.plaintext = [ ".Slic3r" ];
|
||||
|
||||
# creds, widevine .so download. TODO: could easily manage these statically.
|
||||
spotify.persist.plaintext = [ ".config/spotify" ];
|
||||
|
||||
steam.persist.plaintext = [
|
||||
".steam"
|
||||
".local/share/Steam"
|
||||
];
|
||||
|
||||
tdesktop.persist.private = [ ".local/share/TelegramDesktop" ];
|
||||
|
||||
tokodon.persist.private = [ ".cache/KDE/tokodon" ];
|
||||
|
||||
# hardenedMalloc solves a crash at startup
|
||||
# TODO 2023/02/02: is this safe to remove yet?
|
||||
tor-browser-bundle-bin.package = pkgs.tor-browser-bundle-bin.override {
|
||||
useHardenedMalloc = false;
|
||||
};
|
||||
|
||||
whalebird.persist.private = [ ".config/Whalebird" ];
|
||||
|
||||
yarn.persist.plaintext = [ ".cache/yarn" ];
|
||||
|
||||
# zcash coins. safe to delete, just slow to regenerate (10-60 minutes)
|
||||
zecwallet-lite.persist.private = [ ".zcash" ];
|
||||
}
|
||||
];
|
||||
|
||||
# XXX: this might not be necessary. try removing this and cacert.unbundled (servo)?
|
||||
environment.etc."ssl/certs".source = "${pkgs.cacert.unbundled}/etc/ssl/certs/*";
|
||||
|
||||
# steam requires system-level config for e.g. firewall or controller support
|
||||
programs.steam = mkIf config.sane.programs.steam.enabled {
|
||||
enable = true;
|
||||
# not sure if needed: stole this whole snippet from the wiki
|
||||
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
|
||||
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@@ -11,7 +11,15 @@ in
|
||||
user.name = "Colin";
|
||||
user.email = "colin@uninsane.org";
|
||||
|
||||
alias.co = "checkout";
|
||||
alias.br = "branch";
|
||||
alias.co = "checkout";
|
||||
alias.cp = "cherry-pick";
|
||||
alias.d = "difftool";
|
||||
alias.dif = "diff"; # common typo
|
||||
alias.difsum = "diff --compact-summary"; #< show only the list of files which changed, not contents
|
||||
alias.rb = "rebase";
|
||||
alias.st = "status";
|
||||
alias.stat = "status";
|
||||
|
||||
# difftastic docs:
|
||||
# - <https://difftastic.wilfred.me.uk/git.html>
|
||||
@@ -22,5 +30,10 @@ in
|
||||
|
||||
# render dates as YYYY-MM-DD HH:MM:SS +TZ
|
||||
log.date = "iso";
|
||||
|
||||
sendemail.annotate = "yes";
|
||||
sendemail.confirm = "always";
|
||||
|
||||
stash.showPatch = true;
|
||||
};
|
||||
}
|
||||
|
@@ -7,7 +7,8 @@ let
|
||||
wanted-feeds = feeds.filterByFormat ["podcast"] all-feeds;
|
||||
in {
|
||||
sane.programs.gpodder = {
|
||||
package = pkgs.gpodder-configured;
|
||||
package = pkgs.gpodder-adaptive-configured;
|
||||
# package = pkgs.gpodder-configured;
|
||||
fs.".config/gpodderFeeds.opml".symlink.text = feeds.feedsToOpml wanted-feeds;
|
||||
|
||||
# XXX: we preserve the whole thing because if we only preserve gPodder/Downloads
|
||||
|
4
hosts/common/programs/gthumb.nix
Normal file
4
hosts/common/programs/gthumb.nix
Normal file
@@ -0,0 +1,4 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
sane.programs.gthumb.package = pkgs.gthumb.override { withWebservices = false; };
|
||||
}
|
10
hosts/common/programs/imagemagick.nix
Normal file
10
hosts/common/programs/imagemagick.nix
Normal file
@@ -0,0 +1,10 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
sane.programs.imagemagick = {
|
||||
package = pkgs.imagemagick.override {
|
||||
ghostscriptSupport = true;
|
||||
};
|
||||
suggestedPrograms = [ "ghostscript" ];
|
||||
};
|
||||
sane.programs.ghostscript = {};
|
||||
}
|
13
hosts/common/programs/jellyfin-media-player.nix
Normal file
13
hosts/common/programs/jellyfin-media-player.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
sane.programs.jellyfin-media-player = {
|
||||
# package = pkgs.jellyfin-media-player;
|
||||
package = pkgs.jellyfin-media-player-qt6;
|
||||
|
||||
# jellyfin stores things in a bunch of directories: this one persists auth info.
|
||||
# it *might* be possible to populate this externally (it's Qt stuff), but likely to
|
||||
# be fragile and take an hour+ to figure out.
|
||||
persist.plaintext = [ ".local/share/Jellyfin Media Player" ];
|
||||
};
|
||||
}
|
@@ -1,14 +1,17 @@
|
||||
{ ... }:
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
sane.programs.kitty.fs.".config/kitty/kitty.conf".symlink.text = ''
|
||||
# docs: https://sw.kovidgoyal.net/kitty/conf/
|
||||
# disable terminal bell (when e.g. you backspace too many times)
|
||||
enable_audio_bell no
|
||||
sane.programs.kitty = {
|
||||
fs.".config/kitty/kitty.conf".symlink.text = ''
|
||||
# docs: https://sw.kovidgoyal.net/kitty/conf/
|
||||
# disable terminal bell (when e.g. you backspace too many times)
|
||||
enable_audio_bell no
|
||||
|
||||
map ctrl+n new_os_window_with_cwd
|
||||
include ${./PaperColor_dark.conf}
|
||||
'';
|
||||
map ctrl+n new_os_window_with_cwd
|
||||
include ${./PaperColor_dark.conf}
|
||||
'';
|
||||
env.TERMINAL = lib.mkDefault "kitty";
|
||||
};
|
||||
|
||||
# include ${pkgs.kitty-themes}/themes/PaperColor_dark.conf
|
||||
|
||||
|
8
hosts/common/programs/komikku.nix
Normal file
8
hosts/common/programs/komikku.nix
Normal file
@@ -0,0 +1,8 @@
|
||||
{ ... }:
|
||||
{
|
||||
sane.programs.komikku = {
|
||||
secrets.".local/share/komikku/keyrings/plaintext.keyring" = ../../../secrets/common/komikku_accounts.json.bin;
|
||||
# downloads end up here, and without the toplevel database komikku doesn't know they exist.
|
||||
persist.plaintext = [ ".local/share/komikku" ];
|
||||
};
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
-- as of 2023.05.1, koreader FTP browser always fails to load.
|
||||
-- it's convinced that it's offline, and asks to connect to wifi.
|
||||
-- this seems to be because of the following in <frontend/device/sdl/device.lua>:
|
||||
--
|
||||
-- function Device:initNetworkManager(NetworkMgr)
|
||||
-- function NetworkMgr:isWifiOn() return true end
|
||||
-- function NetworkMgr:isConnected()
|
||||
-- -- Pull the default gateway first, so we don't even try to ping anything if there isn't one...
|
||||
-- local default_gw = Device:getDefaultRoute()
|
||||
-- if not default_gw then
|
||||
-- return false
|
||||
-- end
|
||||
-- return 0 == os.execute("ping -c1 -w2 " .. default_gw .. " > /dev/null")
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- specifically, `os.execute` is not *expected* to return 0. it returns `true` on success:
|
||||
-- <https://www.lua.org/manual/5.3/manual.html#pdf-os.execute>
|
||||
-- this apparently changed from 5.1 -> 5.2
|
||||
--
|
||||
-- XXX: this same bug likely applies to `isCommand` and `runCommand` in <frontend/device/sdl/device.lua>
|
||||
-- - that would manifest as wikipedia links failing to open in external application (xdg-open)
|
||||
|
||||
local logger = require("logger")
|
||||
logger.info("applying colin patch")
|
||||
|
||||
local Device = require("device")
|
||||
logger.info("Device:" .. tostring(Device))
|
||||
|
||||
local orig_initNetworkManager = Device.initNetworkManager
|
||||
Device.initNetworkManager = function(self, NetworkMgr)
|
||||
logger.info("Device:initNetworkManager")
|
||||
orig_initNetworkManager(self, NetworkMgr)
|
||||
function NetworkMgr:isConnected()
|
||||
logger.info("mocked `NetworkMgr:isConnected` to return true")
|
||||
return true
|
||||
-- unpatch to show that the boolean form works
|
||||
-- local rc = os.execute("ping -c1 -w2 10.78.79.1 > /dev/null")
|
||||
-- logger.info("ping rc: " .. tostring(rc))
|
||||
-- return rc
|
||||
end
|
||||
end
|
46
hosts/common/programs/koreader/default.nix
Normal file
46
hosts/common/programs/koreader/default.nix
Normal file
@@ -0,0 +1,46 @@
|
||||
{ config, lib, sane-lib, ... }:
|
||||
|
||||
let
|
||||
feeds = sane-lib.feeds;
|
||||
allFeeds = config.sane.feeds;
|
||||
wantedFeeds = feeds.filterByFormat [ "image" "text" ] allFeeds;
|
||||
koreaderRssEntries = builtins.map (feed:
|
||||
# format:
|
||||
# { "<rss/atom url>", limit = <int>, download_full_article=<bool>, include_images=<bool>, enable_filter=<bool>, filter_element = "<css selector>"},
|
||||
# limit = 0 => download and keep *all* articles
|
||||
# download_full_article = true => populate feed by downloading the webpage -- not just what's encoded in the RSS <article> tags
|
||||
# - use this for articles where the RSS only encodes content previews
|
||||
# enable_filter = true => only render content that matches the filter_element css selector.
|
||||
let fields = [
|
||||
(lib.escapeShellArg feed.url)
|
||||
"limit = 5"
|
||||
"download_full_article = false"
|
||||
"include_images = true"
|
||||
"enable_filter = false"
|
||||
"filter_element = \"\""
|
||||
]; in "{ ${lib.concatStringsSep ", " fields } }"
|
||||
) wantedFeeds;
|
||||
in {
|
||||
sane.programs.koreader = {
|
||||
# koreader applies these lua "patches" at boot:
|
||||
# - <https://github.com/koreader/koreader/wiki/User-patches>
|
||||
# - TODO: upstream this patch to koreader
|
||||
# fs.".config/koreader/patches".symlink.target = "${./.}";
|
||||
fs.".config/koreader/patches/2-colin-NetworkManager-isConnected.lua".symlink.target = "${./2-colin-NetworkManager-isConnected.lua}";
|
||||
|
||||
# koreader news plugin, enabled by default. file format described here:
|
||||
# - <repo:koreader/koreader:plugins/newsdownloader.koplugin/feed_config.lua>
|
||||
fs.".config/koreader/news/feed_config.lua".symlink.text = ''
|
||||
return {--do NOT change this line
|
||||
${lib.concatStringsSep ",\n " koreaderRssEntries}
|
||||
}--do NOT change this line
|
||||
'';
|
||||
|
||||
# koreader on aarch64 errors if there's no fonts directory (sandboxing thing, i guess)
|
||||
fs.".local/share/fonts".dir = {};
|
||||
|
||||
# history, cache, dictionaries...
|
||||
# could be more explicit if i symlinked the history.lua file to somewhere it can persist better.
|
||||
persist.plaintext = [ ".config/koreader" ];
|
||||
};
|
||||
}
|
7
hosts/common/programs/lemoa.nix
Normal file
7
hosts/common/programs/lemoa.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{ ... }:
|
||||
{
|
||||
sane.programs.lemoa = {
|
||||
# creds
|
||||
persist.private = [ ".local/share/io.github.lemmygtk.lemoa" ];
|
||||
};
|
||||
}
|
18
hosts/common/programs/mepo.nix
Normal file
18
hosts/common/programs/mepo.nix
Normal file
@@ -0,0 +1,18 @@
|
||||
# docs: <https://git.sr.ht/~mil/mepo>
|
||||
# irc #mepo:irc.oftc.net
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
sane.programs.mepo = {
|
||||
persist.plaintext = [ ".cache/mepo/tiles" ];
|
||||
# ~/.cache/mepo/savestate has precise coordinates and pins: keep those private
|
||||
persist.private = [ ".cache/mepo/savestate" ];
|
||||
};
|
||||
|
||||
programs.mepo = lib.mkIf config.sane.programs.mepo.enabled {
|
||||
# enable location services (via geoclue)
|
||||
enable = true;
|
||||
# more precise, via gpsd ("may require additional config")
|
||||
# programs.mepo.gpsd.enable = true
|
||||
};
|
||||
}
|
25
hosts/common/programs/msmtp.nix
Normal file
25
hosts/common/programs/msmtp.nix
Normal file
@@ -0,0 +1,25 @@
|
||||
# docs: <https://nixos.wiki/wiki/Msmtp>
|
||||
# validate with e.g.
|
||||
# - `echo -e "Content-Type: text/plain\r\nSubject: Test\r\n\r\nHello World" | sendmail test@uninsane.org`
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
sane.programs.msmtp = {
|
||||
secrets.".config/msmtp/password.txt" = ../../../secrets/common/msmtp_password.txt.bin;
|
||||
};
|
||||
|
||||
programs.msmtp = lib.mkIf config.sane.programs.msmtp.enabled {
|
||||
enable = true;
|
||||
accounts = {
|
||||
default = {
|
||||
auth = true;
|
||||
tls = true;
|
||||
tls_starttls = false; # needed else sendmail hangs
|
||||
from = "Colin <colin@uninsane.org>";
|
||||
host = "mx.uninsane.org";
|
||||
user = "colin";
|
||||
passwordeval = "cat ~/.config/msmtp/password.txt";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
@@ -5,30 +5,11 @@ let
|
||||
inherit (lib) concatMapStrings mkIf optionalString;
|
||||
# this structure roughly mirrors home-manager's `programs.neovim.plugins` option
|
||||
plugins = with pkgs.vimPlugins; [
|
||||
# docs: surround-nvim: https://github.com/ur4ltz/surround.nvim/
|
||||
# docs: vim-surround: https://github.com/tpope/vim-surround
|
||||
{ plugin = vim-surround; }
|
||||
# docs: fzf-vim (fuzzy finder): https://github.com/junegunn/fzf.vim
|
||||
{ plugin = fzf-vim; }
|
||||
({
|
||||
# docs: tex-conceal-vim: https://github.com/KeitaNakamura/tex-conceal.vim/
|
||||
plugin = tex-conceal-vim;
|
||||
type = "viml";
|
||||
config = ''
|
||||
" present prettier fractions
|
||||
let g:tex_conceal_frac=1
|
||||
'';
|
||||
})
|
||||
({
|
||||
plugin = vim-SyntaxRange;
|
||||
type = "viml";
|
||||
config = ''
|
||||
" enable markdown-style codeblock highlighting for tex code
|
||||
autocmd BufEnter * call SyntaxRange#Include('```tex', '```', 'tex', 'NonText')
|
||||
" autocmd Syntax tex set conceallevel=2
|
||||
'';
|
||||
})
|
||||
({
|
||||
{
|
||||
# docs: fzf-vim (fuzzy finder): https://github.com/junegunn/fzf.vim
|
||||
plugin = fzf-vim;
|
||||
}
|
||||
{
|
||||
# treesitter syntax highlighting: https://nixos.wiki/wiki/Tree_sitters
|
||||
# docs: https://github.com/nvim-treesitter/nvim-treesitter
|
||||
# config taken from: https://github.com/i077/system/blob/master/modules/home/neovim/default.nix
|
||||
@@ -64,7 +45,35 @@ let
|
||||
vim.o.foldmethod = 'expr'
|
||||
vim.o.foldexpr = 'nvim_treesitter#foldexpr()'
|
||||
'';
|
||||
})
|
||||
}
|
||||
{
|
||||
# docs: tex-conceal-vim: https://github.com/KeitaNakamura/tex-conceal.vim/
|
||||
plugin = tex-conceal-vim;
|
||||
type = "viml";
|
||||
config = ''
|
||||
" present prettier fractions
|
||||
let g:tex_conceal_frac=1
|
||||
'';
|
||||
}
|
||||
{
|
||||
# source: <https://github.com/LnL7/vim-nix>
|
||||
# fixes auto-indent (incl tab size) when editing .nix files
|
||||
plugin = vim-nix;
|
||||
}
|
||||
{
|
||||
# docs: surround-nvim: https://github.com/ur4ltz/surround.nvim/
|
||||
# docs: vim-surround: https://github.com/tpope/vim-surround
|
||||
plugin = vim-surround;
|
||||
}
|
||||
{
|
||||
plugin = vim-SyntaxRange;
|
||||
type = "viml";
|
||||
config = ''
|
||||
" enable markdown-style codeblock highlighting for tex code
|
||||
autocmd BufEnter * call SyntaxRange#Include('```tex', '```', 'tex', 'NonText')
|
||||
" autocmd Syntax tex set conceallevel=2
|
||||
'';
|
||||
}
|
||||
];
|
||||
plugin-packages = map (p: p.plugin) plugins;
|
||||
plugin-config-tex = concatMapStrings (p: optionalString (p.type or "" == "viml") p.config) plugins;
|
||||
@@ -72,7 +81,12 @@ let
|
||||
in
|
||||
{
|
||||
# private because there could be sensitive things in the swap
|
||||
sane.programs.neovim.persist.private = [ ".cache/vim-swap" ];
|
||||
sane.programs.neovim = {
|
||||
persist.private = [ ".cache/vim-swap" ];
|
||||
env.EDITOR = "vim";
|
||||
# git claims it should use EDITOR, but it doesn't!
|
||||
env.GIT_EDITOR = "vim";
|
||||
};
|
||||
|
||||
programs.neovim = mkIf config.sane.programs.neovim.enabled {
|
||||
# neovim: https://github.com/neovim/neovim
|
||||
|
7
hosts/common/programs/nix-index.nix
Normal file
7
hosts/common/programs/nix-index.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
# provides `nix-locate`, backed by the manually run `nix-index`
|
||||
sane.programs.nix-index = {
|
||||
persist.plaintext = [ ".cache/nix-index" ];
|
||||
};
|
||||
}
|
28
hosts/common/programs/sfeed.nix
Normal file
28
hosts/common/programs/sfeed.nix
Normal file
@@ -0,0 +1,28 @@
|
||||
# simple RSS and Atom parser
|
||||
# - <https://codemadness.org/sfeed-simple-feed-parser.html>
|
||||
# - used by sxmo
|
||||
# - man 5 sfeedrc
|
||||
#
|
||||
# call `sfeed_update` to query each feed and populate entries in ~/.sfeed/feeds
|
||||
{ lib, config, sane-lib, ... }:
|
||||
let
|
||||
feeds = sane-lib.feeds;
|
||||
allFeeds = config.sane.feeds;
|
||||
wantedFeeds = feeds.filterByFormat ["text"] allFeeds;
|
||||
sfeedEntries = builtins.map (feed:
|
||||
# format:
|
||||
# feed <name> <feedurl> [basesiteurl] [encoding]
|
||||
lib.escapeShellArgs [ "feed" (if feed.title != null then feed.title else feed.url) feed.url ]
|
||||
) wantedFeeds;
|
||||
in {
|
||||
sane.programs.sfeed = {
|
||||
fs.".sfeed/sfeedrc".symlink.text = ''
|
||||
feeds() {
|
||||
${lib.concatStringsSep "\n " sfeedEntries}
|
||||
}
|
||||
'';
|
||||
|
||||
# this is where the parsed feed items go
|
||||
persist.plaintext = [ ".sfeed/feeds" ];
|
||||
};
|
||||
}
|
16
hosts/common/programs/steam.nix
Normal file
16
hosts/common/programs/steam.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{ config, lib, ...}:
|
||||
{
|
||||
sane.programs.steam = {
|
||||
persist.plaintext = [
|
||||
".steam"
|
||||
".local/share/Steam"
|
||||
];
|
||||
};
|
||||
# steam requires system-level config for e.g. firewall or controller support
|
||||
programs.steam = lib.mkIf config.sane.programs.steam.enabled {
|
||||
enable = true;
|
||||
# not sure if needed: stole this whole snippet from the wiki
|
||||
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
|
||||
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
|
||||
};
|
||||
}
|
@@ -13,17 +13,15 @@ let
|
||||
# allow easy switching between firefox and librewolf with `defaultSettings`, below
|
||||
librewolfSettings = {
|
||||
browser = pkgs.librewolf-unwrapped;
|
||||
# browser = pkgs.librewolf-unwrapped.overrideAttrs (drv: {
|
||||
# # this allows side-loading unsigned addons
|
||||
# MOZ_REQUIRE_SIGNING = false;
|
||||
# });
|
||||
extraPrefsFiles = pkgs.librewolf-unwrapped.extraPrefsFiles ++ pkgs.librewolf-pmos-mobile.extraPrefsFiles;
|
||||
libName = "librewolf";
|
||||
dotDir = ".librewolf";
|
||||
cacheDir = ".cache/librewolf"; # TODO: is it?
|
||||
cacheDir = ".cache/librewolf";
|
||||
desktop = "librewolf.desktop";
|
||||
};
|
||||
firefoxSettings = {
|
||||
browser = pkgs.firefox-esr-unwrapped;
|
||||
extraPrefsFiles = pkgs.firefox-pmos-mobile.extraPrefsFiles;
|
||||
libName = "firefox";
|
||||
dotDir = ".mozilla/firefox";
|
||||
cacheDir = ".cache/mozilla";
|
||||
@@ -47,8 +45,7 @@ let
|
||||
package = pkgs.wrapFirefox cfg.browser.browser {
|
||||
# inherit the default librewolf.cfg
|
||||
# it can be further customized via ~/.librewolf/librewolf.overrides.cfg
|
||||
inherit (pkgs.librewolf-unwrapped) extraPrefsFiles;
|
||||
inherit (cfg.browser) libName;
|
||||
inherit (cfg.browser) extraPrefsFiles libName;
|
||||
|
||||
extraNativeMessagingHosts = optional cfg.addons.browserpass-extension.enable pkgs.browserpass;
|
||||
# extraNativeMessagingHosts = [ pkgs.gopass-native-messaging-host ];
|
||||
@@ -56,10 +53,29 @@ let
|
||||
nixExtensions = concatMap (ext: optional ext.enable ext.package) (attrValues cfg.addons);
|
||||
|
||||
extraPolicies = {
|
||||
FirefoxHome = {
|
||||
Search = true;
|
||||
Pocket = false;
|
||||
Snippets = false;
|
||||
TopSites = false;
|
||||
Highlights = false;
|
||||
};
|
||||
NoDefaultBookmarks = true;
|
||||
OfferToSaveLogins = false;
|
||||
OfferToSaveLoginsDefault = false;
|
||||
PasswordManagerEnabled = false;
|
||||
SearchEngines = {
|
||||
Default = "DuckDuckGo";
|
||||
};
|
||||
UserMessaging = {
|
||||
ExtensionRecommendations = false;
|
||||
FeatureRecommendations = false;
|
||||
SkipOnboarding = true;
|
||||
UrlbarInterventions = false;
|
||||
WhatsNew = false;
|
||||
};
|
||||
|
||||
# these were taken from Librewolf
|
||||
AppUpdateURL = "https://localhost";
|
||||
DisableAppUpdate = true;
|
||||
OverrideFirstRunPage = "";
|
||||
@@ -88,6 +104,7 @@ let
|
||||
# };
|
||||
# NewTabPage = true;
|
||||
};
|
||||
# extraPrefs = ...
|
||||
};
|
||||
|
||||
addonOpts = types.submodule {
|
||||
@@ -145,8 +162,9 @@ in
|
||||
# bypass-paywalls-clean.package = addon "bypass-paywalls-clean" "{d133e097-46d9-4ecc-9903-fa6a722a6e0e}" "sha256-oUwdqdAwV3DezaTtOMx7A/s4lzIws+t2f08mwk+324k=";
|
||||
# bypass-paywalls-clean.enable = lib.mkDefault true;
|
||||
|
||||
# TODO: give these update scripts, make them reachable via `pkgs`
|
||||
ether-metamask = {
|
||||
package = addon "ether-metamask" "webextension@metamask.io" "sha256-G+MwJDOcsaxYSUXjahHJmkWnjLeQ0Wven8DU/lGeMzA=";
|
||||
package = addon "ether-metamask" "webextension@metamask.io" "sha256-UI83wUUc33OlQYX+olgujeppoo2D2PAUJ+Wma5mH2O0=";
|
||||
enable = lib.mkDefault true;
|
||||
};
|
||||
i2p-in-private-browsing = {
|
||||
@@ -158,15 +176,15 @@ in
|
||||
enable = lib.mkDefault true;
|
||||
};
|
||||
sponsorblock = {
|
||||
package = addon "sponsorblock" "sponsorBlocker@ajay.app" "sha256-hRsvLaAsVm3dALsTrJqHTNgRFAQcU7XSaGhr5G6+mFs=";
|
||||
package = addon "sponsorblock" "sponsorBlocker@ajay.app" "sha256-b/OTFmhSEUZ/CYrYCE4rHVMQmY+Y78k8jSGMoR8vsZA=";
|
||||
enable = lib.mkDefault true;
|
||||
};
|
||||
ublacklist = {
|
||||
package = addon "ublacklist" "@ublacklist" "sha256-RqY5iHzbL2qizth7aguyOKWPyINXmrwOlf/OsfqAS48=";
|
||||
package = addon "ublacklist" "@ublacklist" "sha256-NZ2FmgJiYnH7j2Lkn0wOembxaEphmUuUk0Ytmb0rNWo=";
|
||||
enable = lib.mkDefault true;
|
||||
};
|
||||
ublock-origin = {
|
||||
package = addon "ublock-origin" "uBlock0@raymondhill.net" "sha256-eHlQrU/b9X/6sTbHBpGAd+0VsLT7IrVCnd0AQ948lyA=";
|
||||
package = addon "ublock-origin" "uBlock0@raymondhill.net" "sha256-EGGAA+cLUow/F5luNzFG055rFfd3rEyh8hTaL/23pbM=";
|
||||
enable = lib.mkDefault true;
|
||||
};
|
||||
};
|
||||
@@ -175,6 +193,9 @@ in
|
||||
sane.programs.web-browser = {
|
||||
inherit package;
|
||||
|
||||
# env.BROWSER = "${package}/bin/${cfg.browser.libName}";
|
||||
env.BROWSER = cfg.browser.libName; # used by misc tools like xdg-email, as fallback
|
||||
|
||||
# uBlock filter list configuration.
|
||||
# specifically, enable the GDPR cookie prompt blocker.
|
||||
# data.toOverwrite.filterLists is additive (i.e. it supplements the default filters)
|
||||
@@ -193,6 +214,7 @@ in
|
||||
}
|
||||
}
|
||||
'';
|
||||
# TODO: this is better suited in `extraPrefs` during `wrapFirefox` call
|
||||
fs."${cfg.browser.dotDir}/${cfg.browser.libName}.overrides.cfg".symlink.text = ''
|
||||
// if we can't query the revocation status of a SSL cert because the issuer is offline,
|
||||
// treat it as unrevoked.
|
||||
|
@@ -1,3 +1,20 @@
|
||||
# zsh files/init order
|
||||
# - see `man zsh` => "STARTUP/SHUTDOWN FILES"
|
||||
# - /etc/zshenv
|
||||
# - $ZDOTDIR/.zshenv
|
||||
# - if login shell:
|
||||
# - /etc/zprofile
|
||||
# - $ZDOTDIR/.zprofile
|
||||
# - if interactive:
|
||||
# - /etc/zshrc
|
||||
# - $ZDOTDIR/.zshrc
|
||||
# - if login (again):
|
||||
# - /etc/zlogin
|
||||
# - ZDOTDIR/.zlogin
|
||||
# - at exit:
|
||||
# - $ZDOTDIR/.zlogout
|
||||
# - /etc/zlogout
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
@@ -33,7 +50,7 @@ in
|
||||
showDeadlines = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "show upcoming deadlines (frommy PKM) upon shell init";
|
||||
description = "show upcoming deadlines (from my PKM) upon shell init";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -41,41 +58,60 @@ in
|
||||
config = mkMerge [
|
||||
({
|
||||
sane.programs.zsh = {
|
||||
persist.plaintext = [
|
||||
persist.private = [
|
||||
# we don't need to full zsh dir -- just the history file --
|
||||
# but zsh will sometimes backup the history file and we get fewer errors if we do proper mounts instead of symlinks.
|
||||
# TODO: should be private?
|
||||
# but zsh will sometimes backup the history file and symlinking just the file messes things up
|
||||
".local/share/zsh"
|
||||
# cache gitstatus otherwise p10k fetched it from the net EVERY BOOT
|
||||
];
|
||||
persist.plaintext = [
|
||||
# cache gitstatus otherwise p10k fetches it from the net EVERY BOOT
|
||||
".cache/gitstatus"
|
||||
];
|
||||
|
||||
# zsh/prezto complains if zshrc doesn't exist; but it does allow an "empty" file.
|
||||
fs.".config/zsh/.zshrc".symlink.text = "# ";
|
||||
fs.".config/zsh/.zshrc".symlink.text = ''
|
||||
# zsh/prezto complains if zshrc doesn't exist or is empty;
|
||||
# preserve this comment to prevent that from ever happening.
|
||||
'' + lib.optionalString cfg.showDeadlines ''
|
||||
${pkgs.sane-scripts.deadlines}/bin/sane-deadlines
|
||||
'' + ''
|
||||
# auto-cd into any of these dirs by typing them and pressing 'enter':
|
||||
hash -d 3rd="/home/colin/dev/3rd"
|
||||
hash -d dev="/home/colin/dev"
|
||||
hash -d knowledge="/home/colin/knowledge"
|
||||
hash -d nixos="/home/colin/nixos"
|
||||
hash -d nixpkgs="/home/colin/dev/3rd/nixpkgs"
|
||||
hash -d ref="/home/colin/ref"
|
||||
hash -d secrets="/home/colin/knowledge/secrets"
|
||||
hash -d tmp="/home/colin/tmp"
|
||||
hash -d uninsane="/home/colin/dev/uninsane"
|
||||
hash -d Videos="/home/colin/Videos"
|
||||
'';
|
||||
|
||||
# prezto = oh-my-zsh fork; controls prompt, auto-completion, etc.
|
||||
# see: https://github.com/sorin-ionescu/prezto
|
||||
# i believe this file is auto-sourced by the prezto init.zsh script.
|
||||
# this file is auto-sourced by the prezto init.zsh script.
|
||||
# TODO: i should work to move away from prezto:
|
||||
# - it's FUCKING SLOW to initialize (that might also be powerlevel10k tho)
|
||||
# - it messes with my other `setopt`s
|
||||
fs.".config/zsh/.zpreztorc".symlink.text = ''
|
||||
zstyle ':prezto:*:*' color 'yes'
|
||||
zstyle ':prezto:module:utility' correct 'no' # prezto: don't setopt CORRECT
|
||||
|
||||
# modules (they ship with prezto):
|
||||
# ENVIRONMENT: configures jobs to persist after shell exit; other basic niceties
|
||||
# TERMINAL: auto-titles terminal (e.g. based on cwd)
|
||||
# EDITOR: configures shortcuts like Ctrl+U=undo, Ctrl+L=clear
|
||||
# HISTORY: `history-stat` alias, setopts for good history defaults
|
||||
# DIRECTORY: sets AUTO_CD, adds `d` alias to list directory stack, and `1`-`9` to cd that far back the stack
|
||||
# DIRECTORY: sets AUTO_CD, adds `d` alias to list directory stack, and `1`-`9` to cd that far back the stack. also overrides CLOBBER and some other options
|
||||
# SPECTRUM: helpers for term colors and styling. used by prompts? might be unnecessary
|
||||
# UTILITY: configures aliases like `ll`, `la`, disables globbing for things like rsync
|
||||
# adds aliases like `get` to fetch a file. also adds `http-serve` alias??
|
||||
# COMPLETION: tab completion. requires `utility` module prior to loading
|
||||
# TODO: enable AUTO_PARAM_SLASH
|
||||
zstyle ':prezto:load' pmodule \
|
||||
'environment' \
|
||||
'terminal' \
|
||||
'editor' \
|
||||
'history' \
|
||||
'directory' \
|
||||
'spectrum' \
|
||||
'utility' \
|
||||
'completion' \
|
||||
@@ -105,12 +141,19 @@ in
|
||||
"cd../" = "cd ../";
|
||||
};
|
||||
setOptions = [
|
||||
# defaults:
|
||||
# docs: `man zshoptions`
|
||||
# nixos defaults:
|
||||
"HIST_FCNTL_LOCK"
|
||||
"HIST_IGNORE_DUPS"
|
||||
"SHARE_HISTORY"
|
||||
"HIST_FCNTL_LOCK"
|
||||
# disable `rm *` confirmations
|
||||
"rmstarsilent"
|
||||
# customizations:
|
||||
"AUTO_CD" # type directory name to go there
|
||||
"AUTO_MENU" # show auto-complete menu on double-tab
|
||||
"CDABLE_VARS" # allow auto-cd to use my `hash` aliases -- not just immediate subdirs
|
||||
"CLOBBER" # allow `foo > bar.txt` to overwrite bar.txt
|
||||
"NO_CORRECT" # don't try to correct commands
|
||||
"PIPE_FAIL" # when `cmd_a | cmd_b`, make $? be non-zero if *any* of cmd_a or cmd_b fail
|
||||
"RM_STAR_SILENT" # disable `rm *` confirmations
|
||||
];
|
||||
|
||||
# .zshenv config:
|
||||
@@ -118,7 +161,7 @@ in
|
||||
ZDOTDIR=$HOME/.config/zsh
|
||||
'';
|
||||
|
||||
# .zshrc config:
|
||||
# system-wide .zshrc config:
|
||||
interactiveShellInit =
|
||||
(builtins.readFile ./p10k.zsh)
|
||||
+ p10k-overrides
|
||||
@@ -136,22 +179,6 @@ in
|
||||
mkdir -p "$1";
|
||||
pushd "$1";
|
||||
}
|
||||
''
|
||||
+ lib.optionalString cfg.showDeadlines ''
|
||||
${pkgs.sane-scripts}/bin/sane-deadlines
|
||||
''
|
||||
+ ''
|
||||
# auto-cd into any of these dirs by typing them and pressing 'enter':
|
||||
hash -d 3rd="/home/colin/dev/3rd"
|
||||
hash -d dev="/home/colin/dev"
|
||||
hash -d knowledge="/home/colin/knowledge"
|
||||
hash -d nixos="/home/colin/nixos"
|
||||
hash -d nixpkgs="/home/colin/dev/3rd/nixpkgs"
|
||||
hash -d ref="/home/colin/ref"
|
||||
hash -d secrets="/home/colin/knowledge/secrets"
|
||||
hash -d tmp="/home/colin/tmp"
|
||||
hash -d uninsane="/home/colin/dev/uninsane"
|
||||
hash -d Videos="/home/colin/Videos"
|
||||
'';
|
||||
|
||||
syntaxHighlighting.enable = true;
|
||||
@@ -159,8 +186,8 @@ in
|
||||
};
|
||||
|
||||
# enable a command-not-found hook to show nix packages that might provide the binary typed.
|
||||
programs.nix-index.enable = true;
|
||||
programs.command-not-found.enable = false; #< mutually exclusive with nix-index
|
||||
# programs.nix-index.enableZshIntegration = true;
|
||||
programs.command-not-found.enable = false;
|
||||
})
|
||||
];
|
||||
}
|
||||
|
@@ -29,14 +29,18 @@
|
||||
|
||||
let
|
||||
inherit (lib.strings) hasSuffix removeSuffix;
|
||||
secretsForHost = host: sane-lib.joinAttrsets (
|
||||
secretsForHost = host: let
|
||||
extraAttrsForPath = path: lib.optionalAttrs (sane-lib.path.isChild "guest" path) {
|
||||
owner = "guest";
|
||||
};
|
||||
in sane-lib.joinAttrsets (
|
||||
map
|
||||
(path: lib.optionalAttrs (hasSuffix ".bin" path) (sane-lib.nameValueToAttrs {
|
||||
name = removeSuffix ".bin" path;
|
||||
value = {
|
||||
sopsFile = ../../secrets/${host}/${path};
|
||||
format = "binary";
|
||||
};
|
||||
} // (extraAttrsForPath path);
|
||||
}))
|
||||
(sane-lib.enumerateFilePaths ../../secrets/${host})
|
||||
);
|
||||
@@ -63,6 +67,7 @@ in
|
||||
"jackett_apikey".owner = config.users.users.colin.name;
|
||||
"mx-sanebot-env".owner = config.users.users.colin.name;
|
||||
"snippets".owner = config.users.users.colin.name;
|
||||
"transmission_passwd".owner = config.users.users.colin.name;
|
||||
}
|
||||
];
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{ config, lib, sane-data, sane-lib, ... }:
|
||||
|
||||
let
|
||||
inherit (builtins) head map mapAttrs tail;
|
||||
inherit (builtins) attrValues head map mapAttrs tail;
|
||||
inherit (lib) concatStringsSep mkMerge reverseList;
|
||||
in
|
||||
{
|
||||
@@ -18,11 +18,21 @@ in
|
||||
|
||||
# [{ 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 = {
|
||||
colin = hostCfg.ssh.user_pubkey;
|
||||
root = hostCfg.ssh.host_pubkey;
|
||||
};
|
||||
})
|
||||
hostCfg.names
|
||||
;
|
||||
domainKeys = sane-lib.flattenAttrs (
|
||||
mapAttrs (host: cfg: {
|
||||
colin = cfg.ssh.user_pubkey;
|
||||
root = cfg.ssh.host_pubkey;
|
||||
}) config.sane.hosts.by-name
|
||||
sane-lib.joinAttrsets (
|
||||
map keysForHost (builtins.attrValues config.sane.hosts.by-name)
|
||||
)
|
||||
);
|
||||
in mkMerge (map
|
||||
({ path, value }: {
|
||||
@@ -30,4 +40,15 @@ in
|
||||
})
|
||||
(globalKeys ++ domainKeys)
|
||||
);
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings.PermitRootLogin = "no";
|
||||
settings.PasswordAuthentication = false;
|
||||
};
|
||||
sane.ports.ports."22" = {
|
||||
protocol = [ "tcp" ];
|
||||
visibleTo.lan = true;
|
||||
description = lib.mkDefault "colin-ssh";
|
||||
};
|
||||
}
|
||||
|
@@ -1,139 +0,0 @@
|
||||
{ config, pkgs, lib, sane-lib, ... }:
|
||||
|
||||
# installer docs: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/installation-device.nix
|
||||
with lib;
|
||||
let
|
||||
cfg = config.sane.guest;
|
||||
fs = sane-lib.fs;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
sane.guest.enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
# Users are exactly these specified here;
|
||||
# old ones will be deleted (from /etc/passwd, etc) upon upgrade.
|
||||
users.mutableUsers = false;
|
||||
|
||||
# docs: https://nixpkgs-manual-sphinx-markedown-example.netlify.app/generated/options-db.xml.html#users-users
|
||||
users.users.colin = {
|
||||
# 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 = [
|
||||
{ startUid=100000; count=1; }
|
||||
];
|
||||
group = "users";
|
||||
extraGroups = [
|
||||
"dialout" # required for modem access (moby)
|
||||
"feedbackd"
|
||||
"input" # for /dev/input/<xyz>: sxmo
|
||||
"networkmanager"
|
||||
"nixbuild"
|
||||
"video" # phosh/mobile. XXX colin: unsure if necessary
|
||||
"wheel"
|
||||
"wireshark"
|
||||
];
|
||||
|
||||
# initial password is empty, in case anything goes wrong.
|
||||
# if `colin-passwd` (a password hash) is successfully found/decrypted, that becomes the password at boot.
|
||||
initialPassword = lib.mkDefault "";
|
||||
passwordFile = lib.mkIf (config.sops.secrets ? "colin-passwd") config.sops.secrets.colin-passwd.path;
|
||||
|
||||
shell = pkgs.zsh;
|
||||
|
||||
# mount encrypted stuff at login
|
||||
# some other nix pam users:
|
||||
# - <https://github.com/g00pix/nixconf/blob/32c04f6fa843fed97639dd3f09e157668d3eea1f/profiles/sshfs.nix>
|
||||
# - <https://github.com/lourkeur/distro/blob/11173454c6bb50f7ccab28cc2c757dca21446d1d/nixos/profiles/users/louis-full.nix>
|
||||
# - <https://github.com/dnr/sample-nix-code/blob/03494480c1fae550c033aa54fd96aeb3827761c5/nixos/laptop.nix>
|
||||
pamMount = let
|
||||
priv = config.fileSystems."/home/colin/private";
|
||||
in {
|
||||
fstype = priv.fsType;
|
||||
path = priv.device;
|
||||
mountpoint = priv.mountPoint;
|
||||
options = builtins.concatStringsSep "," priv.options;
|
||||
};
|
||||
};
|
||||
|
||||
security.pam.mount.enable = true;
|
||||
|
||||
sane.users.colin.default = true;
|
||||
# ensure ~ perms are known to sane.fs module.
|
||||
# TODO: this is generic enough to be lifted up into sane.fs itself.
|
||||
sane.fs."/home/colin".dir.acl = {
|
||||
user = "colin";
|
||||
group = config.users.users.colin.group;
|
||||
mode = config.users.users.colin.homeMode;
|
||||
};
|
||||
|
||||
sane.user.persist.plaintext = [
|
||||
"archive"
|
||||
"dev"
|
||||
# TODO: records should be private
|
||||
"records"
|
||||
"ref"
|
||||
"tmp"
|
||||
"use"
|
||||
"Music"
|
||||
"Pictures"
|
||||
"Videos"
|
||||
|
||||
".cache/nix"
|
||||
".cache/nix-index"
|
||||
|
||||
# ".cargo"
|
||||
# ".rustup"
|
||||
];
|
||||
|
||||
# convenience
|
||||
sane.user.fs."knowledge" = fs.wantedSymlinkTo "private/knowledge";
|
||||
sane.user.fs."nixos" = fs.wantedSymlinkTo "dev/nixos";
|
||||
sane.user.fs."Books/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Books";
|
||||
sane.user.fs."Videos/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Videos";
|
||||
sane.user.fs."Videos/servo-incomplete" = fs.wantedSymlinkTo "/mnt/servo-media/incomplete";
|
||||
sane.user.fs."Music/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Music";
|
||||
sane.user.fs."Pictures/servo-macros" = fs.wantedSymlinkTo "/mnt/servo-media/Pictures/macros";
|
||||
|
||||
# used by password managers, e.g. unix `pass`
|
||||
sane.user.fs.".password-store" = fs.wantedSymlinkTo "knowledge/secrets/accounts";
|
||||
|
||||
sane.persist.sys.plaintext = mkIf cfg.enable [
|
||||
# intentionally allow other users to write to the guest folder
|
||||
{ directory = "/home/guest"; user = "guest"; group = "users"; mode = "0775"; }
|
||||
];
|
||||
users.users.guest = mkIf cfg.enable {
|
||||
isNormalUser = true;
|
||||
home = "/home/guest";
|
||||
subUidRanges = [
|
||||
{ startUid=200000; count=1; }
|
||||
];
|
||||
group = "users";
|
||||
initialPassword = lib.mkDefault "";
|
||||
shell = pkgs.zsh;
|
||||
openssh.authorizedKeys.keys = [
|
||||
# TODO: insert pubkeys that should be allowed in
|
||||
];
|
||||
};
|
||||
|
||||
security.sudo = {
|
||||
enable = true;
|
||||
wheelNeedsPassword = false;
|
||||
};
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings.PermitRootLogin = "no";
|
||||
settings.PasswordAuthentication = false;
|
||||
};
|
||||
};
|
||||
}
|
93
hosts/common/users/colin.nix
Normal file
93
hosts/common/users/colin.nix
Normal file
@@ -0,0 +1,93 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# docs: https://nixpkgs-manual-sphinx-markedown-example.netlify.app/generated/options-db.xml.html#users-users
|
||||
users.users.colin = {
|
||||
# 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 = [
|
||||
{ startUid=100000; count=1; }
|
||||
];
|
||||
group = "users";
|
||||
extraGroups = [
|
||||
"dialout" # required for modem access (moby)
|
||||
"feedbackd"
|
||||
"input" # for /dev/input/<xyz>: sxmo
|
||||
"networkmanager"
|
||||
"nixbuild"
|
||||
"transmission" # servo, to admin /var/lib/uninsane/media
|
||||
"video" # phosh/mobile. XXX colin: unsure if necessary
|
||||
"wheel"
|
||||
"wireshark"
|
||||
];
|
||||
|
||||
# initial password is empty, in case anything goes wrong.
|
||||
# if `colin-passwd` (a password hash) is successfully found/decrypted, that becomes the password at boot.
|
||||
initialPassword = lib.mkDefault "";
|
||||
passwordFile = lib.mkIf (config.sops.secrets ? "colin-passwd") config.sops.secrets.colin-passwd.path;
|
||||
|
||||
shell = pkgs.zsh;
|
||||
|
||||
# mount encrypted stuff at login
|
||||
# some other nix pam users:
|
||||
# - <https://github.com/g00pix/nixconf/blob/32c04f6fa843fed97639dd3f09e157668d3eea1f/profiles/sshfs.nix>
|
||||
# - <https://github.com/lourkeur/distro/blob/11173454c6bb50f7ccab28cc2c757dca21446d1d/nixos/profiles/users/louis-full.nix>
|
||||
# - <https://github.com/dnr/sample-nix-code/blob/03494480c1fae550c033aa54fd96aeb3827761c5/nixos/laptop.nix>
|
||||
pamMount = let
|
||||
priv = config.fileSystems."/home/colin/private";
|
||||
in {
|
||||
fstype = priv.fsType;
|
||||
path = priv.device;
|
||||
mountpoint = priv.mountPoint;
|
||||
options = builtins.concatStringsSep "," priv.options;
|
||||
};
|
||||
};
|
||||
|
||||
security.pam.mount.enable = true;
|
||||
|
||||
sane.users.colin = {
|
||||
default = true;
|
||||
# ensure ~ perms are known to sane.fs module.
|
||||
# TODO: this is generic enough to be lifted up into sane.fs itself.
|
||||
fs."/".dir.acl = {
|
||||
user = "colin";
|
||||
group = config.users.users.colin.group;
|
||||
mode = config.users.users.colin.homeMode;
|
||||
};
|
||||
|
||||
persist.plaintext = [
|
||||
"archive"
|
||||
"dev"
|
||||
# TODO: records should be private
|
||||
"records"
|
||||
"ref"
|
||||
"tmp"
|
||||
"use"
|
||||
"Music"
|
||||
"Pictures"
|
||||
"Videos"
|
||||
|
||||
".cache/nix"
|
||||
|
||||
# ".cargo"
|
||||
# ".rustup"
|
||||
];
|
||||
|
||||
# convenience
|
||||
fs."knowledge".symlink.target = "private/knowledge";
|
||||
fs."nixos".symlink.target = "dev/nixos";
|
||||
fs."Books/servo".symlink.target = "/mnt/servo-media/Books";
|
||||
fs."Videos/servo".symlink.target = "/mnt/servo-media/Videos";
|
||||
fs."Videos/servo-incomplete".symlink.target = "/mnt/servo-media/incomplete";
|
||||
fs."Music/servo".symlink.target = "/mnt/servo-media/Music";
|
||||
fs."Pictures/servo-macros".symlink.target = "/mnt/servo-media/Pictures/macros";
|
||||
|
||||
# used by password managers, e.g. unix `pass`
|
||||
fs.".password-store".symlink.target = "knowledge/secrets/accounts";
|
||||
};
|
||||
}
|
17
hosts/common/users/default.nix
Normal file
17
hosts/common/users/default.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
{ config, pkgs, lib, sane-lib, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./colin.nix
|
||||
./guest.nix
|
||||
];
|
||||
|
||||
# Users are exactly these specified here;
|
||||
# old ones will be deleted (from /etc/passwd, etc) upon upgrade.
|
||||
users.mutableUsers = false;
|
||||
|
||||
security.sudo = {
|
||||
enable = true;
|
||||
wheelNeedsPassword = false;
|
||||
};
|
||||
}
|
33
hosts/common/users/guest.nix
Normal file
33
hosts/common/users/guest.nix
Normal file
@@ -0,0 +1,33 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.sane.guest;
|
||||
in
|
||||
{
|
||||
options = with lib; {
|
||||
sane.guest.enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
users.users.guest = lib.mkIf cfg.enable {
|
||||
isNormalUser = true;
|
||||
home = "/home/guest";
|
||||
subUidRanges = [
|
||||
{ startUid=200000; count=1; }
|
||||
];
|
||||
group = "users";
|
||||
initialPassword = lib.mkDefault "";
|
||||
shell = pkgs.zsh;
|
||||
};
|
||||
|
||||
sane.users.guest.fs.".ssh/authorized_keys".symlink.target = config.sops.secrets."guest/authorized_keys".path or "/dev/null";
|
||||
|
||||
sane.persist.sys.plaintext = lib.mkIf cfg.enable [
|
||||
# intentionally allow other users to write to the guest folder
|
||||
{ directory = "/home/guest"; user = "guest"; group = "users"; mode = "0775"; }
|
||||
];
|
||||
};
|
||||
}
|
@@ -7,6 +7,7 @@ in
|
||||
{
|
||||
imports = [
|
||||
./gnome.nix
|
||||
./gtk.nix
|
||||
./phosh.nix
|
||||
./plasma.nix
|
||||
./plasma-mobile.nix
|
||||
|
133
hosts/modules/gui/gtk.nix
Normal file
133
hosts/modules/gui/gtk.nix
Normal file
@@ -0,0 +1,133 @@
|
||||
{ config, lib, pkgs }:
|
||||
let
|
||||
cfg = config.sane.gui.gtk;
|
||||
themes = {
|
||||
inherit (pkgs)
|
||||
# themes are in <repo:nixos/nixpkgs:pkgs/data/themes>
|
||||
adapta-gtk-theme
|
||||
adapta-kde-theme
|
||||
adementary-theme
|
||||
adi1090x-plymouth-themes
|
||||
adw-gtk3
|
||||
adwaita-qt
|
||||
adwaita-qt6
|
||||
albatross
|
||||
amarena-theme
|
||||
amber-theme
|
||||
ant-bloody-theme
|
||||
ant-nebula-theme
|
||||
ant-theme
|
||||
arc-kde-theme
|
||||
arc-theme
|
||||
artim-dark
|
||||
ayu-theme-gtk
|
||||
base16-schemes
|
||||
blackbird
|
||||
breath-theme
|
||||
canta-theme
|
||||
catppuccin-gtk
|
||||
catppuccin-kde
|
||||
catppuccin-kvantum
|
||||
catppuccin-plymouth
|
||||
clearlooks-phenix
|
||||
colloid-gtk-theme
|
||||
colloid-kde
|
||||
dracula-theme
|
||||
e17gtk
|
||||
equilux-theme
|
||||
flat-remix-gnome
|
||||
flat-remix-gtk
|
||||
fluent-gtk-theme
|
||||
graphite-gtk-theme
|
||||
graphite-kde-theme
|
||||
greybird
|
||||
gruvbox-dark-gtk
|
||||
gruvbox-gtk-theme
|
||||
gruvterial-theme
|
||||
juno-theme
|
||||
kde-gruvbox
|
||||
kde-rounded-corners
|
||||
layan-gtk-theme
|
||||
layan-kde
|
||||
lightly-boehs
|
||||
lightly-qt
|
||||
lounge-gtk-theme
|
||||
marwaita
|
||||
marwaita-manjaro
|
||||
marwaita-peppermint
|
||||
marwaita-pop_os
|
||||
marwaita-ubuntu
|
||||
matcha-gtk-theme
|
||||
materia-kde-theme
|
||||
materia-theme
|
||||
material-kwin-decoration
|
||||
mojave-gtk-theme
|
||||
nixos-bgrt-plymouth
|
||||
nordic
|
||||
numix-gtk-theme
|
||||
numix-solarized-gtk-theme
|
||||
numix-sx-gtk-theme
|
||||
oceanic-theme
|
||||
omni-gtk-theme
|
||||
onestepback
|
||||
openzone-cursors
|
||||
orchis-theme
|
||||
orion
|
||||
palenight-theme
|
||||
paper-gtk-theme
|
||||
pitch-black
|
||||
plano-theme
|
||||
plasma-overdose-kde-theme
|
||||
plata-theme
|
||||
pop-gtk-theme
|
||||
qogir-kde
|
||||
qogir-theme
|
||||
rose-pine-gtk-theme
|
||||
shades-of-gray-theme
|
||||
sierra-breeze-enhanced
|
||||
sierra-gtk-theme
|
||||
skeu
|
||||
snowblind
|
||||
solarc-gtk-theme
|
||||
spacx-gtk-theme
|
||||
stilo-themes
|
||||
sweet
|
||||
sweet-nova
|
||||
theme-jade1
|
||||
theme-obsidian2
|
||||
theme-vertex
|
||||
tokyo-night-gtk
|
||||
ubuntu-themes
|
||||
venta
|
||||
vimix-gtk-themes
|
||||
whitesur-gtk-theme
|
||||
yaru-remix-theme
|
||||
yaru-theme
|
||||
zuki-themes
|
||||
;
|
||||
};
|
||||
in
|
||||
{
|
||||
options = with lib; {
|
||||
sane.gui.gtk.enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = "apply theme to gtk4 apps";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
programs.dconf.packages = [
|
||||
(pkgs.writeTextFile {
|
||||
name = "dconf-sway-settings";
|
||||
destination = "/etc/dconf/db/site.d/10_sway_settings";
|
||||
text = ''
|
||||
[org/gnome/desktop/interface]
|
||||
gtk-theme="Dracula"
|
||||
icon-theme="Dracula"
|
||||
'';
|
||||
})
|
||||
];
|
||||
environment.systemPackages = lib.attrValues themes;
|
||||
};
|
||||
}
|
@@ -43,7 +43,7 @@ in
|
||||
})
|
||||
phosh-mobile-settings
|
||||
"plasma5Packages.konsole"
|
||||
# "gnome.gnome-bluetooth"
|
||||
"gnome.gnome-bluetooth"
|
||||
"gnome.gnome-terminal"
|
||||
;
|
||||
};
|
||||
|
@@ -66,16 +66,17 @@ in
|
||||
"mako" # notification daemon
|
||||
# # "pavucontrol"
|
||||
# "gnome.gnome-bluetooth" # XXX(2023/05/14): broken
|
||||
"gnome.gnome-control-center"
|
||||
# "gnome.gnome-control-center" # XXX(2023/06/28): depends on webkitgtk4_1
|
||||
"sway-contrib.grimshot"
|
||||
"wdisplays" # like xrandr
|
||||
];
|
||||
};
|
||||
}
|
||||
{
|
||||
sane.programs = {
|
||||
inherit (pkgs // {
|
||||
"gnome.gnome-bluetooth" = pkgs.gnome.gnome-bluetooth;
|
||||
"gnome.gnome-control-center" = pkgs.gnome.gnome-control-center;
|
||||
# "gnome.gnome-bluetooth" = pkgs.gnome.gnome-bluetooth;
|
||||
# "gnome.gnome-control-center" = pkgs.gnome.gnome-control-center;
|
||||
"sway-contrib.grimshot" = pkgs.sway-contrib.grimshot;
|
||||
})
|
||||
swaylock
|
||||
@@ -83,15 +84,17 @@ in
|
||||
wl-clipboard
|
||||
blueberry
|
||||
mako
|
||||
"gnome.gnome-bluetooth"
|
||||
"gnome.gnome-control-center"
|
||||
# "gnome.gnome-bluetooth"
|
||||
# "gnome.gnome-control-center"
|
||||
"sway-contrib.grimshot"
|
||||
wdisplays
|
||||
;
|
||||
};
|
||||
}
|
||||
|
||||
(mkIf cfg.enable {
|
||||
sane.programs.swayApps.enableFor.user.colin = true;
|
||||
sane.gui.gtk.enable = lib.mkDefault true;
|
||||
|
||||
# swap in these lines to use SDDM instead of `services.greetd`.
|
||||
# services.xserver.displayManager.sddm.enable = true;
|
||||
@@ -126,13 +129,13 @@ in
|
||||
hardware.bluetooth.enable = true;
|
||||
services.blueman.enable = true;
|
||||
# gsd provides Rfkill, which is required for the bluetooth pane in gnome-control-center to work
|
||||
services.gnome.gnome-settings-daemon.enable = true;
|
||||
# services.gnome.gnome-settings-daemon.enable = true;
|
||||
# start the components of gsd we need at login
|
||||
systemd.user.targets."org.gnome.SettingsDaemon.Rfkill".wantedBy = [ "graphical-session.target" ];
|
||||
# systemd.user.targets."org.gnome.SettingsDaemon.Rfkill".wantedBy = [ "graphical-session.target" ];
|
||||
# go ahead and `systemctl --user cat gnome-session-initialized.target`. i dare you.
|
||||
# the only way i can figure out how to get Rfkill to actually load is to just disable all the shit it depends on.
|
||||
# it doesn't actually seem to need ANY of them in the first place T_T
|
||||
systemd.user.targets."gnome-session-initialized".enable = false;
|
||||
# systemd.user.targets."gnome-session-initialized".enable = false;
|
||||
# bluez can't connect to audio devices unless pipewire is running.
|
||||
# a system service can't depend on a user service, so just launch it at graphical-session
|
||||
systemd.user.services."pipewire".wantedBy = [ "graphical-session.target" ];
|
||||
|
@@ -63,34 +63,18 @@ in
|
||||
"sway" => layered sway greeter. behaves as if you booted to swaylock.
|
||||
'';
|
||||
};
|
||||
sane.gui.sxmo.hooks = mkOption {
|
||||
sane.gui.sxmo.package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.runCommand "sxmo-hooks" { } ''
|
||||
mkdir -p $out
|
||||
ln -s ${pkgs.sxmo-utils}/share/sxmo/default_hooks $out/bin
|
||||
'';
|
||||
default = pkgs.sxmo-utils;
|
||||
description = ''
|
||||
hooks to make visible to sxmo.
|
||||
a hook is a script generally of the name sxmo_hook_<thing>.sh
|
||||
which is called by sxmo at key moments to proide user programmability.
|
||||
'';
|
||||
};
|
||||
sane.gui.sxmo.deviceHooks = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.runCommand "sxmo-device-hooks" { } ''
|
||||
mkdir -p $out
|
||||
ln -s ${pkgs.sxmo-utils}/share/sxmo/default_hooks/unknown $out/bin
|
||||
'';
|
||||
description = ''
|
||||
device-specific hooks to make visible to sxmo.
|
||||
this package supplies things like `sxmo_hook_inputhandler.sh`.
|
||||
a hook is a script generally of the name sxmo_hook_<thing>.sh
|
||||
which is called by sxmo at key moments to proide user programmability.
|
||||
sxmo base scripts and hooks collection.
|
||||
consider overriding the outputs under /share/sxmo/default_hooks
|
||||
to insert your own user scripts.
|
||||
'';
|
||||
};
|
||||
sane.gui.sxmo.terminal = mkOption {
|
||||
# type = types.nullOr (types.enum [ "foot" "st" "vte" ]);
|
||||
type = types.nullOr types.string;
|
||||
type = types.nullOr types.str;
|
||||
default = "foot";
|
||||
description = ''
|
||||
name of terminal to use for sxmo_terminal.sh.
|
||||
@@ -99,7 +83,7 @@ in
|
||||
};
|
||||
sane.gui.sxmo.keyboard = mkOption {
|
||||
# type = types.nullOr (types.enum ["wvkbd"])
|
||||
type = types.nullOr types.string;
|
||||
type = types.nullOr types.str;
|
||||
default = "wvkbd";
|
||||
description = ''
|
||||
name of on-screen-keyboard to use for sxmo_keyboard.sh.
|
||||
@@ -108,12 +92,29 @@ in
|
||||
'';
|
||||
};
|
||||
sane.gui.sxmo.settings = mkOption {
|
||||
type = types.attrsOf types.string;
|
||||
default = {};
|
||||
description = ''
|
||||
environment variables used to configure sxmo.
|
||||
e.g. SXMO_UNLOCK_IDLE_TIME or SXMO_VOLUME_BUTTON.
|
||||
'';
|
||||
type = types.submodule {
|
||||
freeformType = types.attrsOf types.str;
|
||||
options =
|
||||
let
|
||||
mkSettingsOpt = default: description: mkOption {
|
||||
inherit default description;
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
in {
|
||||
SXMO_BAR_SHOW_BAT_PER = mkSettingsOpt "1" "show battery percentage in statusbar";
|
||||
SXMO_UNLOCK_IDLE_TIME = mkSettingsOpt "300" "how many seconds of inactivity before locking the screen"; # lock -> screenoff happens 8s later, not configurable
|
||||
};
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
sane.gui.sxmo.noidle = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "inhibit lock-on-idle and screenoff-on-idle";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -123,18 +124,25 @@ in
|
||||
package = null;
|
||||
suggestedPrograms = [
|
||||
"guiApps"
|
||||
"sfeed" # want this here so that the user's ~/.sfeed/sfeedrc gets created
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
# TODO: lift to option declaration
|
||||
sane.gui.sxmo.settings.TERMCMD = lib.mkIf (cfg.terminal != null)
|
||||
(lib.mkDefault (if cfg.terminal == "vte" then "vte-2.91" else cfg.terminal));
|
||||
sane.gui.sxmo.settings.KEYBOARD = lib.mkIf (cfg.keyboard != null)
|
||||
(lib.mkDefault (if cfg.keyboard == "wvkbd" then "wvkbd-mobintl" else cfg.keyboard));
|
||||
}
|
||||
|
||||
(lib.mkIf cfg.enable {
|
||||
sane.programs.sxmoApps.enableFor.user.colin = true;
|
||||
|
||||
# some programs (e.g. fractal/nheko) **require** a "Secret Service Provider"
|
||||
services.gnome.gnome-keyring.enable = true;
|
||||
|
||||
# TODO: probably need to enable pipewire
|
||||
|
||||
networking.useDHCP = false;
|
||||
networking.networkmanager.enable = true;
|
||||
networking.wireless.enable = lib.mkForce false;
|
||||
@@ -146,10 +154,12 @@ in
|
||||
security.doas.enable = true;
|
||||
security.doas.wheelNeedsPassword = false;
|
||||
|
||||
# TODO: not all of these fonts seem to be mapped to the correct icon
|
||||
# TODO: nerdfonts is 4GB. it accepts an option to ship only some fonts: probably want to use that.
|
||||
fonts.fonts = [ pkgs.nerdfonts ];
|
||||
|
||||
# i believe sxmo recomments a different audio stack
|
||||
# sxmo has first-class support only for pulseaudio and alsa -- not pipewire.
|
||||
# however, pipewire can emulate pulseaudio support via `services.pipewire.pulse.enable = true`
|
||||
# after which the stock pulseaudio binaries magically work
|
||||
# administer with pw-cli, pw-mon, pw-top commands
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
@@ -160,45 +170,19 @@ in
|
||||
systemd.user.services."pipewire".wantedBy = [ "graphical-session.target" ];
|
||||
|
||||
# TODO: could use `displayManager.sessionPackages`?
|
||||
environment.systemPackages = with pkgs; [
|
||||
bc
|
||||
bemenu
|
||||
bonsai
|
||||
conky
|
||||
gojq
|
||||
inotify-tools
|
||||
jq
|
||||
libnotify
|
||||
lisgd
|
||||
mako
|
||||
superd
|
||||
sway
|
||||
swayidle
|
||||
sxmo-utils
|
||||
wob
|
||||
wvkbd
|
||||
xdg-user-dirs
|
||||
|
||||
# X11 only?
|
||||
xdotool
|
||||
|
||||
cfg.deviceHooks
|
||||
cfg.hooks
|
||||
environment.systemPackages = [
|
||||
cfg.package
|
||||
] ++ lib.optionals (cfg.terminal != null) [ pkgs."${cfg.terminal}" ]
|
||||
++ lib.optionals (cfg.keyboard != null) [ pkgs."${cfg.keyboard}" ];
|
||||
|
||||
environment.sessionVariables = {
|
||||
XDG_DATA_DIRS = [
|
||||
# TODO: only need the share/sxmo directly linked
|
||||
"${pkgs.sxmo-utils}/share"
|
||||
"${cfg.package}/share"
|
||||
];
|
||||
} // lib.optionalAttrs (cfg.terminal != null) {
|
||||
TERMCMD = lib.mkDefault (if cfg.terminal == "vte" then "vte-2.91" else cfg.terminal);
|
||||
} // lib.optionalAttrs (cfg.keyboard != null) {
|
||||
KEYBOARD = lib.mkDefault (if cfg.keyboard == "wvkbd" then "wvkbd-mobintl" else cfg.keyboard);
|
||||
} // cfg.settings;
|
||||
|
||||
sane.user.fs.".cache/sxmo/sxmo.noidle" = sane-lib.fs.wantedText "";
|
||||
sane.user.fs.".cache/sxmo/sxmo.noidle" = lib.mkIf cfg.noidle (sane-lib.fs.wantedText "");
|
||||
|
||||
|
||||
## greeter
|
||||
@@ -213,7 +197,7 @@ in
|
||||
'';
|
||||
|
||||
displayManager.sessionPackages = with pkgs; [
|
||||
sxmo-utils # this gets share/wayland-sessions/swmo.desktop linked
|
||||
cfg.package # this gets share/wayland-sessions/swmo.desktop linked
|
||||
];
|
||||
|
||||
# taken from gui/phosh:
|
||||
@@ -248,6 +232,15 @@ in
|
||||
in "${sway-as-greeter}/bin/sway-as-greeter";
|
||||
};
|
||||
|
||||
systemd.services."sxmo-set-permissions" = {
|
||||
description = "configure specific /sys and /dev nodes to be writable by sxmo scripts";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${cfg.package}/bin/sxmo_setpermissions.sh";
|
||||
};
|
||||
wantedBy = [ "display-manager.service" ];
|
||||
};
|
||||
|
||||
sane.fs."/var/log/sway" = lib.mkIf (cfg.greeter == "sway") {
|
||||
dir.acl.mode = "0777";
|
||||
wantedBeforeBy = [ "greetd.service" "display-manager.service" ];
|
||||
@@ -260,7 +253,7 @@ in
|
||||
# name = "sxmo";
|
||||
# desktopNames = [ "sxmo" ];
|
||||
# start = ''
|
||||
# ${pkgs.sxmo-utils}/bin/sxmo_xinit.sh &
|
||||
# ${cfg.package}/bin/sxmo_xinit.sh &
|
||||
# waitPID=$!
|
||||
# '';
|
||||
# }];
|
||||
@@ -270,7 +263,7 @@ in
|
||||
# enable = true;
|
||||
# settings = {
|
||||
# default_session = {
|
||||
# command = "${pkgs.sxmo-utils}/bin/sxmo_winit.sh";
|
||||
# command = "${cfg.package}/bin/sxmo_winit.sh";
|
||||
# user = "colin";
|
||||
# };
|
||||
# };
|
||||
|
@@ -11,6 +11,7 @@
|
||||
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"
|
||||
|
@@ -4,8 +4,14 @@ let
|
||||
inherit (lib) attrValues filterAttrs mkMerge mkOption types;
|
||||
cfg = config.sane.hosts;
|
||||
|
||||
host = types.submodule ({ config, ... }: {
|
||||
host = types.submodule ({ config, name, ... }: {
|
||||
options = {
|
||||
names = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = ''
|
||||
all names by which this host is reachable
|
||||
'';
|
||||
};
|
||||
ssh.user_pubkey = mkOption {
|
||||
type = types.str;
|
||||
description = ''
|
||||
@@ -48,6 +54,11 @@ let
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
names = [ name ]
|
||||
++ lib.optional (config.wg-home.ip != null) "${name}-hn";
|
||||
};
|
||||
});
|
||||
in
|
||||
{
|
||||
|
@@ -26,7 +26,7 @@ in
|
||||
type = types.bool;
|
||||
};
|
||||
sane.nixcache.substituters = mkOption {
|
||||
type = types.listOf types.string;
|
||||
type = types.listOf types.str;
|
||||
default =
|
||||
# TODO: make these blacklisted entries injectable
|
||||
(lib.optional (hostName != "servo") "https://nixcache.uninsane.org")
|
||||
|
@@ -10,7 +10,7 @@
|
||||
};
|
||||
|
||||
config = lib.mkIf config.sane.roles.ac {
|
||||
sane.yggdrasil.enable = true;
|
||||
services.i2p.enable = true;
|
||||
# sane.yggdrasil.enable = true;
|
||||
# services.i2p.enable = true;
|
||||
};
|
||||
}
|
||||
|
@@ -32,6 +32,11 @@ in
|
||||
# serve packages to other machines that ask for them
|
||||
sane.services.nixserve.enable = true;
|
||||
|
||||
# each concurrent derivation realization uses a different nix build user.
|
||||
# default is 32 build users, limiting us to that many concurrent jobs.
|
||||
# it's nice to not be limited in that way, so increase this a bit.
|
||||
nix.nrBuildUsers = 64;
|
||||
|
||||
# enable cross compilation
|
||||
# TODO: do this via stdenv injection, linking into /run/binfmt the stuff in <nixpkgs:nixos/modules/system/boot/binfmt.nix>
|
||||
boot.binfmt.emulatedSystems = lib.optionals cfg.emulation [
|
||||
|
@@ -17,8 +17,8 @@ in
|
||||
config = mkMerge [
|
||||
({
|
||||
sane.programs.docsets.config.rustPkgs = [
|
||||
"lemmy-server"
|
||||
"mx-sanebot"
|
||||
# "lemmy-server"
|
||||
# "mx-sanebot"
|
||||
];
|
||||
})
|
||||
(mkIf cfg {
|
||||
|
@@ -33,6 +33,11 @@ in
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
sane.services.wg-home.enableWan = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "whether to make this port visible on the WAN";
|
||||
};
|
||||
sane.services.wg-home.ip = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
@@ -50,7 +55,12 @@ in
|
||||
# this config defines both the endpoint (server) and client configs
|
||||
|
||||
# for convenience, have both the server and client use the same port for their wireguard connections.
|
||||
networking.firewall.allowedUDPPorts = [ 51820 ];
|
||||
sane.ports.ports."51820" = {
|
||||
protocol = [ "udp" ];
|
||||
visibleTo.lan = true;
|
||||
visibleTo.wan = cfg.enableWan;
|
||||
description = "colin-wireguard";
|
||||
};
|
||||
networking.wireguard.interfaces.wg-home = {
|
||||
listenPort = 51820;
|
||||
privateKeyFile = "/run/wg-home.priv";
|
||||
|
@@ -22,6 +22,7 @@
|
||||
# ^ source: <https://github.com/nix-community/nur-packages-template/blob/master/.github/workflows/build.yml#L63>
|
||||
# N.B.: nur eval allows only PATH (inherited) and NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM="1" (forced),
|
||||
# hence the erasing of NIX_PATH above (to remove external overlays)
|
||||
# - or do: `nix run '.#check-nur'` via the toplevel flake.nix in this repo
|
||||
#
|
||||
# if it validates here but not upstream, likely to do with different `nixpkgs` inputs.
|
||||
# - CI logs: <https://github.com/nix-community/NUR/actions/workflows/update.yml>
|
||||
|
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 1369733,
|
||||
"content_type": "application/rss+xml; charset=utf-8",
|
||||
"description": "Every company has a story. Learn the playbooks that built the world’s greatest companies — and how you can apply them as a founder, operator, or investor.",
|
||||
"favicon": null,
|
||||
"hubs": [],
|
||||
"is_podcast": true,
|
||||
"is_push": false,
|
||||
"item_count": 173,
|
||||
"last_seen": "2023-01-11T15:26:37.515527+00:00",
|
||||
"last_updated": "2022-12-19T07:22:28+00:00",
|
||||
"score": 18,
|
||||
"self_url": "https://acquired.libsyn.com/rss",
|
||||
"site_name": null,
|
||||
"site_url": null,
|
||||
"title": "Acquired",
|
||||
"url": "https://acquired.libsyn.com/rss",
|
||||
"velocity": 0.066,
|
||||
"version": "rss20"
|
||||
}
|
@@ -1,21 +1,23 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 443732,
|
||||
"content_type": "application/rss+xml; charset=utf-8",
|
||||
"description": "Ben and David are joined by expert founders and investors \u2014 writing the next generation of great company stories in real-time.\n\nWe go behind the scenes on their journeys and bring back emerging insights and lessons that are useful for anyone in the tech and investing ecosystems.\n\nAcquired covers yesterday. ACQ2 covers tomorrow.",
|
||||
"content_length": 567579,
|
||||
"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": [],
|
||||
"hubs": [
|
||||
"https://pubsubhubbub.appspot.com/"
|
||||
],
|
||||
"is_podcast": true,
|
||||
"is_push": false,
|
||||
"item_count": 92,
|
||||
"last_updated": "2023-03-02T17:03:15+00:00",
|
||||
"score": 10,
|
||||
"self_url": "https://acquiredlpbonussecretsecret.libsyn.com/",
|
||||
"site_name": "ACQ2 by Acquired",
|
||||
"site_url": "https://acquiredlpbonussecretsecret.libsyn.com",
|
||||
"title": "ACQ2 by Acquired",
|
||||
"url": "https://acquiredlpbonussecretsecret.libsyn.com",
|
||||
"velocity": 0.057,
|
||||
"is_push": true,
|
||||
"item_count": 91,
|
||||
"last_updated": "2023-05-09T06:51:48+00:00",
|
||||
"score": 24,
|
||||
"self_url": "https://feeds.transistor.fm/acq2",
|
||||
"site_name": "ACQ2: The Acquired Interviews",
|
||||
"site_url": "https://feeds.transistor.fm",
|
||||
"title": "ACQ2: The Acquired Interviews",
|
||||
"url": "https://feeds.transistor.fm/acq2",
|
||||
"velocity": 0.054,
|
||||
"version": "rss20"
|
||||
}
|
File diff suppressed because one or more lines are too long
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 1579416,
|
||||
"content_type": "text/xml; charset=utf-8",
|
||||
"description": "Every company has a story.",
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [
|
||||
"https://pubsubhubbub.appspot.com/"
|
||||
],
|
||||
"is_podcast": true,
|
||||
"is_push": true,
|
||||
"item_count": 178,
|
||||
"last_updated": "2023-05-30T05:02:40+00:00",
|
||||
"score": 24,
|
||||
"self_url": "https://feeds.transistor.fm/acquired",
|
||||
"site_name": "",
|
||||
"site_url": "https://feeds.transistor.fm",
|
||||
"title": "Acquired",
|
||||
"url": "https://feeds.transistor.fm/acquired",
|
||||
"velocity": 0.064,
|
||||
"version": "rss20"
|
||||
}
|
File diff suppressed because one or more lines are too long
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 918085,
|
||||
"content_type": "application/xml; charset=utf-8",
|
||||
"description": "A show that cuts through all the political drivel and media misinformation to give you a straight take on one big news story of the week.",
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [],
|
||||
"is_podcast": true,
|
||||
"is_push": false,
|
||||
"item_count": 238,
|
||||
"last_updated": "2023-06-06T16:03:38+00:00",
|
||||
"score": 10,
|
||||
"self_url": "https://feeds.acast.com/public/shows/1d1223a2-9d05-473b-9e79-c2b65b71d676",
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"title": "Deconstructed",
|
||||
"url": "https://feeds.acast.com/public/shows/1d1223a2-9d05-473b-9e79-c2b65b71d676",
|
||||
"velocity": 0.123,
|
||||
"version": "rss20"
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 1131706,
|
||||
"content_type": "application/xml; charset=utf-8",
|
||||
"description": "The people behind The Intercept\u2019s fearless reporting and incisive commentary discuss the crucial issues of our time.",
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [],
|
||||
"is_podcast": true,
|
||||
"is_push": false,
|
||||
"item_count": 261,
|
||||
"last_updated": "2023-06-07T09:30:43+00:00",
|
||||
"score": 10,
|
||||
"self_url": "https://feeds.acast.com/public/shows/f5b64019-68c3-57d4-b70b-043e63e5cbf6",
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"title": "Intercepted",
|
||||
"url": "https://feeds.acast.com/public/shows/f5b64019-68c3-57d4-b70b-043e63e5cbf6",
|
||||
"velocity": 0.111,
|
||||
"version": "rss20"
|
||||
}
|
@@ -1,21 +1,21 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 235911,
|
||||
"content_length": 145311,
|
||||
"content_type": "application/xml; charset=utf-8",
|
||||
"description": "<p>The Portal is an exploration into discovery, including conversations with thought leaders. Host Eric Weinstein, Managing Director of Thiel Capital, brings his unique expertise and diverse roster of guests for a wide range of discussions, including science, culture, business, and capitalism. The show will feature people whose lives demonstrate that portals into what we would normally consider impossible, are indeed possible. Guests include presidential candidate Andrew Yang, NY Times bestselling author Sam Harris, and retired Navy Seal and creator of the hit business podcast Jocko Willink.</p>",
|
||||
"favicon": null,
|
||||
"favicon": "",
|
||||
"favicon_data_uri": "",
|
||||
"hubs": [],
|
||||
"is_podcast": true,
|
||||
"is_push": false,
|
||||
"item_count": 44,
|
||||
"last_seen": "2023-01-11T14:47:44.995855+00:00",
|
||||
"last_updated": "2020-12-02T07:50:55+00:00",
|
||||
"score": -12,
|
||||
"self_url": "https://www.omnycontent.com/d/playlist/9b7dacdf-a925-4f95-84dc-ac46003451ff/1713c520-edb6-43a3-b1b9-acb8002fdae7/58e33a0c-f86b-41c5-a11c-acb8002fdaf5/podcast.rss",
|
||||
"site_name": null,
|
||||
"site_url": null,
|
||||
"score": 8,
|
||||
"self_url": "",
|
||||
"site_name": "",
|
||||
"site_url": "",
|
||||
"title": "The Portal",
|
||||
"url": "https://www.omnycontent.com/d/playlist/9b7dacdf-a925-4f95-84dc-ac46003451ff/1713c520-edb6-43a3-b1b9-acb8002fdae7/58e33a0c-f86b-41c5-a11c-acb8002fdaf5/podcast.rss",
|
||||
"url": "https://feed.cdnstream1.com/zjb/feed/download/d9/8a/71/d98a71ac-d1a3-4d92-ab64-64b4ff3192d1.xml",
|
||||
"velocity": 0.082,
|
||||
"version": "rss20"
|
||||
}
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 809084,
|
||||
"content_type": "application/xml+rss; charset=utf-8",
|
||||
"description": "A show that cuts through all the political drivel and media misinformation to give you a straight take on one big news story of the week.",
|
||||
"favicon": null,
|
||||
"hubs": [],
|
||||
"is_podcast": true,
|
||||
"is_push": false,
|
||||
"item_count": 217,
|
||||
"last_seen": "2023-01-11T13:40:50.240217+00:00",
|
||||
"last_updated": "2023-01-06T10:37:50+00:00",
|
||||
"score": 16,
|
||||
"self_url": "https://feeds.acast.com/public/shows/1d1223a2-9d05-473b-9e79-c2b65b71d676",
|
||||
"site_name": null,
|
||||
"site_url": null,
|
||||
"title": "Deconstructed",
|
||||
"url": "https://rss.prod.firstlook.media/deconstructed/podcast.rss",
|
||||
"velocity": 0.122,
|
||||
"version": "rss20"
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"bozo": 0,
|
||||
"content_length": 1034995,
|
||||
"content_type": "application/xml+rss; charset=utf-8",
|
||||
"description": "The people behind The Intercept’s fearless reporting and incisive commentary discuss the crucial issues of our time.",
|
||||
"favicon": null,
|
||||
"hubs": [],
|
||||
"is_podcast": true,
|
||||
"is_push": false,
|
||||
"item_count": 243,
|
||||
"last_seen": "2023-01-11T14:04:41.283509+00:00",
|
||||
"last_updated": "2022-12-21T10:30:43+00:00",
|
||||
"score": 16,
|
||||
"self_url": "https://feeds.acast.com/public/shows/f5b64019-68c3-57d4-b70b-043e63e5cbf6",
|
||||
"site_name": null,
|
||||
"site_url": null,
|
||||
"title": "Intercepted",
|
||||
"url": "https://rss.prod.firstlook.media/intercepted/podcast.rss",
|
||||
"velocity": 0.112,
|
||||
"version": "rss20"
|
||||
}
|
@@ -2,12 +2,14 @@
|
||||
|
||||
{
|
||||
imports = [
|
||||
./dns.nix
|
||||
./feeds.nix
|
||||
./fs
|
||||
./ids.nix
|
||||
./programs.nix
|
||||
./image.nix
|
||||
./persist
|
||||
./ports.nix
|
||||
./services
|
||||
./sops.nix
|
||||
./ssh.nix
|
||||
|
145
modules/dns.nix
Normal file
145
modules/dns.nix
Normal file
@@ -0,0 +1,145 @@
|
||||
# TODO: consider using this library for .zone file generation:
|
||||
# - <https://github.com/kirelagin/dns.nix>
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with builtins;
|
||||
let
|
||||
cfg = config.sane.dns;
|
||||
toml = pkgs.formats.toml { };
|
||||
recordFormatters = {
|
||||
# quote rules for zone files:
|
||||
# - any character may be encoded by `\DDD`, where `DDD` represents its ascii value in base 8.
|
||||
# - any non-digit `X` may be encoded by `\X`.
|
||||
# - stated in: <https://www.ietf.org/rfc/rfc1035.txt>: 5.1 Format
|
||||
# - visible in <trust-dns:crates/proto/src/serialize/txt/zone_lex.rs:escape_seq>
|
||||
# for us, we can just replace `\` => `\\ and `"` -> `\"`
|
||||
TXT = value: "\"" + (lib.escape [ "\\" "\"" ] value) + "\"";
|
||||
};
|
||||
# proto: "INET", etc
|
||||
# rrtype: "TXT", "A", "CNAME", etc
|
||||
fmtRecord = proto: rrtype: name: value:
|
||||
let
|
||||
formatter = recordFormatters."${rrtype}" or lib.id;
|
||||
in
|
||||
"${name}\t${proto}\t${rrtype}\t${formatter value}";
|
||||
fmtRecordList = proto: rrtype: name: values: concatStringsSep
|
||||
"\n"
|
||||
(map (fmtRecord proto rrtype name) values)
|
||||
;
|
||||
fmtRecordAttrs = proto: rrtype: rrAttrs:
|
||||
concatStringsSep
|
||||
"\n"
|
||||
(
|
||||
attrValues (
|
||||
mapAttrs
|
||||
(name: fmtRecordList proto rrtype name)
|
||||
rrAttrs
|
||||
)
|
||||
);
|
||||
# format other .zone files to include into this one
|
||||
fmtIncludes = paths: concatStringsSep
|
||||
"\n"
|
||||
(map (path: "$INCLUDE ${path}") paths);
|
||||
|
||||
genZone = zcfg: ''
|
||||
$TTL ${toString zcfg.TTL}
|
||||
${fmtRecordAttrs "IN" "SOA" zcfg.inet.SOA}
|
||||
${fmtRecordAttrs "IN" "A" zcfg.inet.A}
|
||||
${fmtRecordAttrs "IN" "CNAME" zcfg.inet.CNAME}
|
||||
${fmtRecordAttrs "IN" "MX" zcfg.inet.MX}
|
||||
${fmtRecordAttrs "IN" "NS" zcfg.inet.NS}
|
||||
${fmtRecordAttrs "IN" "SRV" zcfg.inet.SRV}
|
||||
${fmtRecordAttrs "IN" "TXT" zcfg.inet.TXT}
|
||||
${fmtIncludes zcfg.include}
|
||||
${zcfg.extraConfig}
|
||||
'';
|
||||
|
||||
# (listOf ty) type which also accepts single-assignment of `ty`.
|
||||
# it's used to allow the user to write:
|
||||
# CNAME."foo" = "bar";
|
||||
# as shorthand for
|
||||
# CNAME."foo" = [ "bar" ];
|
||||
listOrUnit = with lib; ty: types.coercedTo ty (elem: [ elem ]) (types.listOf ty);
|
||||
in
|
||||
{
|
||||
options = {
|
||||
sane.dns = with lib; {
|
||||
zones = mkOption {
|
||||
description = ''
|
||||
declarative zone config.
|
||||
this doesn't feed into anything, rather, one should read `config.sane.dns.zones."foo".rendered`
|
||||
and do something with it.
|
||||
'';
|
||||
default = {};
|
||||
type = types.attrsOf (types.submodule ({ name, config, ... }: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
description = "zone name. defaults to the attribute name in zones";
|
||||
default = name;
|
||||
};
|
||||
rendered = mkOption {
|
||||
type = types.str;
|
||||
description = "rendered .zone text for this zone (read-only)";
|
||||
};
|
||||
TTL = mkOption {
|
||||
type = types.int;
|
||||
description = "default TTL";
|
||||
default = 3600;
|
||||
};
|
||||
include = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "paths of other zone files to $INCLUDE into this one";
|
||||
default = [];
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
description = "extra lines to append to the zone file";
|
||||
default = "";
|
||||
};
|
||||
inet = {
|
||||
SOA = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "Start of Authority record(s)";
|
||||
default = {};
|
||||
};
|
||||
A = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "IPv4 address record(s)";
|
||||
default = {};
|
||||
};
|
||||
CNAME = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "canonical name record(s)";
|
||||
default = {};
|
||||
};
|
||||
MX = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "mail exchanger record(s)";
|
||||
default = {};
|
||||
};
|
||||
NS = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "name server record(s)";
|
||||
default = {};
|
||||
};
|
||||
SRV = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "service record(s)";
|
||||
default = {};
|
||||
};
|
||||
TXT = mkOption {
|
||||
type = types.attrsOf (listOrUnit types.str);
|
||||
description = "text record(s)";
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
config = {
|
||||
rendered = genZone config;
|
||||
};
|
||||
}));
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
@@ -24,6 +24,8 @@ let path = rec {
|
||||
# return the last path component; error on the empty path
|
||||
leaf = str: lib.last (split str);
|
||||
|
||||
# XXX: this is bugged in that
|
||||
# from "/foo/bar" "/foo/barbag" => "/bag"
|
||||
from = start: end: let
|
||||
s = path.norm start;
|
||||
e = path.norm end;
|
||||
@@ -32,6 +34,12 @@ let path = rec {
|
||||
"/" + (lib.removePrefix s e)
|
||||
);
|
||||
|
||||
isChild = parent: child:
|
||||
lib.any
|
||||
(p: p == norm parent)
|
||||
(walk "/" child)
|
||||
;
|
||||
|
||||
# yield every node between start and end, including each the endpoints
|
||||
# e.g. walk "/foo" "/foo/bar/baz" => [ "/foo" "/foo/bar" "/foo/bar/baz" ]
|
||||
# XXX: assumes input paths are normalized
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user