Compare commits
256 Commits
wip/feeds2
...
wip/packag
Author | SHA1 | Date | |
---|---|---|---|
09cb75319f | |||
4ed0a9127c | |||
d0dca651be | |||
0e756d5064 | |||
a52ead5aec | |||
c0377ff1a0 | |||
062ef20d05 | |||
a0861edc5f | |||
eae075acb5 | |||
ef2ba01141 | |||
2756e15bab | |||
940aac3a22 | |||
5f24e029af | |||
98b542332b | |||
70b62e9f76 | |||
7c81df00df | |||
f288f34d1e | |||
854977c3aa | |||
3653776399 | |||
e4bff9b5ef | |||
ec22c128e0 | |||
77cc560052 | |||
c1f3fc502d | |||
4d3248d315 | |||
45a1c07210 | |||
a1a711190f | |||
ee9a2b320d | |||
870afec07e | |||
5f8154e6ce | |||
0bc3b78a52 | |||
5288be1822 | |||
5b1113929a | |||
216c812f7b | |||
39effa15ad | |||
f66de76b76 | |||
427ee669c5 | |||
8e81b5827c | |||
cb3e7623ae | |||
a9cf619a14 | |||
02100ed1a2 | |||
ae22865099 | |||
6c85c6ecd8 | |||
161bbc1159 | |||
b94d0672cc | |||
768bc35940 | |||
9aca00c186 | |||
443100daa4 | |||
ac25909a10 | |||
ed70e045cb | |||
e9172fe731 | |||
fd19802e91 | |||
d84846e293 | |||
b46ccb9bc2 | |||
1958c1f36b | |||
67299ebfd7 | |||
adecfbaea4 | |||
fa4a576703 | |||
abb0a3c94e | |||
32612e6acb | |||
e0a3979b65 | |||
4d84ca0878 | |||
1ae8ab2550 | |||
ed1380ba70 | |||
e1b8d3ccc3 | |||
392ad7c674 | |||
4026334e51 | |||
2269016736 | |||
f2c61d64b7 | |||
840c2feba5 | |||
4603f0fd8e | |||
64704d361b | |||
7df18686e0 | |||
aee928dac0 | |||
76c0c3dc6a | |||
796988bdeb | |||
31d28ccf23 | |||
a298678622 | |||
32eb3b1998 | |||
7a726b8d08 | |||
3edbb1c873 | |||
d94687e8cc | |||
641ffc3452 | |||
fa8016db67 | |||
0c9cc87728 | |||
5236da2383 | |||
aa24eebf40 | |||
3cc0d7ec40 | |||
42c2d93306 | |||
f6f8d0e19d | |||
8ad4d8a4f9 | |||
d419e10f10 | |||
c56734e00e | |||
e095149797 | |||
6006b84f9e | |||
b3b914bc2e | |||
d6f87c7ee7 | |||
028d78437b | |||
0539bb8fd5 | |||
95cc42f057 | |||
54cfde0e30 | |||
b358cbe02a | |||
64cd562824 | |||
749f59a4af | |||
77d5ff623e | |||
6386abb8c6 | |||
28f8434c53 | |||
30fafb4837 | |||
c7205ed668 | |||
c69c6612fe | |||
6951b277ad | |||
1167c9bd0c | |||
8537fe411b | |||
1fb2ddbecc | |||
27608cb8c7 | |||
33ee59e80d | |||
edacc28e4a | |||
99780e30bc | |||
140dd05bd1 | |||
c35bc92ac9 | |||
16b92f98e7 | |||
576b63da9c | |||
e434add20d | |||
d288086aa2 | |||
e9c0f692d8 | |||
5a75d0f56b | |||
a222cf18a3 | |||
45b9ee763b | |||
50a2196495 | |||
e4419ffad4 | |||
ae3ba64fc3 | |||
948b2489d3 | |||
abe491b563 | |||
9911593a63 | |||
798ba7f7e3 | |||
f72e901f57 | |||
2047222233 | |||
5d33cb66d6 | |||
6fded1f256 | |||
1d1c528abc | |||
35fdd2788f | |||
77cb951545 | |||
1909e0fbe8 | |||
33d7819619 | |||
0846abb6bf | |||
f3568462c2 | |||
ed9291a443 | |||
9eac7f7c02 | |||
f5eaa635a5 | |||
47db6f0dd4 | |||
bba7efc535 | |||
358b673344 | |||
d9c101689d | |||
ccbb573681 | |||
f5c270233f | |||
bf92bb48be | |||
2037b425d6 | |||
026746a76f | |||
de74c4e7d5 | |||
34a5f3f49b | |||
ee93141c07 | |||
f2d22231a3 | |||
d5334e65ad | |||
17cdfff286 | |||
8d4ff6d4e6 | |||
5d78bc6704 | |||
4da19a6d34 | |||
2f75925678 | |||
55a1856e87 | |||
2ee0f4efe2 | |||
b0c5a5907f | |||
9af157b294 | |||
c36fed8547 | |||
a653311f04 | |||
f4d6ecb1cf | |||
c2e5a0a2fc | |||
c316e51344 | |||
f4f0c1bdd6 | |||
6a2374e046 | |||
708cb841fe | |||
094b7223c7 | |||
f6dfc9cf29 | |||
7c2ab92302 | |||
7c18d77046 | |||
02f316f7f8 | |||
df848b3262 | |||
1e67b5c97e | |||
a3a7b6c563 | |||
e527beb9d0 | |||
2e942e2dd4 | |||
f46e3fdf01 | |||
038a9034d7 | |||
5a232eb832 | |||
9301b95dbb | |||
d13bcc49ab | |||
35e28041cd | |||
58a5a8b56d | |||
e6d4ff3c6a | |||
be29ad8bd8 | |||
0fb8e2c867 | |||
580c1b74cb | |||
f8595f1ed6 | |||
1deda148bb | |||
5bbef18130 | |||
6967c331e2 | |||
9202345beb | |||
17a8cabc09 | |||
bc190f90bd | |||
bb983a5328 | |||
0e8fc29b01 | |||
4e14f063fc | |||
10d69fb0a4 | |||
7aac965e32 | |||
98ae1a8513 | |||
72a2ab78f3 | |||
18c98feb34 | |||
487af9b492 | |||
472d25c056 | |||
9eafacad12 | |||
0eb46a3179 | |||
ddb184b5ff | |||
194a6b6cf4 | |||
016384aa2b | |||
b4e19c037e | |||
bd504f6c83 | |||
bdd309eb15 | |||
eedc1170ec | |||
5a586c6e3c | |||
371bcad650 | |||
926decbea5 | |||
c0f76ea8d8 | |||
40fc37930f | |||
30e7eb9ab6 | |||
2e03f47edc | |||
4d552e3f0f | |||
176a98879d | |||
fc70889c34 | |||
49b4c57826 | |||
5111d095ac | |||
fe15cdd705 | |||
638420ea0d | |||
d55dd5ace6 | |||
45695aed6b | |||
d6e79c4d07 | |||
380ceaf625 | |||
942c581107 | |||
b6d94c2e08 | |||
fd7acc8fc8 | |||
db670fc172 | |||
6438971c8c | |||
e439d398b6 | |||
0f25cba331 | |||
39959e912d | |||
62e649743d | |||
b1741a18e1 | |||
a829a8e027 | |||
d742ae83bd |
85
flake.lock
generated
85
flake.lock
generated
@@ -15,35 +15,14 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home-manager": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1667907331,
|
|
||||||
"narHash": "sha256-bHkAwkYlBjkupPUFcQjimNS8gxWSWjOTevEuwdnp5m0=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "home-manager",
|
|
||||||
"rev": "6639e3a837fc5deb6f99554072789724997bc8e5",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"ref": "release-22.05",
|
|
||||||
"repo": "home-manager",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mobile-nixos": {
|
"mobile-nixos": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1670131242,
|
"lastModified": 1674880620,
|
||||||
"narHash": "sha256-T/o1/3gffr010fsqgNshs1NJJjsnUYvQnUZgm6hilsY=",
|
"narHash": "sha256-JMALuC7xcoH/T66sKTVLuItHfOJBCWsNKpE49Qrvs80=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "mobile-nixos",
|
"repo": "mobile-nixos",
|
||||||
"rev": "5ee45cc1f8e43f4af14ee17ccef9156b0db8cd77",
|
"rev": "7478a9ffad737486951186b66f6c5535dc5802e2",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -60,37 +39,22 @@
|
|||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1,
|
"lastModified": 1,
|
||||||
"narHash": "sha256-5eJxyBRYQCoRt92ZFUOdT237Z0VscuNRd0pktDYWJYE=",
|
"narHash": "sha256-arp7Uy7ct5ryTcmSY032eN7hr33i7D2XvjTRLliCFDc=",
|
||||||
"path": "nixpatches",
|
"path": "/nix/store/jblp2g67p3wid2qarcyd8bzrbs9wg5lb-source/nixpatches",
|
||||||
"type": "path"
|
"type": "path"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"path": "nixpatches",
|
"path": "/nix/store/jblp2g67p3wid2qarcyd8bzrbs9wg5lb-source/nixpatches",
|
||||||
"type": "path"
|
"type": "path"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs-stable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1673163619,
|
"lastModified": 1674352297,
|
||||||
"narHash": "sha256-B33PFBL64ZgTWgMnhFL3jgheAN/DjHPsZ1Ih3z0VE5I=",
|
"narHash": "sha256-OkAnJPrauEcUCrst4/3DKoQfUn2gXKuU6CFvhtMrLgg=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "8c54d842d9544361aac5f5b212ba04e4089e8efe",
|
"rev": "918b760070bb8f48cb511300fcd7e02e13058a2e",
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"id": "nixpkgs",
|
|
||||||
"ref": "nixos-22.11",
|
|
||||||
"type": "indirect"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-stable_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1673100377,
|
|
||||||
"narHash": "sha256-mT76pTd0YFxT6CwtPhDgHJhuIgLY+ZLSMiQpBufwMG4=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "9f11a2df77cb945c115ae2a65f53f38121597d73",
|
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -102,25 +66,24 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-unpatched": {
|
"nixpkgs-unpatched": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1673226411,
|
"lastModified": 1674641431,
|
||||||
"narHash": "sha256-b6cGb5Ln7Zy80YO66+cbTyGdjZKtkoqB/iIIhDX9gRA=",
|
"narHash": "sha256-qfo19qVZBP4qn5M5gXc/h1MDgAtPA5VxJm9s8RUAkVk=",
|
||||||
"owner": "NixOS",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "aa1d74709f5dac623adb4d48fdfb27cc2c92a4d4",
|
"rev": "9b97ad7b4330aacda9b2343396eb3df8a853b4fc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"id": "nixpkgs",
|
"owner": "nixos",
|
||||||
"ref": "nixos-unstable",
|
"ref": "nixos-unstable",
|
||||||
"type": "indirect"
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"home-manager": "home-manager",
|
|
||||||
"mobile-nixos": "mobile-nixos",
|
"mobile-nixos": "mobile-nixos",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"nixpkgs-stable": "nixpkgs-stable",
|
|
||||||
"nixpkgs-unpatched": "nixpkgs-unpatched",
|
"nixpkgs-unpatched": "nixpkgs-unpatched",
|
||||||
"sops-nix": "sops-nix",
|
"sops-nix": "sops-nix",
|
||||||
"uninsane-dot-org": "uninsane-dot-org"
|
"uninsane-dot-org": "uninsane-dot-org"
|
||||||
@@ -131,14 +94,14 @@
|
|||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
],
|
],
|
||||||
"nixpkgs-stable": "nixpkgs-stable_2"
|
"nixpkgs-stable": "nixpkgs-stable"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1673147300,
|
"lastModified": 1674546403,
|
||||||
"narHash": "sha256-gR9OEfTzWfL6vG0qkbn1TlBAOlg4LuW8xK/u0V41Ihc=",
|
"narHash": "sha256-vkyNv0xzXuEnu9v52TUtRugNmQWIti8c2RhYnbLG71w=",
|
||||||
"owner": "Mic92",
|
"owner": "Mic92",
|
||||||
"repo": "sops-nix",
|
"repo": "sops-nix",
|
||||||
"rev": "2253120d2a6147e57bafb5c689e086221df8032f",
|
"rev": "b6ab3c61e2ca5e07d1f4eb1b67304e2670ea230c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -155,11 +118,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1666870107,
|
"lastModified": 1675131883,
|
||||||
"narHash": "sha256-b9eXZxSwhzdJI5uQgfrMhu4SY2POrPkinUg7F5gQVYo=",
|
"narHash": "sha256-yBgJDG72YqIr1bltasqHD1E/kHc9uRFgDjxDmy6kI8M=",
|
||||||
"ref": "refs/heads/master",
|
"ref": "refs/heads/master",
|
||||||
"rev": "80c6ec95bd430e29d231cf745f19279bb76fb382",
|
"rev": "b099c24091cc192abf3997b94342d4b31cc5757b",
|
||||||
"revCount": 164,
|
"revCount": 170,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.uninsane.org/colin/uninsane"
|
"url": "https://git.uninsane.org/colin/uninsane"
|
||||||
},
|
},
|
||||||
|
61
flake.nix
61
flake.nix
@@ -1,24 +1,39 @@
|
|||||||
# docs:
|
# FLAKE FEEDBACK:
|
||||||
# - <https://nixos.wiki/wiki/Flakes>
|
# - if flake inputs are meant to be human-readable, a human should be able to easily track them down given the URL.
|
||||||
|
# - this is not the case with registry URLs, like `nixpkgs/nixos-22.11`.
|
||||||
|
# - this is marginally the case with schemes like `github:nixos/nixpkgs`.
|
||||||
|
# - given the *existing* `git+https://` scheme, i propose expressing github URLs similarly:
|
||||||
|
# - `github+https://github.com/nixos/nixpkgs/tree/nixos-22.11`
|
||||||
|
# - need some way to apply local patches to inputs.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# DEVELOPMENT DOCS:
|
||||||
|
# - Flake docs: <https://nixos.wiki/wiki/Flakes>
|
||||||
|
# - Flake RFC: <https://github.com/tweag/rfcs/blob/flakes/rfcs/0049-flakes.md>
|
||||||
|
# - Discussion: <https://github.com/NixOS/rfcs/pull/49>
|
||||||
# - <https://serokell.io/blog/practical-nix-flakes>
|
# - <https://serokell.io/blog/practical-nix-flakes>
|
||||||
|
|
||||||
{
|
{
|
||||||
|
# XXX: use the `github:` scheme instead of the more readable git+https: because it's *way* more efficient
|
||||||
|
# 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 = {
|
inputs = {
|
||||||
nixpkgs-stable.url = "nixpkgs/nixos-22.11";
|
# <https://github.com/nixos/nixpkgs/tree/nixos-22.11>
|
||||||
nixpkgs-unpatched.url = "nixpkgs/nixos-unstable";
|
# nixpkgs-stable.url = "github:nixos/nixpkgs?ref=nixos-22.11";
|
||||||
|
|
||||||
|
# <https://github.com/nixos/nixpkgs/tree/nixos-unstable>
|
||||||
|
nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||||
nixpkgs = {
|
nixpkgs = {
|
||||||
url = "path:nixpatches";
|
url = "./nixpatches";
|
||||||
inputs.nixpkgs.follows = "nixpkgs-unpatched";
|
inputs.nixpkgs.follows = "nixpkgs-unpatched";
|
||||||
};
|
};
|
||||||
mobile-nixos = {
|
mobile-nixos = {
|
||||||
|
# <https://github.com/nixos/mobile-nixos>
|
||||||
url = "github:nixos/mobile-nixos";
|
url = "github:nixos/mobile-nixos";
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
home-manager = {
|
|
||||||
url = "github:nix-community/home-manager/release-22.05";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
sops-nix = {
|
sops-nix = {
|
||||||
|
# <https://github.com/Mic92/sops-nix>
|
||||||
url = "github:Mic92/sops-nix";
|
url = "github:Mic92/sops-nix";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
@@ -31,22 +46,23 @@
|
|||||||
outputs = {
|
outputs = {
|
||||||
self,
|
self,
|
||||||
nixpkgs,
|
nixpkgs,
|
||||||
nixpkgs-stable,
|
|
||||||
nixpkgs-unpatched,
|
nixpkgs-unpatched,
|
||||||
mobile-nixos,
|
mobile-nixos,
|
||||||
home-manager,
|
|
||||||
sops-nix,
|
sops-nix,
|
||||||
uninsane-dot-org
|
uninsane-dot-org,
|
||||||
}:
|
...
|
||||||
|
}@inputs:
|
||||||
let
|
let
|
||||||
nixpkgsCompiledBy = local: nixpkgs.legacyPackages."${local}";
|
nixpkgsCompiledBy = local: nixpkgs.legacyPackages."${local}";
|
||||||
|
|
||||||
evalHost = { name, local, target }:
|
evalHost = { name, local, target }:
|
||||||
let
|
let
|
||||||
# XXX: we'd prefer to use `nixosSystem = (nixpkgsCompiledBy local).nixos`
|
# XXX: we'd prefer to use `nixosSystem = (nixpkgsCompiledBy target).nixos`
|
||||||
# but it doesn't propagate config to the underlying pkgs, meaning it doesn't let you use
|
# but it doesn't propagate config to the underlying pkgs, meaning it doesn't let you use
|
||||||
# non-free packages even after setting nixpkgs.allowUnfree.
|
# non-free packages even after setting nixpkgs.allowUnfree.
|
||||||
nixosSystem = import ((nixpkgsCompiledBy local).path + "/nixos/lib/eval-config.nix");
|
# XXX: patch using the target -- not local -- otherwise the target will
|
||||||
|
# need to emulate the host in order to rebuild!
|
||||||
|
nixosSystem = import ((nixpkgsCompiledBy target).path + "/nixos/lib/eval-config.nix");
|
||||||
in
|
in
|
||||||
(nixosSystem {
|
(nixosSystem {
|
||||||
# we use pkgs built for and *by* the target, i.e. emulation, by default.
|
# we use pkgs built for and *by* the target, i.e. emulation, by default.
|
||||||
@@ -60,6 +76,7 @@
|
|||||||
nixpkgs.overlays = [
|
nixpkgs.overlays = [
|
||||||
self.overlays.default
|
self.overlays.default
|
||||||
self.overlays.passthru
|
self.overlays.passthru
|
||||||
|
self.overlays.pins
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@@ -96,12 +113,16 @@
|
|||||||
|
|
||||||
overlays = rec {
|
overlays = rec {
|
||||||
default = pkgs;
|
default = pkgs;
|
||||||
pkgs = import ./pkgs/overlay.nix;
|
pkgs = import ./overlays/pkgs.nix;
|
||||||
|
pins = import ./overlays/pins.nix; # TODO: move to `nixpatches/` input
|
||||||
passthru =
|
passthru =
|
||||||
let
|
let
|
||||||
stable = next: prev: {
|
stable =
|
||||||
stable = nixpkgs-stable.legacyPackages."${prev.stdenv.hostPlatform}";
|
if inputs ? "nixpkgs-stable" then (
|
||||||
};
|
next: prev: {
|
||||||
|
stable = inputs.nixpkgs-stable.legacyPackages."${prev.stdenv.hostPlatform.system}";
|
||||||
|
}
|
||||||
|
) else (next: prev: {});
|
||||||
mobile = (import "${mobile-nixos}/overlay/overlay.nix");
|
mobile = (import "${mobile-nixos}/overlay/overlay.nix");
|
||||||
uninsane = uninsane-dot-org.overlay;
|
uninsane = uninsane-dot-org.overlay;
|
||||||
in
|
in
|
||||||
@@ -114,7 +135,6 @@
|
|||||||
sane = import ./modules;
|
sane = import ./modules;
|
||||||
passthru = { ... }: {
|
passthru = { ... }: {
|
||||||
imports = [
|
imports = [
|
||||||
home-manager.nixosModule
|
|
||||||
sops-nix.nixosModules.sops
|
sops-nix.nixosModules.sops
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
@@ -146,6 +166,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
init-feed = {
|
init-feed = {
|
||||||
|
# use like `nix run '.#init-feed' uninsane.org`
|
||||||
type = "app";
|
type = "app";
|
||||||
program = "${pkgs.feeds.passthru.initFeedScript}";
|
program = "${pkgs.feeds.passthru.initFeedScript}";
|
||||||
};
|
};
|
||||||
|
@@ -6,12 +6,16 @@
|
|||||||
|
|
||||||
# sane.packages.enableDevPkgs = true;
|
# sane.packages.enableDevPkgs = true;
|
||||||
|
|
||||||
sane.gui.sway.enable = true;
|
sane.roles.client = true;
|
||||||
|
sane.services.wg-home.enable = true;
|
||||||
|
sane.services.wg-home.ip = config.sane.hosts.by-name."desko".wg-home.ip;
|
||||||
sane.services.duplicity.enable = true;
|
sane.services.duplicity.enable = true;
|
||||||
sane.services.nixserve.enable = true;
|
sane.services.nixserve.enable = true;
|
||||||
sane.services.nixserve.sopsFile = ../../secrets/desko.yaml;
|
sane.services.nixserve.sopsFile = ../../../secrets/desko.yaml;
|
||||||
sane.persist.enable = true;
|
sane.persist.enable = true;
|
||||||
|
|
||||||
|
sane.gui.sway.enable = true;
|
||||||
|
|
||||||
boot.loader.efi.canTouchEfiVariables = false;
|
boot.loader.efi.canTouchEfiVariables = false;
|
||||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||||
|
|
||||||
@@ -19,7 +23,7 @@
|
|||||||
services.usbmuxd.enable = true;
|
services.usbmuxd.enable = true;
|
||||||
|
|
||||||
sops.secrets.colin-passwd = {
|
sops.secrets.colin-passwd = {
|
||||||
sopsFile = ../../secrets/desko.yaml;
|
sopsFile = ../../../secrets/desko.yaml;
|
||||||
neededForUsers = true;
|
neededForUsers = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,7 +45,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets.duplicity_passphrase = {
|
sops.secrets.duplicity_passphrase = {
|
||||||
sopsFile = ../../secrets/desko.yaml;
|
sopsFile = ../../../secrets/desko.yaml;
|
||||||
};
|
};
|
||||||
|
|
||||||
programs.steam = {
|
programs.steam = {
|
||||||
@@ -50,7 +54,7 @@
|
|||||||
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
|
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
|
||||||
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
|
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
|
||||||
};
|
};
|
||||||
sane.persist.home.plaintext = [
|
sane.user.persist.plaintext = [
|
||||||
".steam"
|
".steam"
|
||||||
".local/share/Steam"
|
".local/share/Steam"
|
||||||
];
|
];
|
@@ -1,12 +1,16 @@
|
|||||||
{ pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./fs.nix
|
./fs.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
sane.roles.client = true;
|
||||||
|
sane.services.wg-home.enable = true;
|
||||||
|
sane.services.wg-home.ip = config.sane.hosts.by-name."lappy".wg-home.ip;
|
||||||
|
|
||||||
# sane.packages.enableDevPkgs = true;
|
# sane.packages.enableDevPkgs = true;
|
||||||
|
|
||||||
# sane.users.guest.enable = true;
|
# sane.guest.enable = true;
|
||||||
sane.gui.sway.enable = true;
|
sane.gui.sway.enable = true;
|
||||||
sane.persist.enable = true;
|
sane.persist.enable = true;
|
||||||
sane.nixcache.enable = true;
|
sane.nixcache.enable = true;
|
||||||
@@ -14,7 +18,7 @@
|
|||||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||||
|
|
||||||
sops.secrets.colin-passwd = {
|
sops.secrets.colin-passwd = {
|
||||||
sopsFile = ../../secrets/lappy.yaml;
|
sopsFile = ../../../secrets/lappy.yaml;
|
||||||
neededForUsers = true;
|
neededForUsers = true;
|
||||||
};
|
};
|
||||||
|
|
@@ -6,6 +6,10 @@
|
|||||||
./kernel.nix
|
./kernel.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
sane.roles.client = true;
|
||||||
|
sane.services.wg-home.enable = true;
|
||||||
|
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;
|
||||||
|
|
||||||
# cross-compiled documentation is *slow*.
|
# cross-compiled documentation is *slow*.
|
||||||
# no obvious way to natively compile docs (2022/09/29).
|
# no obvious way to natively compile docs (2022/09/29).
|
||||||
# entrypoint is nixos/modules/misc/documentation.nix
|
# entrypoint is nixos/modules/misc/documentation.nix
|
||||||
@@ -19,14 +23,21 @@
|
|||||||
services.getty.autologinUser = "root"; # allows for emergency maintenance?
|
services.getty.autologinUser = "root"; # allows for emergency maintenance?
|
||||||
|
|
||||||
sops.secrets.colin-passwd = {
|
sops.secrets.colin-passwd = {
|
||||||
sopsFile = ../../secrets/moby.yaml;
|
sopsFile = ../../../secrets/moby.yaml;
|
||||||
neededForUsers = true;
|
neededForUsers = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
# usability compromises
|
sane.web-browser = {
|
||||||
sane.web-browser.persistCache = "private";
|
# compromise impermanence for the sake of usability
|
||||||
sane.web-browser.persistData = "private";
|
persistCache = "private";
|
||||||
sane.persist.home.plaintext = [
|
persistData = "private";
|
||||||
|
|
||||||
|
# i don't do crypto stuff on moby
|
||||||
|
addons.ether-metamask.enable = false;
|
||||||
|
# addons.sideberry.enable = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
sane.user.persist.plaintext = [
|
||||||
".config/pulse" # persist pulseaudio volume
|
".config/pulse" # persist pulseaudio volume
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -54,9 +65,10 @@
|
|||||||
|
|
||||||
# without this some GUI apps fail: `DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory`
|
# without this some GUI apps fail: `DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory`
|
||||||
# this is because they can't allocate enough video ram.
|
# this is because they can't allocate enough video ram.
|
||||||
# the default CMA seems to be 32M. we could probably get by with as little as 64M, and safely with 128M.
|
# the default CMA seems to be 32M.
|
||||||
|
# i was running fine with 256MB from 2022/07-ish through 2022/12-ish, but then the phone quit reliably coming back from sleep: maybe a memory leak?
|
||||||
# `cat /proc/meminfo` to see CmaTotal/CmaFree if interested in tuning this.
|
# `cat /proc/meminfo` to see CmaTotal/CmaFree if interested in tuning this.
|
||||||
boot.kernelParams = [ "cma=256M" ];
|
boot.kernelParams = [ "cma=512M" ];
|
||||||
|
|
||||||
# mobile-nixos' /lib/firmware includes:
|
# mobile-nixos' /lib/firmware includes:
|
||||||
# rtl_bt (bluetooth)
|
# rtl_bt (bluetooth)
|
@@ -125,6 +125,9 @@ in
|
|||||||
# aarch64-unknown-linux-gnu-gcc: error: unrecognized command line option '-mfpu=neon'
|
# aarch64-unknown-linux-gnu-gcc: error: unrecognized command line option '-mfpu=neon'
|
||||||
# make[3]: *** [../scripts/Makefile.build:289: drivers/video/fbdev/sun5i-eink-neon.o] Error 1
|
# make[3]: *** [../scripts/Makefile.build:289: drivers/video/fbdev/sun5i-eink-neon.o] Error 1
|
||||||
FB_SUN5I_EINK = no;
|
FB_SUN5I_EINK = no;
|
||||||
|
# used by the pinephone pro, but fails to compile with:
|
||||||
|
# ../drivers/media/i2c/ov8858.c:1834:27: error: implicit declaration of function 'compat_ptr'
|
||||||
|
VIDEO_OV8858 = no;
|
||||||
})
|
})
|
||||||
))
|
))
|
||||||
];
|
];
|
@@ -1,29 +1,32 @@
|
|||||||
{ pkgs, ... }:
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./fs.nix
|
./fs.nix
|
||||||
./net.nix
|
./net.nix
|
||||||
./users.nix
|
./secrets.nix
|
||||||
./services
|
./services
|
||||||
];
|
];
|
||||||
|
|
||||||
sane.packages.extraUserPkgs = [
|
sane.packages.extraUserPkgs = with pkgs; [
|
||||||
# for administering services
|
# for administering services
|
||||||
pkgs.matrix-synapse
|
freshrss
|
||||||
pkgs.freshrss
|
matrix-synapse
|
||||||
|
signaldctl
|
||||||
];
|
];
|
||||||
sane.persist.enable = true;
|
sane.persist.enable = true;
|
||||||
sane.services.dyn-dns.enable = true;
|
sane.services.dyn-dns.enable = true;
|
||||||
|
sane.services.wg-home.enable = 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
|
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade
|
||||||
|
|
||||||
|
# automatically log in at the virtual consoles.
|
||||||
|
# using root here makes sure we always have an escape hatch
|
||||||
|
services.getty.autologinUser = "root";
|
||||||
|
|
||||||
boot.loader.efi.canTouchEfiVariables = false;
|
boot.loader.efi.canTouchEfiVariables = false;
|
||||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||||
|
|
||||||
sops.secrets.duplicity_passphrase = {
|
|
||||||
sopsFile = ../../secrets/servo.yaml;
|
|
||||||
};
|
|
||||||
|
|
||||||
# both transmission and ipfs try to set different net defaults.
|
# both transmission and ipfs try to set different net defaults.
|
||||||
# we just use the most aggressive of the two here:
|
# we just use the most aggressive of the two here:
|
||||||
boot.kernel.sysctl = {
|
boot.kernel.sysctl = {
|
@@ -52,18 +52,18 @@
|
|||||||
|
|
||||||
# services.resolved.extraConfig = ''
|
# services.resolved.extraConfig = ''
|
||||||
# # docs: `man resolved.conf`
|
# # docs: `man resolved.conf`
|
||||||
# # DNS servers to use via the `wg0` interface.
|
# # DNS servers to use via the `wg-ovpns` interface.
|
||||||
# # i hope that from the root ns, these aren't visible.
|
# # i hope that from the root ns, these aren't visible.
|
||||||
# DNS=46.227.67.134%wg0 192.165.9.158%wg0
|
# DNS=46.227.67.134%wg-ovpns 192.165.9.158%wg-ovpns
|
||||||
# FallbackDNS=1.1.1.1 9.9.9.9
|
# FallbackDNS=1.1.1.1 9.9.9.9
|
||||||
# '';
|
# '';
|
||||||
|
|
||||||
# OVPN CONFIG (https://www.ovpn.com):
|
# OVPN CONFIG (https://www.ovpn.com):
|
||||||
# DOCS: https://nixos.wiki/wiki/WireGuard
|
# DOCS: https://nixos.wiki/wiki/WireGuard
|
||||||
# if you `systemctl restart wireguard-wg0`, make sure to also restart any other services in `NetworkNamespacePath = .../ovpns`.
|
# if you `systemctl restart wireguard-wg-ovpns`, make sure to also restart any other services in `NetworkNamespacePath = .../ovpns`.
|
||||||
# TODO: why not create the namespace as a seperate operation (nix config for that?)
|
# TODO: why not create the namespace as a seperate operation (nix config for that?)
|
||||||
networking.wireguard.enable = true;
|
networking.wireguard.enable = true;
|
||||||
networking.wireguard.interfaces.wg0 = let
|
networking.wireguard.interfaces.wg-ovpns = let
|
||||||
ip = "${pkgs.iproute2}/bin/ip";
|
ip = "${pkgs.iproute2}/bin/ip";
|
||||||
in-ns = "${ip} netns exec ovpns";
|
in-ns = "${ip} netns exec ovpns";
|
||||||
iptables = "${pkgs.iptables}/bin/iptables";
|
iptables = "${pkgs.iptables}/bin/iptables";
|
||||||
@@ -163,9 +163,6 @@
|
|||||||
'';
|
'';
|
||||||
networking.iproute2.enable = true;
|
networking.iproute2.enable = true;
|
||||||
|
|
||||||
sops.secrets."wg_ovpns_privkey" = {
|
|
||||||
sopsFile = ../../secrets/servo.yaml;
|
|
||||||
};
|
|
||||||
|
|
||||||
# HURRICANE ELECTRIC CONFIG:
|
# HURRICANE ELECTRIC CONFIG:
|
||||||
# networking.sits = {
|
# networking.sits = {
|
41
hosts/by-name/servo/secrets.nix
Normal file
41
hosts/by-name/servo/secrets.nix
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
sops.secrets."ddns_afraid" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
sops.secrets."ddns_he" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."dovecot_passwd" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."duplicity_passphrase" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."freshrss_passwd" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."matrix_synapse_secrets" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
sops.secrets."mautrix_signal_env" = {
|
||||||
|
sopsFile = ../../../secrets/servo/mautrix_signal_env.bin;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."mediawiki_pw" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."pleroma_secrets" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."wg_ovpns_privkey" = {
|
||||||
|
sopsFile = ../../../secrets/servo.yaml;
|
||||||
|
};
|
||||||
|
}
|
@@ -24,8 +24,4 @@ lib.mkIf false
|
|||||||
OnUnitActiveSec = "10min";
|
OnUnitActiveSec = "10min";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets."ddns_afraid" = {
|
|
||||||
sopsFile = ../../../secrets/servo.yaml;
|
|
||||||
};
|
|
||||||
}
|
}
|
@@ -27,8 +27,4 @@ lib.mkIf false
|
|||||||
OnUnitActiveSec = "10min";
|
OnUnitActiveSec = "10min";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets."ddns_he" = {
|
|
||||||
sopsFile = ../../../secrets/servo.yaml;
|
|
||||||
};
|
|
||||||
}
|
}
|
@@ -46,6 +46,8 @@
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
# provide access to certs
|
# provide access to certs
|
||||||
|
# TODO: this should just be `acme`. then we also add nginx to the `acme` group.
|
||||||
|
# why is /var/lib/acme/* owned by `nginx` group??
|
||||||
users.users.ejabberd.extraGroups = [ "nginx" ];
|
users.users.ejabberd.extraGroups = [ "nginx" ];
|
||||||
|
|
||||||
security.acme.certs."uninsane.org".extraDomainNames = [
|
security.acme.certs."uninsane.org".extraDomainNames = [
|
@@ -11,8 +11,7 @@
|
|||||||
|
|
||||||
{ config, lib, pkgs, sane-lib, ... }:
|
{ config, lib, pkgs, sane-lib, ... }:
|
||||||
{
|
{
|
||||||
sops.secrets.freshrss_passwd = {
|
sops.secrets."freshrss_passwd" = {
|
||||||
sopsFile = ../../../secrets/servo.yaml;
|
|
||||||
owner = config.users.users.freshrss.name;
|
owner = config.users.users.freshrss.name;
|
||||||
mode = "0400";
|
mode = "0400";
|
||||||
};
|
};
|
||||||
@@ -42,7 +41,10 @@
|
|||||||
description = "import sane RSS feed list";
|
description = "import sane RSS feed list";
|
||||||
after = [ "freshrss-config.service" ];
|
after = [ "freshrss-config.service" ];
|
||||||
script = ''
|
script = ''
|
||||||
${pkgs.freshrss}/cli/import-for-user.php --user admin --filename ${opml}
|
# easiest way to preserve feeds: delete the user, recreate it, import feeds
|
||||||
|
${pkgs.freshrss}/cli/delete-user.php --user colin || true
|
||||||
|
${pkgs.freshrss}/cli/create-user.php --user colin --password "$(cat ${config.services.freshrss.passwordFile})" || true
|
||||||
|
${pkgs.freshrss}/cli/import-for-user.php --user colin --filename ${opml}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
@@ -15,6 +15,17 @@
|
|||||||
services.gitea.settings.session.COOKIE_SECURE = true;
|
services.gitea.settings.session.COOKIE_SECURE = true;
|
||||||
# services.gitea.disableRegistration = true;
|
# services.gitea.disableRegistration = true;
|
||||||
|
|
||||||
|
# gitea doesn't create the git user
|
||||||
|
users.users.git = {
|
||||||
|
description = "Gitea Service";
|
||||||
|
home = "/var/lib/gitea";
|
||||||
|
useDefaultShell = true;
|
||||||
|
group = "gitea";
|
||||||
|
isSystemUser = true;
|
||||||
|
# sendmail access (not 100% sure if this is necessary)
|
||||||
|
extraGroups = [ "postdrop" ];
|
||||||
|
};
|
||||||
|
|
||||||
services.gitea.settings = {
|
services.gitea.settings = {
|
||||||
server = {
|
server = {
|
||||||
# options: "home", "explore", "organizations", "login" or URL fragment (or full URL)
|
# options: "home", "explore", "organizations", "login" or URL fragment (or full URL)
|
@@ -7,8 +7,8 @@
|
|||||||
];
|
];
|
||||||
services.jackett.enable = true;
|
services.jackett.enable = true;
|
||||||
|
|
||||||
systemd.services.jackett.after = [ "wireguard-wg0.service" ];
|
systemd.services.jackett.after = [ "wireguard-wg-ovpns.service" ];
|
||||||
systemd.services.jackett.partOf = [ "wireguard-wg0.service" ];
|
systemd.services.jackett.partOf = [ "wireguard-wg-ovpns.service" ];
|
||||||
systemd.services.jackett.serviceConfig = {
|
systemd.services.jackett.serviceConfig = {
|
||||||
# run this behind the OVPN static VPN
|
# run this behind the OVPN static VPN
|
||||||
NetworkNamespacePath = "/run/netns/ovpns";
|
NetworkNamespacePath = "/run/netns/ovpns";
|
@@ -6,12 +6,18 @@
|
|||||||
imports = [
|
imports = [
|
||||||
./discord-puppet.nix
|
./discord-puppet.nix
|
||||||
# ./irc.nix
|
# ./irc.nix
|
||||||
|
./signal.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# allow synapse to read the registration files of its appservices
|
||||||
|
users.users.matrix-synapse.extraGroups = [ "mautrix-signal" ];
|
||||||
|
|
||||||
sane.persist.sys.plaintext = [
|
sane.persist.sys.plaintext = [
|
||||||
{ user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/matrix-synapse"; }
|
{ user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/matrix-synapse"; }
|
||||||
];
|
];
|
||||||
services.matrix-synapse.enable = true;
|
services.matrix-synapse.enable = true;
|
||||||
|
# this changes the default log level from INFO to WARN.
|
||||||
|
# maybe there's an easier way?
|
||||||
services.matrix-synapse.settings.log_config = ./synapse-log_level.yaml;
|
services.matrix-synapse.settings.log_config = ./synapse-log_level.yaml;
|
||||||
services.matrix-synapse.settings.server_name = "uninsane.org";
|
services.matrix-synapse.settings.server_name = "uninsane.org";
|
||||||
|
|
||||||
@@ -127,8 +133,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
sops.secrets.matrix_synapse_secrets = {
|
sops.secrets."matrix_synapse_secrets" = {
|
||||||
sopsFile = ../../../../secrets/servo.yaml;
|
|
||||||
owner = config.users.users.matrix-synapse.name;
|
owner = config.users.users.matrix-synapse.name;
|
||||||
};
|
};
|
||||||
}
|
}
|
@@ -43,6 +43,7 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# TODO: should use a dedicated user
|
||||||
systemd.services.mx-puppet-discord.serviceConfig = {
|
systemd.services.mx-puppet-discord.serviceConfig = {
|
||||||
# fix up to not use /var/lib/private, but just /var/lib
|
# fix up to not use /var/lib/private, but just /var/lib
|
||||||
DynamicUser = lib.mkForce false;
|
DynamicUser = lib.mkForce false;
|
35
hosts/by-name/servo/services/matrix/signal.nix
Normal file
35
hosts/by-name/servo/services/matrix/signal.nix
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# config options:
|
||||||
|
# - <https://github.com/mautrix/signal/blob/master/mautrix_signal/example-config.yaml>
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.persist.sys.plaintext = [
|
||||||
|
{ user = "mautrix-signal"; group = "mautrix-signal"; directory = "/var/lib/mautrix-signal"; }
|
||||||
|
{ user = "signald"; group = "signald"; directory = "/var/lib/signald"; }
|
||||||
|
];
|
||||||
|
|
||||||
|
services.signald.enable = true;
|
||||||
|
services.mautrix-signal.enable = true;
|
||||||
|
services.mautrix-signal.environmentFile =
|
||||||
|
config.sops.secrets.mautrix_signal_env.path;
|
||||||
|
|
||||||
|
services.mautrix-signal.settings.signal.socket_path = "/run/signald/signald.sock";
|
||||||
|
services.mautrix-signal.settings.homeserver.domain = "uninsane.org";
|
||||||
|
services.mautrix-signal.settings.bridge.permissions."@colin:uninsane.org" = "admin";
|
||||||
|
services.matrix-synapse.settings.app_service_config_files = [
|
||||||
|
# auto-created by mautrix-signal service
|
||||||
|
"/var/lib/mautrix-signal/signal-registration.yaml"
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd.services.mautrix-signal.serviceConfig = {
|
||||||
|
# allow communication to signald
|
||||||
|
SupplementaryGroups = [ "signald" ];
|
||||||
|
ReadWritePaths = [ "/run/signald" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets."mautrix_signal_env" = {
|
||||||
|
format = "binary";
|
||||||
|
mode = "0440";
|
||||||
|
owner = config.users.users.mautrix-signal.name;
|
||||||
|
group = config.users.users.matrix-synapse.name;
|
||||||
|
};
|
||||||
|
}
|
@@ -1,11 +1,8 @@
|
|||||||
{ ... }:
|
{ lib, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
sane.persist.sys.plaintext = [
|
sane.persist.sys.plaintext = [
|
||||||
# TODO: we don't have a static user allocated for navidrome!
|
{ user = "navidrome"; group = "navidrome"; directory = "/var/lib/navidrome"; }
|
||||||
# the chown would happen too early for us to set static perms
|
|
||||||
"/var/lib/private/navidrome"
|
|
||||||
# { user = "navidrome"; group = "navidrome"; directory = "/var/lib/private/navidrome"; }
|
|
||||||
];
|
];
|
||||||
services.navidrome.enable = true;
|
services.navidrome.enable = true;
|
||||||
services.navidrome.settings = {
|
services.navidrome.settings = {
|
||||||
@@ -18,6 +15,20 @@
|
|||||||
ScanSchedule = "@every 1h";
|
ScanSchedule = "@every 1h";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.services.navidrome.serviceConfig = {
|
||||||
|
# fix to use a normal user so we can configure perms correctly
|
||||||
|
DynamicUser = lib.mkForce false;
|
||||||
|
User = "navidrome";
|
||||||
|
Group = "navidrome";
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.navidrome = {};
|
||||||
|
|
||||||
|
users.users.navidrome = {
|
||||||
|
group = "navidrome";
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts."music.uninsane.org" = {
|
services.nginx.virtualHosts."music.uninsane.org" = {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
@@ -17,5 +17,5 @@
|
|||||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."nixcache" = "native";
|
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."nixcache" = "native";
|
||||||
|
|
||||||
sane.services.nixserve.enable = true;
|
sane.services.nixserve.enable = true;
|
||||||
sane.services.nixserve.sopsFile = ../../../secrets/servo.yaml;
|
sane.services.nixserve.sopsFile = ../../../../secrets/servo.yaml;
|
||||||
}
|
}
|
@@ -135,6 +135,11 @@
|
|||||||
# CapabilityBoundingSet = lib.mkForce "~";
|
# CapabilityBoundingSet = lib.mkForce "~";
|
||||||
# };
|
# };
|
||||||
|
|
||||||
|
# this is required to allow pleroma to send email.
|
||||||
|
# raw `sendmail` works, but i think pleroma's passing it some funny flags or something, idk.
|
||||||
|
# hack to fix that.
|
||||||
|
users.users.pleroma.extraGroups = [ "postdrop" ];
|
||||||
|
|
||||||
# Pleroma server and web interface
|
# Pleroma server and web interface
|
||||||
# TODO: enable publog?
|
# TODO: enable publog?
|
||||||
services.nginx.virtualHosts."fed.uninsane.org" = {
|
services.nginx.virtualHosts."fed.uninsane.org" = {
|
||||||
@@ -179,8 +184,7 @@
|
|||||||
|
|
||||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."fed" = "native";
|
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."fed" = "native";
|
||||||
|
|
||||||
sops.secrets.pleroma_secrets = {
|
sops.secrets."pleroma_secrets" = {
|
||||||
sopsFile = ../../../secrets/servo.yaml;
|
|
||||||
owner = config.users.users.pleroma.name;
|
owner = config.users.users.pleroma.name;
|
||||||
};
|
};
|
||||||
}
|
}
|
@@ -1,3 +1,6 @@
|
|||||||
|
# DOCS:
|
||||||
|
# - dovecot config: <https://doc.dovecot.org/configuration_manual/>
|
||||||
|
|
||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
@@ -110,8 +113,8 @@ in
|
|||||||
services.postfix.enableSubmissions = true;
|
services.postfix.enableSubmissions = true;
|
||||||
services.postfix.submissionsOptions = submissionOptions;
|
services.postfix.submissionsOptions = submissionOptions;
|
||||||
|
|
||||||
systemd.services.postfix.after = [ "wireguard-wg0.service" ];
|
systemd.services.postfix.after = [ "wireguard-wg-ovpns.service" ];
|
||||||
systemd.services.postfix.partOf = [ "wireguard-wg0.service" ];
|
systemd.services.postfix.partOf = [ "wireguard-wg-ovpns.service" ];
|
||||||
systemd.services.postfix.serviceConfig = {
|
systemd.services.postfix.serviceConfig = {
|
||||||
# run this behind the OVPN static VPN
|
# run this behind the OVPN static VPN
|
||||||
NetworkNamespacePath = "/run/netns/ovpns";
|
NetworkNamespacePath = "/run/netns/ovpns";
|
||||||
@@ -132,8 +135,8 @@ in
|
|||||||
# keeping this the same as the hostname seems simplest
|
# keeping this the same as the hostname seems simplest
|
||||||
services.opendkim.selector = "mx";
|
services.opendkim.selector = "mx";
|
||||||
|
|
||||||
systemd.services.opendkim.after = [ "wireguard-wg0.service" ];
|
systemd.services.opendkim.after = [ "wireguard-wg-ovpns.service" ];
|
||||||
systemd.services.opendkim.partOf = [ "wireguard-wg0.service" ];
|
systemd.services.opendkim.partOf = [ "wireguard-wg-ovpns.service" ];
|
||||||
systemd.services.opendkim.serviceConfig = {
|
systemd.services.opendkim.serviceConfig = {
|
||||||
# run this behind the OVPN static VPN
|
# run this behind the OVPN static VPN
|
||||||
NetworkNamespacePath = "/run/netns/ovpns";
|
NetworkNamespacePath = "/run/netns/ovpns";
|
||||||
@@ -143,6 +146,25 @@ in
|
|||||||
|
|
||||||
# inspired by https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/
|
# inspired by https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/
|
||||||
services.dovecot2.enable = true;
|
services.dovecot2.enable = true;
|
||||||
|
services.dovecot2.mailboxes = {
|
||||||
|
# special-purpose mailboxes: "All" "Archive" "Drafts" "Flagged" "Junk" "Sent" "Trash"
|
||||||
|
# RFC6154 describes these special mailboxes: https://www.ietf.org/rfc/rfc6154.html
|
||||||
|
# how these boxes are treated is 100% up to the client and server to decide.
|
||||||
|
# client behavior:
|
||||||
|
# iOS
|
||||||
|
# - Drafts: ?
|
||||||
|
# - Sent: works
|
||||||
|
# - Trash: works
|
||||||
|
# aerc
|
||||||
|
# - Drafts: works
|
||||||
|
# - Sent: works
|
||||||
|
# - Trash: no; deleted messages are actually deleted
|
||||||
|
# use `:move trash` instead
|
||||||
|
# Sent mailbox: all sent messages are copied to it. unclear if this happens server-side or client-side.
|
||||||
|
Drafts = { specialUse = "Drafts"; auto = "create"; };
|
||||||
|
Sent = { specialUse = "Sent"; auto = "create"; };
|
||||||
|
Trash = { specialUse = "Trash"; auto = "create"; };
|
||||||
|
};
|
||||||
services.dovecot2.sslServerCert = "/var/lib/acme/imap.uninsane.org/fullchain.pem";
|
services.dovecot2.sslServerCert = "/var/lib/acme/imap.uninsane.org/fullchain.pem";
|
||||||
services.dovecot2.sslServerKey = "/var/lib/acme/imap.uninsane.org/key.pem";
|
services.dovecot2.sslServerKey = "/var/lib/acme/imap.uninsane.org/key.pem";
|
||||||
services.dovecot2.enablePAM = false;
|
services.dovecot2.enablePAM = false;
|
||||||
@@ -197,8 +219,7 @@ in
|
|||||||
# }
|
# }
|
||||||
];
|
];
|
||||||
|
|
||||||
sops.secrets.dovecot_passwd = {
|
sops.secrets."dovecot_passwd" = {
|
||||||
sopsFile = ../../../secrets/servo.yaml;
|
|
||||||
owner = config.users.users.dovecot2.name;
|
owner = config.users.users.dovecot2.name;
|
||||||
# TODO: debug why mail can't be sent without this being world-readable
|
# TODO: debug why mail can't be sent without this being world-readable
|
||||||
mode = "0444";
|
mode = "0444";
|
@@ -40,8 +40,8 @@
|
|||||||
# transmission will by default not allow the world to read its files.
|
# transmission will by default not allow the world to read its files.
|
||||||
services.transmission.downloadDirPermissions = "775";
|
services.transmission.downloadDirPermissions = "775";
|
||||||
|
|
||||||
systemd.services.transmission.after = [ "wireguard-wg0.service" ];
|
systemd.services.transmission.after = [ "wireguard-wg-ovpns.service" ];
|
||||||
systemd.services.transmission.partOf = [ "wireguard-wg0.service" ];
|
systemd.services.transmission.partOf = [ "wireguard-wg-ovpns.service" ];
|
||||||
systemd.services.transmission.serviceConfig = {
|
systemd.services.transmission.serviceConfig = {
|
||||||
# run this behind the OVPN static VPN
|
# run this behind the OVPN static VPN
|
||||||
NetworkNamespacePath = "/run/netns/ovpns";
|
NetworkNamespacePath = "/run/netns/ovpns";
|
@@ -9,6 +9,7 @@
|
|||||||
"192.168.0.5"
|
"192.168.0.5"
|
||||||
"10.0.1.5"
|
"10.0.1.5"
|
||||||
];
|
];
|
||||||
|
sane.services.trust-dns.quiet = true;
|
||||||
|
|
||||||
sane.services.trust-dns.zones."uninsane.org".TTL = 900;
|
sane.services.trust-dns.zones."uninsane.org".TTL = 900;
|
||||||
|
|
@@ -8,7 +8,6 @@ lib.mkIf false
|
|||||||
{
|
{
|
||||||
sops.secrets."mediawiki_pw" = {
|
sops.secrets."mediawiki_pw" = {
|
||||||
owner = config.users.users.mediawiki.name;
|
owner = config.users.users.mediawiki.name;
|
||||||
sopsFile = ../../../secrets/servo.yaml;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.mediawiki.enable = true;
|
services.mediawiki.enable = true;
|
@@ -1,16 +0,0 @@
|
|||||||
{ lib, pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
# persist external pairings by default
|
|
||||||
sane.persist.sys.plaintext = [ "/var/lib/bluetooth" ];
|
|
||||||
|
|
||||||
sane.fs."/var/lib/bluetooth".generated.acl.mode = "0700";
|
|
||||||
sane.fs."/var/lib/bluetooth/.secrets.stamp" = {
|
|
||||||
wantedBeforeBy = [ "bluetooth.service" ];
|
|
||||||
# XXX: install-bluetooth uses sed, but that's part of the default systemd unit path, it seems
|
|
||||||
generated.script.script = builtins.readFile ../../scripts/install-bluetooth + ''
|
|
||||||
touch "/var/lib/bluetooth/.secrets.stamp"
|
|
||||||
'';
|
|
||||||
generated.script.scriptArgs = [ "/run/secrets/bt" ];
|
|
||||||
};
|
|
||||||
}
|
|
@@ -1,5 +1,12 @@
|
|||||||
{ ... }:
|
{ config, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
mkCrossFrom = localSystem: pkgs: import pkgs.path {
|
||||||
|
inherit localSystem;
|
||||||
|
crossSystem = pkgs.stdenv.hostPlatform.system;
|
||||||
|
inherit (config.nixpkgs) config overlays;
|
||||||
|
};
|
||||||
|
in
|
||||||
{
|
{
|
||||||
# the configuration of which specific package set `pkgs.cross` refers to happens elsewhere;
|
# the configuration of which specific package set `pkgs.cross` refers to happens elsewhere;
|
||||||
# here we just define them all.
|
# here we just define them all.
|
||||||
@@ -8,8 +15,8 @@
|
|||||||
# non-emulated packages build *from* local *for* target.
|
# non-emulated packages build *from* local *for* target.
|
||||||
# for large packages like the linux kernel which are expensive to build under emulation,
|
# for large packages like the linux kernel which are expensive to build under emulation,
|
||||||
# the config can explicitly pull such packages from `pkgs.cross` to do more efficient cross-compilation.
|
# the config can explicitly pull such packages from `pkgs.cross` to do more efficient cross-compilation.
|
||||||
crossFrom."x86_64-linux" = (prev.forceSystem "x86_64-linux" null).appendOverlays next.overlays;
|
crossFrom."x86_64-linux" = mkCrossFrom "x86_64-linux" next;
|
||||||
crossFrom."aarch64-linux" = (prev.forceSystem "aarch64-linux" null).appendOverlays next.overlays;
|
crossFrom."aarch64-linux" = mkCrossFrom "aarch64-linux" next;
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@@ -1,34 +1,29 @@
|
|||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./bluetooth.nix
|
|
||||||
./cross.nix
|
./cross.nix
|
||||||
./feeds.nix
|
./feeds.nix
|
||||||
./fs.nix
|
./fs.nix
|
||||||
./hardware
|
./hardware.nix
|
||||||
|
./home
|
||||||
./i2p.nix
|
./i2p.nix
|
||||||
./ids.nix
|
./ids.nix
|
||||||
./machine-id.nix
|
./machine-id.nix
|
||||||
./net.nix
|
./net.nix
|
||||||
|
./persist.nix
|
||||||
|
./programs.nix
|
||||||
./secrets.nix
|
./secrets.nix
|
||||||
./ssh.nix
|
./ssh.nix
|
||||||
./users.nix
|
./users.nix
|
||||||
./vpn.nix
|
./vpn.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
sane.home-manager.enable = true;
|
|
||||||
sane.nixcache.enable-trusted-keys = true;
|
sane.nixcache.enable-trusted-keys = true;
|
||||||
sane.packages.enableConsolePkgs = true;
|
sane.packages.enableConsolePkgs = true;
|
||||||
sane.packages.enableSystemPkgs = true;
|
sane.packages.enableSystemPkgs = true;
|
||||||
|
|
||||||
sane.persist.sys.plaintext = [
|
# some services which use private directories error if the parent (/var/lib/private) isn't 700.
|
||||||
"/var/log"
|
sane.fs."/var/lib/private".dir.acl.mode = "0700";
|
||||||
"/var/backup" # for e.g. postgres dumps
|
|
||||||
# TODO: move elsewhere
|
|
||||||
"/var/lib/alsa" # preserve output levels, default devices
|
|
||||||
"/var/lib/colord" # preserve color calibrations (?)
|
|
||||||
"/var/lib/machines" # maybe not needed, but would be painful to add a VM and forget.
|
|
||||||
];
|
|
||||||
|
|
||||||
nixpkgs.config.allowUnfree = true;
|
nixpkgs.config.allowUnfree = true;
|
||||||
|
|
||||||
@@ -39,8 +34,12 @@
|
|||||||
nix.extraOptions = ''
|
nix.extraOptions = ''
|
||||||
experimental-features = nix-command flakes
|
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"
|
||||||
|
];
|
||||||
|
|
||||||
# TODO: move this into home-manager?
|
|
||||||
fonts = {
|
fonts = {
|
||||||
enableDefaultFonts = true;
|
enableDefaultFonts = true;
|
||||||
fonts = with pkgs; [ font-awesome twitter-color-emoji hack-font ];
|
fonts = with pkgs; [ font-awesome twitter-color-emoji hack-font ];
|
||||||
@@ -68,8 +67,20 @@
|
|||||||
# NIXOS_OZONE_WL = "1";
|
# NIXOS_OZONE_WL = "1";
|
||||||
# LIBGL_ALWAYS_SOFTWARE = "1";
|
# LIBGL_ALWAYS_SOFTWARE = "1";
|
||||||
};
|
};
|
||||||
# enable zsh completions
|
|
||||||
environment.pathsToLink = [ "/share/zsh" ];
|
# 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;
|
||||||
|
programs.dconf.packages = [
|
||||||
|
(pkgs.writeTextFile {
|
||||||
|
name = "dconf-user-profile";
|
||||||
|
destination = "/etc/dconf/profile/user";
|
||||||
|
text = ''
|
||||||
|
user-db:user
|
||||||
|
system-db:site
|
||||||
|
'';
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
# link debug symbols into /run/current-system/sw/lib/debug
|
# link debug symbols into /run/current-system/sw/lib/debug
|
||||||
# hopefully picked up by gdb automatically?
|
# hopefully picked up by gdb automatically?
|
||||||
|
@@ -13,6 +13,7 @@ let
|
|||||||
uncat = { cat = "uncat"; };
|
uncat = { cat = "uncat"; };
|
||||||
|
|
||||||
text = { format = "text"; };
|
text = { format = "text"; };
|
||||||
|
img = { format = "image"; };
|
||||||
|
|
||||||
mkRss = format: url: { inherit url format; } // uncat // infrequent;
|
mkRss = format: url: { inherit url format; } // uncat // infrequent;
|
||||||
# format-specific helpers
|
# format-specific helpers
|
||||||
@@ -29,32 +30,35 @@ let
|
|||||||
in {
|
in {
|
||||||
url = raw.url;
|
url = raw.url;
|
||||||
# not sure the exact mapping with velocity here: entries per day?
|
# not sure the exact mapping with velocity here: entries per day?
|
||||||
freq = lib.mkDefault (
|
freq = lib.mkIf (raw.velocity or 0 != 0) (lib.mkDefault (
|
||||||
if raw.velocity or 0 > 2 then
|
if raw.velocity > 2 then
|
||||||
"hourly"
|
"hourly"
|
||||||
else if raw.velocity or 0 > 0.5 then
|
else if raw.velocity > 0.5 then
|
||||||
"daily"
|
"daily"
|
||||||
else if raw.velocity or 0 > 0.1 then
|
else if raw.velocity > 0.1 then
|
||||||
"weekly"
|
"weekly"
|
||||||
else
|
else
|
||||||
"infrequent"
|
"infrequent"
|
||||||
);
|
));
|
||||||
} // lib.optionalAttrs (raw.is_podcast or false) {
|
} // lib.optionalAttrs (raw.is_podcast or false) {
|
||||||
format = "podcast";
|
format = "podcast";
|
||||||
|
} // lib.optionalAttrs (raw.title or "" != "") {
|
||||||
|
title = lib.mkDefault raw.title;
|
||||||
};
|
};
|
||||||
|
|
||||||
podcasts = [
|
podcasts = [
|
||||||
(fromDb "lexfridman.com/podcast" // rat)
|
(fromDb "lexfridman.com/podcast" // rat)
|
||||||
# (mkPod "https://lexfridman.com/feed/podcast/" // rat // weekly)
|
|
||||||
## Astral Codex Ten
|
## Astral Codex Ten
|
||||||
(fromDb "sscpodcast.libsyn.com" // rat)
|
(fromDb "sscpodcast.libsyn.com" // rat)
|
||||||
## Econ Talk
|
## Econ Talk
|
||||||
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat)
|
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat)
|
||||||
## Cory Doctorow -- both podcast & text entries
|
## Cory Doctorow -- both podcast & text entries
|
||||||
(fromDb "craphound.com" // pol)
|
(fromDb "craphound.com" // pol)
|
||||||
(mkPod "https://congressionaldish.libsyn.com/rss" // pol // infrequent)
|
(fromDb "congressionaldish.libsyn.com" // pol)
|
||||||
## Civboot -- https://anchor.fm/civboot
|
## Civboot -- https://anchor.fm/civboot
|
||||||
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech)
|
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech)
|
||||||
|
## Emerge: making sense of what's next -- <https://www.whatisemerging.com/emergepodcast>
|
||||||
|
(mkPod "https://anchor.fm/s/21bc734/podcast/rss" // pol // infrequent)
|
||||||
(fromDb "feeds.feedburner.com/80000HoursPodcast" // rat)
|
(fromDb "feeds.feedburner.com/80000HoursPodcast" // rat)
|
||||||
(fromDb "allinchamathjason.libsyn.com" // pol)
|
(fromDb "allinchamathjason.libsyn.com" // pol)
|
||||||
(fromDb "acquired.libsyn.com" // tech)
|
(fromDb "acquired.libsyn.com" // tech)
|
||||||
@@ -83,93 +87,108 @@ let
|
|||||||
(fromDb "feed.podbean.com/matrixlive/feed.xml" // tech)
|
(fromDb "feed.podbean.com/matrixlive/feed.xml" // tech)
|
||||||
## Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232>
|
## Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232>
|
||||||
(fromDb "rss.art19.com/your-welcome" // pol)
|
(fromDb "rss.art19.com/your-welcome" // pol)
|
||||||
|
(fromDb "seattlenice.buzzsprout.com" // pol)
|
||||||
|
## Sci-Fi? has Peter Watts; author of No Moods, Ads or Cutesy Fucking Icons (rifters.com)
|
||||||
|
(fromDb "talesfromthebridge.buzzsprout.com" // tech)
|
||||||
];
|
];
|
||||||
|
|
||||||
texts = [
|
texts = [
|
||||||
# AGGREGATORS (> 1 post/day)
|
# AGGREGATORS (> 1 post/day)
|
||||||
|
(fromDb "lwn.net" // tech)
|
||||||
(fromDb "lesswrong.com" // rat)
|
(fromDb "lesswrong.com" // rat)
|
||||||
(fromDb "econlib.org" // pol)
|
(fromDb "econlib.org" // pol)
|
||||||
|
|
||||||
# AGGREGATORS (< 1 post/day)
|
# AGGREGATORS (< 1 post/day)
|
||||||
(mkText "https://palladiummag.com/feed" // uncat // weekly)
|
(fromDb "palladiummag.com" // uncat)
|
||||||
(mkText "https://profectusmag.com/feed" // uncat // weekly)
|
(fromDb "profectusmag.com" // uncat)
|
||||||
(mkText "https://semiaccurate.com/feed" // tech // weekly)
|
(fromDb "semiaccurate.com" // tech)
|
||||||
(mkText "https://linuxphoneapps.org/blog/atom.xml" // tech // infrequent)
|
(mkText "https://linuxphoneapps.org/blog/atom.xml" // tech // infrequent)
|
||||||
(mkText "https://spectrum.ieee.org/rss" // tech // weekly)
|
(fromDb "spectrum.ieee.org" // tech)
|
||||||
|
## n.b.: quality RSS list here: <https://forum.merveilles.town/thread/57/share-your-rss-feeds%21-6/>
|
||||||
|
(mkText "https://forum.merveilles.town/rss.xml" // pol // infrequent)
|
||||||
|
|
||||||
## No Moods, Ads or Cutesy Fucking Icons
|
## No Moods, Ads or Cutesy Fucking Icons
|
||||||
(mkText "https://www.rifters.com/crawl/?feed=rss2" // uncat // weekly)
|
(fromDb "rifters.com/crawl" // uncat)
|
||||||
|
|
||||||
# DEVELOPERS
|
# DEVELOPERS
|
||||||
(fromDb "uninsane.org" // tech)
|
(fromDb "uninsane.org" // tech)
|
||||||
(fromDb "mg.lol" // tech)
|
(fromDb "mg.lol" // tech)
|
||||||
|
(fromDb "drewdevault.com" // tech)
|
||||||
## Ken Shirriff
|
## Ken Shirriff
|
||||||
(fromDb "righto.com" // tech)
|
(fromDb "righto.com" // tech)
|
||||||
|
## shared blog by a few NixOS devs, notably onny
|
||||||
|
(fromDb "project-insanity.org" // tech)
|
||||||
## Vitalik Buterin
|
## Vitalik Buterin
|
||||||
(mkText "https://vitalik.ca/feed.xml" // tech // infrequent)
|
(fromDb "vitalik.ca" // tech)
|
||||||
## ian (Sanctuary)
|
## ian (Sanctuary)
|
||||||
(mkText "https://sagacioussuricata.com/feed.xml" // tech // infrequent)
|
(fromDb "sagacioussuricata.com" // tech)
|
||||||
## Bunnie Juang
|
## Bunnie Juang
|
||||||
(mkText "https://www.bunniestudios.com/blog/?feed=rss2" // tech // infrequent)
|
(fromDb "bunniestudios.com" // tech)
|
||||||
(mkText "https://blog.danieljanus.pl/atom.xml" // tech // infrequent)
|
(fromDb "blog.danieljanus.pl" // tech)
|
||||||
(mkText "https://ianthehenry.com/feed.xml" // tech // infrequent)
|
(fromDb "ianthehenry.com" // tech)
|
||||||
(mkText "https://bitbashing.io/feed.xml" // tech // infrequent)
|
(fromDb "bitbashing.io" // tech)
|
||||||
(mkText "https://idiomdrottning.org/feed.xml" // uncat // daily)
|
(fromDb "idiomdrottning.org" // uncat)
|
||||||
(mkText "https://anish.lakhwara.com/home.html" // tech // weekly)
|
(mkText "https://anish.lakhwara.com/home.html" // tech // weekly)
|
||||||
(mkText "https://www.jefftk.com/news.rss" // tech // daily)
|
(fromDb "jefftk.com" // tech)
|
||||||
(mkText "https://pomeroyb.com/feed.xml" // tech // infrequent)
|
(fromDb "pomeroyb.com" // tech)
|
||||||
|
|
||||||
# (TECH; POL) COMMENTATORS
|
# (TECH; POL) COMMENTATORS
|
||||||
|
## Matt Webb -- engineering-ish, but dreamy
|
||||||
|
(fromDb "interconnected.org/home/feed" // rat)
|
||||||
(fromDb "edwardsnowden.substack.com" // pol // text)
|
(fromDb "edwardsnowden.substack.com" // pol // text)
|
||||||
|
## Julia Evans
|
||||||
|
(mkText "https://jvns.ca/atom.xml" // tech // weekly)
|
||||||
(mkText "http://benjaminrosshoffman.com/feed" // pol // weekly)
|
(mkText "http://benjaminrosshoffman.com/feed" // pol // weekly)
|
||||||
## Ben Thompson
|
## Ben Thompson
|
||||||
(mkText "https://www.stratechery.com/rss" // pol // weekly)
|
(mkText "https://www.stratechery.com/rss" // pol // weekly)
|
||||||
## Balaji
|
## Balaji
|
||||||
(mkText "https://balajis.com/rss" // pol // weekly)
|
(fromDb "balajis.com" // pol)
|
||||||
(mkText "https://www.ben-evans.com/benedictevans/rss.xml" // pol // weekly)
|
(fromDb "ben-evans.com/benedictevans" // pol)
|
||||||
(mkText "https://www.lynalden.com/feed" // pol // infrequent)
|
(fromDb "lynalden.com" // pol)
|
||||||
(mkText "https://austinvernon.site/rss.xml" // tech // infrequent)
|
(fromDb "austinvernon.site" // tech)
|
||||||
(mkSubstack "oversharing" // pol // daily)
|
(mkSubstack "oversharing" // pol // daily)
|
||||||
(mkSubstack "doomberg" // tech // weekly)
|
(mkSubstack "doomberg" // tech // weekly)
|
||||||
## David Rosenthal
|
## David Rosenthal
|
||||||
(mkText "https://blog.dshr.org/rss.xml" // pol // weekly)
|
(fromDb "blog.dshr.org" // pol)
|
||||||
## Matt Levine
|
## Matt Levine
|
||||||
(mkText "https://www.bloomberg.com/opinion/authors/ARbTQlRLRjE/matthew-s-levine.rss" // pol // weekly)
|
(mkText "https://www.bloomberg.com/opinion/authors/ARbTQlRLRjE/matthew-s-levine.rss" // pol // weekly)
|
||||||
(mkText "https://stpeter.im/atom.xml" // pol // weekly)
|
(fromDb "stpeter.im/atom.xml" // pol)
|
||||||
|
## Peter Saint-Andre -- side project of stpeter.im
|
||||||
|
(fromDb "philosopher.coach" // rat)
|
||||||
|
|
||||||
# RATIONALITY/PHILOSOPHY/ETC
|
# RATIONALITY/PHILOSOPHY/ETC
|
||||||
(mkSubstack "samkriss" // humor // infrequent)
|
(mkSubstack "samkriss" // humor // infrequent)
|
||||||
(mkText "https://unintendedconsequenc.es/feed" // rat // infrequent)
|
(fromDb "unintendedconsequenc.es" // rat)
|
||||||
(mkText "https://applieddivinitystudies.com/atom.xml" // rat // weekly)
|
(fromDb "applieddivinitystudies.com" // rat)
|
||||||
(mkText "https://slimemoldtimemold.com/feed.xml" // rat // weekly)
|
(fromDb "slimemoldtimemold.com" // rat)
|
||||||
(mkText "https://www.richardcarrier.info/feed" // rat // weekly)
|
(fromDb "richardcarrier.info" // rat)
|
||||||
(mkText "https://www.gwern.net/feed.xml" // uncat // infrequent)
|
(fromDb "gwern.net" // rat)
|
||||||
## Jason Crawford
|
## Jason Crawford
|
||||||
(mkText "https://rootsofprogress.org/feed.xml" // rat // weekly)
|
(fromDb "rootsofprogress.org" // rat)
|
||||||
## Robin Hanson
|
## Robin Hanson
|
||||||
(mkText "https://www.overcomingbias.com/feed" // rat // daily)
|
(fromDb "overcomingbias.com" // rat)
|
||||||
## Scott Alexander
|
## Scott Alexander
|
||||||
(mkSubstack "astralcodexten" // rat // daily)
|
(mkSubstack "astralcodexten" // rat // daily)
|
||||||
## Paul Christiano
|
## Paul Christiano
|
||||||
(mkText "https://sideways-view.com/feed" // rat // infrequent)
|
(fromDb "sideways-view.com" // rat)
|
||||||
## Sean Carroll
|
## Sean Carroll
|
||||||
(mkText "https://www.preposterousuniverse.com/rss" // rat // infrequent)
|
(fromDb "preposterousuniverse.com" // rat)
|
||||||
|
|
||||||
## mostly dating topics. not advice, or humor, but looking through a social lens
|
## mostly dating topics. not advice, or humor, but looking through a social lens
|
||||||
(mkText "https://putanumonit.com/feed" // rat // infrequent)
|
(fromDb "putanumonit.com" // rat)
|
||||||
|
|
||||||
# CODE
|
# CODE
|
||||||
# (mkText "https://github.com/Kaiteki-Fedi/Kaiteki/commits/master.atom" // tech // infrequent)
|
# (mkText "https://github.com/Kaiteki-Fedi/Kaiteki/commits/master.atom" // tech // infrequent)
|
||||||
];
|
];
|
||||||
|
|
||||||
images = [
|
images = [
|
||||||
(mkImg "https://www.smbc-comics.com/comic/rss" // humor // daily)
|
(fromDb "smbc-comics.com" // img // humor)
|
||||||
(mkImg "https://xkcd.com/atom.xml" // humor // daily)
|
(fromDb "xkcd.com" // img // humor)
|
||||||
(mkImg "https://pbfcomics.com/feed" // humor // infrequent)
|
(fromDb "pbfcomics.com" // img // humor)
|
||||||
# (mkImg "http://dilbert.com/feed" // humor // daily)
|
# (mkImg "http://dilbert.com/feed" // humor // daily)
|
||||||
|
|
||||||
# ART
|
# ART
|
||||||
(mkImg "https://miniature-calendar.com/feed" // art // daily)
|
(fromDb "miniature-calendar.com" // img // art // daily)
|
||||||
];
|
];
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
11
hosts/common/home/aerc.nix
Normal file
11
hosts/common/home/aerc.nix
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Terminal UI mail client
|
||||||
|
{ config, sane-lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
sops.secrets."aerc_accounts" = {
|
||||||
|
owner = config.users.users.colin.name;
|
||||||
|
sopsFile = ../../../secrets/universal/aerc_accounts.conf;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
sane.user.fs.".config/aerc/accounts.conf" = sane-lib.fs.wantedSymlinkTo config.sops.secrets.aerc_accounts.path;
|
||||||
|
}
|
23
hosts/common/home/default.nix
Normal file
23
hosts/common/home/default.nix
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./aerc.nix
|
||||||
|
./firefox.nix
|
||||||
|
./gfeeds.nix
|
||||||
|
./git.nix
|
||||||
|
./gpodder.nix
|
||||||
|
./keyring.nix
|
||||||
|
./kitty.nix
|
||||||
|
./libreoffice.nix
|
||||||
|
./mime.nix
|
||||||
|
./mpv.nix
|
||||||
|
./neovim.nix
|
||||||
|
./newsflash.nix
|
||||||
|
./splatmoji.nix
|
||||||
|
./ssh.nix
|
||||||
|
./sublime-music.nix
|
||||||
|
./vlc.nix
|
||||||
|
./xdg-dirs.nix
|
||||||
|
./zsh
|
||||||
|
];
|
||||||
|
}
|
@@ -32,16 +32,6 @@ let
|
|||||||
defaultSettings = firefoxSettings;
|
defaultSettings = firefoxSettings;
|
||||||
# defaultSettings = librewolfSettings;
|
# defaultSettings = librewolfSettings;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
extraNativeMessagingHosts = [ pkgs.browserpass ];
|
|
||||||
# extraNativeMessagingHosts = [ pkgs.gopass-native-messaging-host ];
|
|
||||||
|
|
||||||
nixExtensions = let
|
|
||||||
addon = name: extid: hash: pkgs.fetchFirefoxAddon {
|
addon = name: extid: hash: pkgs.fetchFirefoxAddon {
|
||||||
inherit name hash;
|
inherit name hash;
|
||||||
url = "https://addons.mozilla.org/firefox/downloads/latest/${name}/latest.xpi";
|
url = "https://addons.mozilla.org/firefox/downloads/latest/${name}/latest.xpi";
|
||||||
@@ -53,20 +43,17 @@ let
|
|||||||
src = "${pkg}/share/mozilla/extensions/\\{ec8030f7-c20a-464f-9b0e-13a3a9e97384\\}/${pkg.extid}.xpi";
|
src = "${pkg}/share/mozilla/extensions/\\{ec8030f7-c20a-464f-9b0e-13a3a9e97384\\}/${pkg.extid}.xpi";
|
||||||
fixedExtid = pkg.extid;
|
fixedExtid = pkg.extid;
|
||||||
};
|
};
|
||||||
in [
|
|
||||||
# get names from:
|
package = pkgs.wrapFirefox cfg.browser.browser {
|
||||||
# - ~/ref/nix-community/nur-combined/repos/rycee/pkgs/firefox-addons/generated-firefox-addons.nix
|
# inherit the default librewolf.cfg
|
||||||
# `wget ...xpi`; `unar ...xpi`; `cat */manifest.json | jq '.browser_specific_settings.gecko.id'`
|
# it can be further customized via ~/.librewolf/librewolf.overrides.cfg
|
||||||
(addon "ublock-origin" "uBlock0@raymondhill.net" "sha256-a/ivUmY1P6teq9x0dt4CbgHt+3kBsEMMXlOfZ5Hx7cg=")
|
inherit (pkgs.librewolf-unwrapped) extraPrefsFiles;
|
||||||
(addon "sponsorblock" "sponsorBlocker@ajay.app" "sha256-d2K3ufvurWnYVzqLbyR//MgejybkY9exitAf9RdLNRo=")
|
inherit (cfg.browser) libName;
|
||||||
(addon "bypass-paywalls-clean" "{d133e097-46d9-4ecc-9903-fa6a722a6e0e}" "sha256-t6Q335Nq60mDILPmzem+DT5KflleAPVJL3bsaA+UL0g=")
|
|
||||||
(addon "sidebery" "{3c078156-979c-498b-8990-85f7987dd929}" "sha256-YONfK/rIjlsrTgRHIt3km07Q7KnpIW89Z9r92ZSCc6w=")
|
extraNativeMessagingHosts = [ pkgs.browserpass ];
|
||||||
(addon "ether-metamask" "webextension@metamask.io" "sha256-G+MwJDOcsaxYSUXjahHJmkWnjLeQ0Wven8DU/lGeMzA=")
|
# extraNativeMessagingHosts = [ pkgs.gopass-native-messaging-host ];
|
||||||
(addon "ublacklist" "@ublacklist" "sha256-vHe/7EYOzcKeAbTElmt0Rb4E2rX0f3JgXThJaUmaz+M=")
|
|
||||||
(addon "i2p-in-private-browsing" "i2ppb@eyedeekay.github.io" "sha256-dJcJ3jxeAeAkRvhODeIVrCflvX+S4E0wT/PyYzQBQWs=")
|
nixExtensions = concatMap (ext: optional ext.enable ext.package) (attrValues cfg.addons);
|
||||||
# (addon "browserpass-ce" "browserpass@maximbaz.com" "sha256-sXgUBbRvMnRpeIW1MTkmTcoqtW/8RDXAkxAq1evFkpc=")
|
|
||||||
(localAddon pkgs.browserpass-extension)
|
|
||||||
];
|
|
||||||
|
|
||||||
extraPolicies = {
|
extraPolicies = {
|
||||||
NoDefaultBookmarks = true;
|
NoDefaultBookmarks = true;
|
||||||
@@ -102,6 +89,17 @@ let
|
|||||||
# NewTabPage = true;
|
# NewTabPage = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
addonOpts = types.submodule {
|
||||||
|
options = {
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
};
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
@@ -119,9 +117,35 @@ in
|
|||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = "cryptClearOnBoot";
|
default = "cryptClearOnBoot";
|
||||||
};
|
};
|
||||||
|
sane.web-browser.addons = mkOption {
|
||||||
|
type = types.attrsOf addonOpts;
|
||||||
|
default = {
|
||||||
|
# get names from:
|
||||||
|
# - ~/ref/nix-community/nur-combined/repos/rycee/pkgs/firefox-addons/generated-firefox-addons.nix
|
||||||
|
# `wget ...xpi`; `unar ...xpi`; `cat */manifest.json | jq '.browser_specific_settings.gecko.id'`
|
||||||
|
# browserpass-ce.package = addon "browserpass-ce" "browserpass@maximbaz.com" "sha256-sXgUBbRvMnRpeIW1MTkmTcoqtW/8RDXAkxAq1evFkpc=";
|
||||||
|
browserpass-extension.package = localAddon pkgs.browserpass-extension;
|
||||||
|
bypass-paywalls-clean.package = addon "bypass-paywalls-clean" "{d133e097-46d9-4ecc-9903-fa6a722a6e0e}" "sha256-JOj5P7c2JTTReHCRZXm4BscaGr3i+9Y4Ey/y621x8PI=";
|
||||||
|
ether-metamask.package = addon "ether-metamask" "webextension@metamask.io" "sha256-G+MwJDOcsaxYSUXjahHJmkWnjLeQ0Wven8DU/lGeMzA=";
|
||||||
|
i2p-in-private-browsing.package = addon "i2p-in-private-browsing" "i2ppb@eyedeekay.github.io" "sha256-dJcJ3jxeAeAkRvhODeIVrCflvX+S4E0wT/PyYzQBQWs=";
|
||||||
|
sidebery.package = addon "sidebery" "{3c078156-979c-498b-8990-85f7987dd929}" "sha256-YONfK/rIjlsrTgRHIt3km07Q7KnpIW89Z9r92ZSCc6w=";
|
||||||
|
sponsorblock.package = addon "sponsorblock" "sponsorBlocker@ajay.app" "sha256-d2K3ufvurWnYVzqLbyR//MgejybkY9exitAf9RdLNRo=";
|
||||||
|
ublacklist.package = addon "ublacklist" "@ublacklist" "sha256-RqY5iHzbL2qizth7aguyOKWPyINXmrwOlf/OsfqAS48=";
|
||||||
|
ublock-origin.package = addon "ublock-origin" "uBlock0@raymondhill.net" "sha256-a/ivUmY1P6teq9x0dt4CbgHt+3kBsEMMXlOfZ5Hx7cg=";
|
||||||
|
|
||||||
|
browserpass-extension.enable = lib.mkDefault true;
|
||||||
|
bypass-paywalls-clean.enable = lib.mkDefault true;
|
||||||
|
ether-metamask.enable = lib.mkDefault true;
|
||||||
|
i2p-in-private-browsing.enable = lib.mkDefault config.services.i2p.enable;
|
||||||
|
sidebery.enable = lib.mkDefault true;
|
||||||
|
sponsorblock.enable = lib.mkDefault true;
|
||||||
|
ublacklist.enable = lib.mkDefault true;
|
||||||
|
ublock-origin.enable = lib.mkDefault true;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf config.sane.home-manager.enable {
|
config = {
|
||||||
|
|
||||||
# uBlock filter list configuration.
|
# uBlock filter list configuration.
|
||||||
# specifically, enable the GDPR cookie prompt blocker.
|
# specifically, enable the GDPR cookie prompt blocker.
|
||||||
@@ -131,7 +155,7 @@ in
|
|||||||
# the specific attribute path is found via scraping ublock code here:
|
# the specific attribute path is found via scraping ublock code here:
|
||||||
# - <https://github.com/gorhill/uBlock/blob/master/src/js/storage.js>
|
# - <https://github.com/gorhill/uBlock/blob/master/src/js/storage.js>
|
||||||
# - <https://github.com/gorhill/uBlock/blob/master/assets/assets.json>
|
# - <https://github.com/gorhill/uBlock/blob/master/assets/assets.json>
|
||||||
sane.fs."/home/colin/${cfg.browser.dotDir}/managed-storage/uBlock0@raymondhill.net.json" = sane-lib.fs.wantedText ''
|
sane.user.fs."${cfg.browser.dotDir}/managed-storage/uBlock0@raymondhill.net.json" = sane-lib.fs.wantedText ''
|
||||||
{
|
{
|
||||||
"name": "uBlock0@raymondhill.net",
|
"name": "uBlock0@raymondhill.net",
|
||||||
"description": "ignored",
|
"description": "ignored",
|
||||||
@@ -141,7 +165,7 @@ in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
sane.fs."/home/colin/${cfg.browser.dotDir}/${cfg.browser.libName}.overrides.cfg" = sane-lib.fs.wantedText ''
|
sane.user.fs."${cfg.browser.dotDir}/${cfg.browser.libName}.overrides.cfg" = sane-lib.fs.wantedText ''
|
||||||
// if we can't query the revocation status of a SSL cert because the issuer is offline,
|
// if we can't query the revocation status of a SSL cert because the issuer is offline,
|
||||||
// treat it as unrevoked.
|
// treat it as unrevoked.
|
||||||
// see: <https://librewolf.net/docs/faq/#im-getting-sec_error_ocsp_server_error-what-can-i-do>
|
// see: <https://librewolf.net/docs/faq/#im-getting-sec_error_ocsp_server_error-what-can-i-do>
|
||||||
@@ -149,13 +173,27 @@ in
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
sane.packages.extraGuiPkgs = [ package ];
|
sane.packages.extraGuiPkgs = [ package ];
|
||||||
# flood the cache to disk to avoid it taking up too much tmp
|
# flush the cache to disk to avoid it taking up too much tmp
|
||||||
sane.persist.home.byPath."${cfg.browser.cacheDir}" = lib.mkIf (cfg.persistCache != null) {
|
sane.user.persist.byPath."${cfg.browser.cacheDir}" = lib.mkIf (cfg.persistCache != null) {
|
||||||
store = cfg.persistCache;
|
store = cfg.persistCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.persist.home.byPath."${cfg.browser.dotDir}" = lib.mkIf (cfg.persistData != null) {
|
sane.user.persist.byPath."${cfg.browser.dotDir}/default" = lib.mkIf (cfg.persistData != null) {
|
||||||
store = cfg.persistData;
|
store = cfg.persistData;
|
||||||
};
|
};
|
||||||
|
sane.user.fs."${cfg.browser.dotDir}/default" = sane-lib.fs.wantedDir;
|
||||||
|
# instruct Firefox to put the profile in a predictable directory (so we can do things like persist just it).
|
||||||
|
# XXX: the directory *must* exist, even if empty; Firefox will not create the directory itself.
|
||||||
|
sane.user.fs."${cfg.browser.dotDir}/profiles.ini" = sane-lib.fs.wantedText ''
|
||||||
|
[Profile0]
|
||||||
|
Name=default
|
||||||
|
IsRelative=1
|
||||||
|
Path=default
|
||||||
|
Default=1
|
||||||
|
|
||||||
|
[General]
|
||||||
|
StartWithLastProfile=1
|
||||||
|
'';
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
@@ -6,7 +6,7 @@ let
|
|||||||
all-feeds = config.sane.feeds;
|
all-feeds = config.sane.feeds;
|
||||||
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
|
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
|
||||||
in {
|
in {
|
||||||
sane.fs."/home/colin/.config/org.gabmus.gfeeds.json" = sane-lib.fs.wantedText (
|
sane.user.fs.".config/org.gabmus.gfeeds.json" = sane-lib.fs.wantedText (
|
||||||
builtins.toJSON {
|
builtins.toJSON {
|
||||||
# feed format is a map from URL to a dict,
|
# feed format is a map from URL to a dict,
|
||||||
# with dict["tags"] a list of string tags.
|
# with dict["tags"] a list of string tags.
|
18
hosts/common/home/git.nix
Normal file
18
hosts/common/home/git.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{ lib, pkgs, sane-lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
mkCfg = lib.generators.toINI { };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.user.fs.".config/git/config" = sane-lib.fs.wantedText (mkCfg {
|
||||||
|
user.name = "Colin";
|
||||||
|
user.email = "colin@uninsane.org";
|
||||||
|
alias.co = "checkout";
|
||||||
|
# difftastic docs:
|
||||||
|
# - <https://difftastic.wilfred.me.uk/git.html>
|
||||||
|
diff.tool = "difftastic";
|
||||||
|
difftool.prompt = false;
|
||||||
|
"difftool \"difftastic\"".cmd = ''${pkgs.difftastic}/bin/difft "$LOCAL" "$REMOTE"'';
|
||||||
|
# now run `git difftool` to use difftastic git
|
||||||
|
});
|
||||||
|
}
|
@@ -6,7 +6,7 @@ let
|
|||||||
all-feeds = config.sane.feeds;
|
all-feeds = config.sane.feeds;
|
||||||
wanted-feeds = feeds.filterByFormat ["podcast"] all-feeds;
|
wanted-feeds = feeds.filterByFormat ["podcast"] all-feeds;
|
||||||
in {
|
in {
|
||||||
sane.fs."/home/colin/.config/gpodderFeeds.opml" = sane-lib.fs.wantedText (
|
sane.user.fs.".config/gpodderFeeds.opml" = sane-lib.fs.wantedText (
|
||||||
feeds.feedsToOpml wanted-feeds
|
feeds.feedsToOpml wanted-feeds
|
||||||
);
|
);
|
||||||
}
|
}
|
11
hosts/common/home/keyring.nix
Normal file
11
hosts/common/home/keyring.nix
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{ config, sane-lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
sane.user.persist.private = [ ".local/share/keyrings" ];
|
||||||
|
|
||||||
|
sane.user.fs."private/.local/share/keyrings/default" = {
|
||||||
|
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 ];
|
||||||
|
};
|
||||||
|
}
|
68
hosts/common/home/kitty.nix
Normal file
68
hosts/common/home/kitty.nix
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
{ pkgs, sane-lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
sane.user.fs.".config/kitty/kitty.conf" = sane-lib.fs.wantedText ''
|
||||||
|
# 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 ${pkgs.kitty-themes}/themes/PaperColor_dark.conf
|
||||||
|
'';
|
||||||
|
# THEME CHOICES:
|
||||||
|
# docs: https://github.com/kovidgoyal/kitty-themes
|
||||||
|
# theme = "1984 Light"; # dislike: awful, harsh blues/teals
|
||||||
|
# theme = "Adventure Time"; # dislike: harsh (dark)
|
||||||
|
# theme = "Atom One Light"; # GOOD: light theme. all color combos readable. not a huge fan of the blue.
|
||||||
|
# theme = "Belafonte Day"; # dislike: too low contrast for text colors
|
||||||
|
# theme = "Belafonte Night"; # better: dark theme that's easy on the eyes. all combos readable. low contrast.
|
||||||
|
# theme = "Catppuccin"; # dislike: a bit pale/low-contrast (dark)
|
||||||
|
# theme = "Desert"; # mediocre: colors are harsh
|
||||||
|
# theme = "Earthsong"; # BEST: dark theme. readable, good contrast. unique, but decent colors.
|
||||||
|
# theme = "Espresso Libre"; # better: dark theme. readable, but meh colors
|
||||||
|
# theme = "Forest Night"; # decent: very pastel. it's workable, but unconventional and muted/flat.
|
||||||
|
# theme = "Gruvbox Material Light Hard"; # mediocre light theme.
|
||||||
|
# theme = "kanagawabones"; # better: dark theme. colors are too background-y
|
||||||
|
# theme = "Kaolin Dark"; # dislike: too dark
|
||||||
|
# theme = "Kaolin Breeze"; # mediocre: not-too-harsh light theme, but some parts are poor contrast
|
||||||
|
# theme = "Later This Evening"; # mediocre: not-too-harsh dark theme, but cursor is poor contrast
|
||||||
|
# theme = "Material"; # decent: light theme, few colors.
|
||||||
|
# theme = "Mayukai"; # decent: not-too-harsh dark theme. the teal is a bit straining
|
||||||
|
# theme = "Nord"; # mediocre: pale background, low contrast
|
||||||
|
# theme = "One Half Light"; # better: not-too-harsh light theme. contrast could be better
|
||||||
|
# theme = "PaperColor Dark"; # BEST: dark theme, very readable still the colors are background-y
|
||||||
|
# theme = "Parasio Dark"; # dislike: too low contrast
|
||||||
|
# theme = "Pencil Light"; # better: not-too-harsh light theme. decent contrast.
|
||||||
|
# theme = "Pnevma"; # dislike: too low contrast
|
||||||
|
# theme = "Piatto Light"; # better: readable light theme. pleasing colors. powerline prompt is hard to read.
|
||||||
|
# theme = "Rosé Pine Dawn"; # GOOD: light theme. all color combinations are readable. it is very mild -- may need to manually tweak contrast. tasteful colors
|
||||||
|
# theme = "Rosé Pine Moon"; # GOOD: dark theme. tasteful colors. but background is a bit intense
|
||||||
|
# theme = "Sea Shells"; # mediocre. not all color combos are readable
|
||||||
|
# theme = "Solarized Light"; # mediocre: not-too-harsh light theme; GREAT background; but some colors are low contrast
|
||||||
|
# theme = "Solarized Dark Higher Contrast"; # better: dark theme, decent colors
|
||||||
|
# theme = "Sourcerer"; # mediocre: ugly colors
|
||||||
|
# theme = "Space Gray"; # mediocre: too muted
|
||||||
|
# theme = "Space Gray Eighties"; # better: all readable, decent colors
|
||||||
|
# theme = "Spacemacs"; # mediocre: too muted
|
||||||
|
# theme = "Spring"; # mediocre: readable light theme, but the teal is ugly.
|
||||||
|
# theme = "Srcery"; # better: highly readable. colors are ehhh
|
||||||
|
# theme = "Substrata"; # decent: nice colors, but a bit flat.
|
||||||
|
# theme = "Sundried"; # mediocre: the solar text makes me squint
|
||||||
|
# theme = "Symfonic"; # mediocre: the dark purple has low contrast to the black bg.
|
||||||
|
# theme = "Tango Light"; # dislike: teal is too grating
|
||||||
|
# theme = "Tokyo Night Day"; # medicore: too muted
|
||||||
|
# theme = "Tokyo Night"; # better: tasteful. a bit flat
|
||||||
|
# theme = "Tomorrow"; # GOOD: all color combinations are readable. contrast is slightly better than Rose. on the blander side
|
||||||
|
# theme = "Treehouse"; # dislike: the orange is harsh on my eyes.
|
||||||
|
# theme = "Urple"; # dislike: weird palette
|
||||||
|
# theme = "Warm Neon"; # decent: not-too-harsh dark theme. the green is a bit unattractive
|
||||||
|
# theme = "Wild Cherry"; # GOOD: dark theme: nice colors. a bit flat
|
||||||
|
# theme = "Xcodedark"; # dislike: bad palette
|
||||||
|
# theme = "citylights"; # decent: dark theme. some parts have just a bit low contrast
|
||||||
|
# theme = "neobones_light"; # better light theme. the background is maybe too muted
|
||||||
|
# theme = "vimbones";
|
||||||
|
# theme = "zenbones_dark"; # mediocre: readable, but meh colors
|
||||||
|
# theme = "zenbones_light"; # decent: light theme. all colors are readable. contrast is passable but not excellent. highlight color is BAD
|
||||||
|
# theme = "zenwritten_dark"; # mediocre: looks same as zenbones_dark
|
||||||
|
}
|
14
hosts/common/home/libreoffice.nix
Normal file
14
hosts/common/home/libreoffice.nix
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{ sane-lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# libreoffice: disable first-run stuff
|
||||||
|
sane.user.fs.".config/libreoffice/4/user/registrymodifications.xcu" = sane-lib.fs.wantedText ''
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<oor:items xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<item oor:path="/org.openoffice.Office.Common/Misc"><prop oor:name="FirstRun" oor:op="fuse"><value>false</value></prop></item>
|
||||||
|
<item oor:path="/org.openoffice.Office.Common/Misc"><prop oor:name="ShowTipOfTheDay" oor:op="fuse"><value>false</value></prop></item>
|
||||||
|
</oor:items>
|
||||||
|
'';
|
||||||
|
# <item oor:path="/org.openoffice.Setup/Product"><prop oor:name="LastTimeDonateShown" oor:op="fuse"><value>1667693880</value></prop></item>
|
||||||
|
# <item oor:path="/org.openoffice.Setup/Product"><prop oor:name="LastTimeGetInvolvedShown" oor:op="fuse"><value>1667693880</value></prop></item>
|
||||||
|
}
|
42
hosts/common/home/mime.nix
Normal file
42
hosts/common/home/mime.nix
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{ config, sane-lib, ...}:
|
||||||
|
|
||||||
|
let
|
||||||
|
www = config.sane.web-browser.browser.desktop;
|
||||||
|
pdf = "org.gnome.Evince.desktop";
|
||||||
|
md = "obsidian.desktop";
|
||||||
|
thumb = "org.gnome.gThumb.desktop";
|
||||||
|
video = "vlc.desktop";
|
||||||
|
# audio = "mpv.desktop";
|
||||||
|
audio = "vlc.desktop";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
# the xdg mime type for a file can be found with:
|
||||||
|
# - `xdg-mime query filetype path/to/thing.ext`
|
||||||
|
# we can have single associations or a list of associations.
|
||||||
|
# there's also options to *remove* [non-default] associations from specific apps
|
||||||
|
xdg.mime.enable = true;
|
||||||
|
xdg.mime.defaultApplications = {
|
||||||
|
# AUDIO
|
||||||
|
"audio/flac" = audio;
|
||||||
|
"audio/mpeg" = audio;
|
||||||
|
"audio/x-vorbis+ogg" = audio;
|
||||||
|
# IMAGES
|
||||||
|
"image/heif" = thumb; # apple codec
|
||||||
|
"image/png" = thumb;
|
||||||
|
"image/jpeg" = thumb;
|
||||||
|
# VIDEO
|
||||||
|
"video/mp4" = video;
|
||||||
|
"video/quicktime" = video;
|
||||||
|
"video/x-matroska" = video;
|
||||||
|
# HTML
|
||||||
|
"text/html" = www;
|
||||||
|
"x-scheme-handler/http" = www;
|
||||||
|
"x-scheme-handler/https" = www;
|
||||||
|
"x-scheme-handler/about" = www;
|
||||||
|
"x-scheme-handler/unknown" = www;
|
||||||
|
# RICH-TEXT DOCUMENTS
|
||||||
|
"application/pdf" = pdf;
|
||||||
|
"text/markdown" = md;
|
||||||
|
};
|
||||||
|
}
|
10
hosts/common/home/mpv.nix
Normal file
10
hosts/common/home/mpv.nix
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{ sane-lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# format is <key>=%<length>%<value>
|
||||||
|
sane.user.fs.".config/mpv/mpv.conf" = sane-lib.fs.wantedText ''
|
||||||
|
save-position-on-quit=%3%yes
|
||||||
|
keep-open=%3%yes
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
|
129
hosts/common/home/neovim.nix
Normal file
129
hosts/common/home/neovim.nix
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
{ lib, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (builtins) map;
|
||||||
|
inherit (lib) concatMapStrings 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
|
||||||
|
'';
|
||||||
|
})
|
||||||
|
({
|
||||||
|
# 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
|
||||||
|
# this is required for tree-sitter to even highlight
|
||||||
|
plugin = nvim-treesitter.withAllGrammars;
|
||||||
|
type = "lua";
|
||||||
|
config = ''
|
||||||
|
require'nvim-treesitter.configs'.setup {
|
||||||
|
highlight = {
|
||||||
|
enable = true,
|
||||||
|
-- disable treesitter on Rust so that we can use SyntaxRange
|
||||||
|
-- and leverage TeX rendering in rust projects
|
||||||
|
disable = { "rust", "tex", "latex" },
|
||||||
|
-- disable = { "tex", "latex" },
|
||||||
|
-- true to also use builtin vim syntax highlighting when treesitter fails
|
||||||
|
additional_vim_regex_highlighting = false
|
||||||
|
},
|
||||||
|
incremental_selection = {
|
||||||
|
enable = true,
|
||||||
|
keymaps = {
|
||||||
|
init_selection = "gnn",
|
||||||
|
node_incremental = "grn",
|
||||||
|
mcope_incremental = "grc",
|
||||||
|
node_decremental = "grm"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
indent = {
|
||||||
|
enable = true,
|
||||||
|
disable = {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vim.o.foldmethod = 'expr'
|
||||||
|
vim.o.foldexpr = 'nvim_treesitter#foldexpr()'
|
||||||
|
'';
|
||||||
|
})
|
||||||
|
];
|
||||||
|
plugin-packages = map (p: p.plugin) plugins;
|
||||||
|
plugin-config-tex = concatMapStrings (p: optionalString (p.type or "" == "viml") p.config) plugins;
|
||||||
|
plugin-config-lua = concatMapStrings (p: optionalString (p.type or "" == "lua") p.config) plugins;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# private because there could be sensitive things in the swap
|
||||||
|
sane.user.persist.private = [ ".cache/vim-swap" ];
|
||||||
|
|
||||||
|
programs.neovim = {
|
||||||
|
# neovim: https://github.com/neovim/neovim
|
||||||
|
enable = true;
|
||||||
|
viAlias = true;
|
||||||
|
vimAlias = true;
|
||||||
|
configure = {
|
||||||
|
packages.myVimPackage = {
|
||||||
|
start = plugin-packages;
|
||||||
|
};
|
||||||
|
customRC = ''
|
||||||
|
" let the terminal handle mouse events, that way i get OS-level ctrl+shift+c/etc
|
||||||
|
" this used to be default, until <https://github.com/neovim/neovim/pull/19290>
|
||||||
|
set mouse=
|
||||||
|
|
||||||
|
" copy/paste to system clipboard
|
||||||
|
set clipboard=unnamedplus
|
||||||
|
|
||||||
|
" screw tabs; always expand them into spaces
|
||||||
|
set expandtab
|
||||||
|
|
||||||
|
" at least don't open files with sections folded by default
|
||||||
|
set nofoldenable
|
||||||
|
|
||||||
|
" allow text substitutions for certain glyphs.
|
||||||
|
" higher number = more aggressive substitution (0, 1, 2, 3)
|
||||||
|
" i only make use of this for tex, but it's unclear how to
|
||||||
|
" apply that *just* to tex and retain the SyntaxRange stuff.
|
||||||
|
set conceallevel=2
|
||||||
|
|
||||||
|
" horizontal rule under the active line
|
||||||
|
" set cursorline
|
||||||
|
|
||||||
|
" highlight trailing space & related syntax errors (doesn't seem to work??)
|
||||||
|
" let c_space_errors=1
|
||||||
|
" let python_space_errors=1
|
||||||
|
|
||||||
|
" enable highlighting of leading/trailing spaces,
|
||||||
|
" and especially tabs
|
||||||
|
" source: https://www.reddit.com/r/neovim/comments/chlmfk/highlight_trailing_whitespaces_in_neovim/
|
||||||
|
set list
|
||||||
|
set listchars=tab:▷\·,trail:·,extends:◣,precedes:◢,nbsp:○
|
||||||
|
|
||||||
|
""""" PLUGIN CONFIG (tex)
|
||||||
|
${plugin-config-tex}
|
||||||
|
|
||||||
|
""""" PLUGIN CONFIG (lua)
|
||||||
|
lua <<EOF
|
||||||
|
${plugin-config-lua}
|
||||||
|
EOF
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@@ -6,7 +6,7 @@ let
|
|||||||
all-feeds = config.sane.feeds;
|
all-feeds = config.sane.feeds;
|
||||||
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
|
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
|
||||||
in {
|
in {
|
||||||
sane.fs."/home/colin/.config/newsflashFeeds.opml" = sane-lib.fs.wantedText (
|
sane.user.fs.".config/newsflashFeeds.opml" = sane-lib.fs.wantedText (
|
||||||
feeds.feedsToOpml wanted-feeds
|
feeds.feedsToOpml wanted-feeds
|
||||||
);
|
);
|
||||||
}
|
}
|
@@ -4,9 +4,9 @@
|
|||||||
{ pkgs, sane-lib, ... }:
|
{ pkgs, sane-lib, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
sane.persist.home.plaintext = [ ".local/state/splatmoji" ];
|
sane.user.persist.plaintext = [ ".local/state/splatmoji" ];
|
||||||
sane.fs."/home/colin/.config/splatmoji/splatmoji.config" = sane-lib.fs.wantedText ''
|
sane.user.fs.".config/splatmoji/splatmoji.config" = sane-lib.fs.wantedText ''
|
||||||
history_file=/home/colin/.local/state/splatmoji/history
|
history_file=~/.local/state/splatmoji/history
|
||||||
history_length=5
|
history_length=5
|
||||||
# TODO: wayland equiv
|
# TODO: wayland equiv
|
||||||
paste_command=xdotool key ctrl+v
|
paste_command=xdotool key ctrl+v
|
@@ -1,4 +1,4 @@
|
|||||||
{ config, lib, pkgs, sane-lib, ... }:
|
{ config, lib, sane-lib, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
@@ -9,11 +9,12 @@ let
|
|||||||
"\n"
|
"\n"
|
||||||
(map (k: k.asHostKey) host-keys)
|
(map (k: k.asHostKey) host-keys)
|
||||||
;
|
;
|
||||||
in lib.mkIf config.sane.home-manager.enable {
|
in
|
||||||
|
{
|
||||||
# ssh key is stored in private storage
|
# ssh key is stored in private storage
|
||||||
sane.persist.home.private = [ ".ssh/id_ed25519" ];
|
sane.user.persist.private = [ ".ssh/id_ed25519" ];
|
||||||
sane.fs."/home/colin/.ssh/id_ed25519.pub" = sane-lib.fs.wantedText user-pubkey;
|
sane.user.fs.".ssh/id_ed25519.pub" = sane-lib.fs.wantedText user-pubkey;
|
||||||
sane.fs."/home/colin/.ssh/known_hosts" = sane-lib.fs.wantedText known-hosts-text;
|
sane.user.fs.".ssh/known_hosts" = sane-lib.fs.wantedText known-hosts-text;
|
||||||
|
|
||||||
users.users.colin.openssh.authorizedKeys.keys =
|
users.users.colin.openssh.authorizedKeys.keys =
|
||||||
let
|
let
|
11
hosts/common/home/sublime-music.nix
Normal file
11
hosts/common/home/sublime-music.nix
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{ config, sane-lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# TODO: this should only be shipped on gui platforms
|
||||||
|
sops.secrets."sublime_music_config" = {
|
||||||
|
owner = config.users.users.colin.name;
|
||||||
|
sopsFile = ../../../secrets/universal/sublime_music_config.json.bin;
|
||||||
|
format = "binary";
|
||||||
|
};
|
||||||
|
sane.user.fs.".config/sublime-music/config.json" = sane-lib.fs.wantedSymlinkTo config.sops.secrets.sublime_music_config.path;
|
||||||
|
}
|
@@ -8,9 +8,8 @@ let
|
|||||||
builtins.map (feed: feed.url) wanted-feeds
|
builtins.map (feed: feed.url) wanted-feeds
|
||||||
);
|
);
|
||||||
in
|
in
|
||||||
lib.mkIf config.sane.home-manager.enable
|
|
||||||
{
|
{
|
||||||
sane.fs."/home/colin/.config/vlc/vlcrc" = sane-lib.fs.wantedText ''
|
sane.user.fs.".config/vlc/vlcrc" = sane-lib.fs.wantedText ''
|
||||||
[podcast]
|
[podcast]
|
||||||
podcast-urls=${podcast-urls}
|
podcast-urls=${podcast-urls}
|
||||||
[core]
|
[core]
|
20
hosts/common/home/xdg-dirs.nix
Normal file
20
hosts/common/home/xdg-dirs.nix
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{ lib, sane-lib, ...}:
|
||||||
|
|
||||||
|
{
|
||||||
|
# XDG defines things like ~/Desktop, ~/Downloads, etc.
|
||||||
|
# these clutter the home, so i mostly don't use them.
|
||||||
|
sane.user.fs.".config/user-dirs.dirs" = sane-lib.fs.wantedText ''
|
||||||
|
XDG_DESKTOP_DIR="$HOME/.xdg/Desktop"
|
||||||
|
XDG_DOCUMENTS_DIR="$HOME/dev"
|
||||||
|
XDG_DOWNLOAD_DIR="$HOME/tmp"
|
||||||
|
XDG_MUSIC_DIR="$HOME/Music"
|
||||||
|
XDG_PICTURES_DIR="$HOME/Pictures"
|
||||||
|
XDG_PUBLICSHARE_DIR="$HOME/.xdg/Public"
|
||||||
|
XDG_TEMPLATES_DIR="$HOME/.xdg/Templates"
|
||||||
|
XDG_VIDEOS_DIR="$HOME/Videos"
|
||||||
|
'';
|
||||||
|
|
||||||
|
# prevent `xdg-user-dirs-update` from overriding/updating our config
|
||||||
|
# see <https://manpages.ubuntu.com/manpages/bionic/man5/user-dirs.conf.5.html>
|
||||||
|
sane.user.fs.".config/user-dirs.conf" = sane-lib.fs.wantedText "enabled=False";
|
||||||
|
}
|
143
hosts/common/home/zsh/default.nix
Normal file
143
hosts/common/home/zsh/default.nix
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
{ pkgs, sane-lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
# powerlevel10k prompt config
|
||||||
|
# p10k.zsh is the auto-generated config, and i overwrite those defaults here, below.
|
||||||
|
p10k-overrides = ''
|
||||||
|
# powerlevel10k launches a gitstatusd daemon to accelerate git prompt queries.
|
||||||
|
# this keeps open file handles for any git repo i touch for 60 minutes (by default).
|
||||||
|
# that prevents unmounting whatever device the git repo is on -- particularly problematic for ~/private.
|
||||||
|
# i can disable gitstatusd and get slower fallback git queries:
|
||||||
|
# - either universally
|
||||||
|
# - or selectively by path
|
||||||
|
# see: <https://github.com/romkatv/powerlevel10k/issues/246>
|
||||||
|
typeset -g POWERLEVEL9K_VCS_DISABLED_DIR_PATTERN='(/home/colin/private/*|/home/colin/knowledge/*)'
|
||||||
|
# typeset -g POWERLEVEL9K_DISABLE_GITSTATUS=true
|
||||||
|
|
||||||
|
# show user@host also when logged into the current machine.
|
||||||
|
# default behavior is to show it only over ssh.
|
||||||
|
typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_CONTENT_EXPANSION='$P9K_CONTENT'
|
||||||
|
'';
|
||||||
|
|
||||||
|
prezto-init = ''
|
||||||
|
source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh
|
||||||
|
source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
|
||||||
|
source ${pkgs.zsh-prezto}/share/zsh-prezto/init.zsh
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sane.user.persist.plaintext = [
|
||||||
|
# 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?
|
||||||
|
".local/share/zsh"
|
||||||
|
# cache gitstatus otherwise p10k fetched it from the net EVERY BOOT
|
||||||
|
".cache/gitstatus"
|
||||||
|
];
|
||||||
|
|
||||||
|
# zsh/prezto complains if zshrc doesn't exist; but it does allow an "empty" file.
|
||||||
|
sane.user.fs.".config/zsh/.zshrc" = sane-lib.fs.wantedText "# ";
|
||||||
|
|
||||||
|
# enable zsh completions
|
||||||
|
environment.pathsToLink = [ "/share/zsh" ];
|
||||||
|
|
||||||
|
programs.zsh = {
|
||||||
|
enable = true;
|
||||||
|
histFile = "$HOME/.local/share/zsh/history";
|
||||||
|
shellAliases = {
|
||||||
|
":q" = "exit";
|
||||||
|
# common typos
|
||||||
|
"cd.." = "cd ..";
|
||||||
|
"cd../" = "cd ../";
|
||||||
|
};
|
||||||
|
setOptions = [
|
||||||
|
# defaults:
|
||||||
|
"HIST_IGNORE_DUPS"
|
||||||
|
"SHARE_HISTORY"
|
||||||
|
"HIST_FCNTL_LOCK"
|
||||||
|
# disable `rm *` confirmations
|
||||||
|
"rmstarsilent"
|
||||||
|
];
|
||||||
|
|
||||||
|
# .zshenv config:
|
||||||
|
shellInit = ''
|
||||||
|
ZDOTDIR=$HOME/.config/zsh
|
||||||
|
'';
|
||||||
|
|
||||||
|
# .zshrc config:
|
||||||
|
interactiveShellInit =
|
||||||
|
(builtins.readFile ./p10k.zsh)
|
||||||
|
+ p10k-overrides
|
||||||
|
+ prezto-init
|
||||||
|
+ ''
|
||||||
|
# zmv is a way to do rich moves/renames, with pattern matching/substitution.
|
||||||
|
# see for an example: <https://filipe.kiss.ink/zmv-zsh-rename/>
|
||||||
|
autoload -Uz zmv
|
||||||
|
|
||||||
|
HISTORY_IGNORE='(sane-shutdown *|sane-reboot *|rm *)'
|
||||||
|
|
||||||
|
# extra aliases
|
||||||
|
# TODO: move to `shellAliases` config?
|
||||||
|
function nd() {
|
||||||
|
mkdir -p "$1";
|
||||||
|
pushd "$1";
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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;
|
||||||
|
vteIntegration = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
sane.user.fs.".config/zsh/.zpreztorc" = sane-lib.fs.wantedText ''
|
||||||
|
zstyle ':prezto:*:*' color 'yes'
|
||||||
|
|
||||||
|
# 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
|
||||||
|
# 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' \
|
||||||
|
'prompt'
|
||||||
|
|
||||||
|
# default keymap. try also `vicmd` (vim normal mode, AKA "cmd mode") or `vi`.
|
||||||
|
zstyle ':prezto:module:editor' key-bindings 'emacs'
|
||||||
|
|
||||||
|
zstyle ':prezto:module:prompt' theme 'powerlevel10k'
|
||||||
|
|
||||||
|
# disable `mv` confirmation (and `rm`, too, unfortunately)
|
||||||
|
zstyle ':prezto:module:utility' safe-ops 'no'
|
||||||
|
'';
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
services.i2p.enable = true;
|
# services.i2p.enable = true;
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,12 @@
|
|||||||
sane.ids.freshrss.uid = 2401;
|
sane.ids.freshrss.uid = 2401;
|
||||||
sane.ids.freshrss.gid = 2401;
|
sane.ids.freshrss.gid = 2401;
|
||||||
sane.ids.mediawiki.uid = 2402;
|
sane.ids.mediawiki.uid = 2402;
|
||||||
|
sane.ids.signald.uid = 2403;
|
||||||
|
sane.ids.signald.gid = 2403;
|
||||||
|
sane.ids.mautrix-signal.uid = 2404;
|
||||||
|
sane.ids.mautrix-signal.gid = 2404;
|
||||||
|
sane.ids.navidrome.uid = 2405;
|
||||||
|
sane.ids.navidrome.gid = 2405;
|
||||||
|
|
||||||
sane.ids.colin.uid = 1000;
|
sane.ids.colin.uid = 1000;
|
||||||
sane.ids.guest.uid = 1100;
|
sane.ids.guest.uid = 1100;
|
||||||
|
@@ -1,16 +1,6 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
# if using router's DNS, these mappings will already exist.
|
|
||||||
# if using a different DNS provider (which servo does), then we need to explicity provide them.
|
|
||||||
# ugly hack. would be better to get servo to somehow use the router's DNS
|
|
||||||
networking.hosts = {
|
|
||||||
"192.168.0.5" = [ "servo" ];
|
|
||||||
"192.168.0.20" = [ "lappy" ];
|
|
||||||
"192.168.0.22" = [ "desko" ];
|
|
||||||
"192.168.0.48" = [ "moby" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
# the default backend is "wpa_supplicant".
|
# the default backend is "wpa_supplicant".
|
||||||
# wpa_supplicant reliably picks weak APs to connect to.
|
# wpa_supplicant reliably picks weak APs to connect to.
|
||||||
# see: <https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/474>
|
# see: <https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/474>
|
||||||
@@ -30,14 +20,4 @@
|
|||||||
General.RoamThreshold = "-52"; # default -70
|
General.RoamThreshold = "-52"; # default -70
|
||||||
General.RoamThreshold5G = "-52"; # default -76
|
General.RoamThreshold5G = "-52"; # default -76
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.fs."/var/lib/iwd/.secrets.psk.stamp" = {
|
|
||||||
wantedBeforeBy = [ "iwd.service" ];
|
|
||||||
generated.acl.mode = "0600";
|
|
||||||
# XXX: install-iwd uses sed, but that's part of the default systemd unit path, it seems
|
|
||||||
generated.script.script = builtins.readFile ../../scripts/install-iwd + ''
|
|
||||||
touch "/var/lib/iwd/.secrets.psk.stamp"
|
|
||||||
'';
|
|
||||||
generated.script.scriptArgs = [ "/run/secrets/iwd" "/var/lib/iwd" ];
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
16
hosts/common/persist.nix
Normal file
16
hosts/common/persist.nix
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
sane.persist.stores.private.origin = "/home/colin/private";
|
||||||
|
# store /home/colin/a/b in /home/private/a/b instead of /home/private/home/colin/a/b
|
||||||
|
sane.persist.stores.private.prefix = "/home/colin";
|
||||||
|
|
||||||
|
sane.persist.sys.plaintext = [
|
||||||
|
"/var/log"
|
||||||
|
"/var/backup" # for e.g. postgres dumps
|
||||||
|
# TODO: move elsewhere
|
||||||
|
"/var/lib/alsa" # preserve output levels, default devices
|
||||||
|
"/var/lib/colord" # preserve color calibrations (?)
|
||||||
|
"/var/lib/machines" # maybe not needed, but would be painful to add a VM and forget.
|
||||||
|
];
|
||||||
|
}
|
21
hosts/common/programs.nix
Normal file
21
hosts/common/programs.nix
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
sane.programs = {
|
||||||
|
btrfs-progs.enableFor.system = true;
|
||||||
|
# "cacert.unbundled".enableFor.system = true;
|
||||||
|
cryptsetup.enableFor.system = true;
|
||||||
|
dig = {
|
||||||
|
enableFor.system = true;
|
||||||
|
suggestedPrograms = [ "efibootmgr" ];
|
||||||
|
};
|
||||||
|
efibootmgr = {};
|
||||||
|
fatresize = {};
|
||||||
|
|
||||||
|
backblaze-b2.enableFor.user.colin = true;
|
||||||
|
cdrtools = {
|
||||||
|
enableFor.user.colin = true;
|
||||||
|
suggestedPrograms = [ "dmidecode" ];
|
||||||
|
};
|
||||||
|
dmidecode = {};
|
||||||
|
};
|
||||||
|
}
|
@@ -1,24 +1,33 @@
|
|||||||
{ config, lib, sane-data, sane-lib, ... }:
|
{ config, lib, sane-data, sane-lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (builtins) head map mapAttrs tail;
|
||||||
|
inherit (lib) concatStringsSep mkMerge reverseList;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
sane.ssh.pubkeys =
|
sane.ssh.pubkeys =
|
||||||
let
|
let
|
||||||
# path is a DNS-style path like [ "org" "uninsane" "root" ]
|
# path is a DNS-style path like [ "org" "uninsane" "root" ]
|
||||||
keyNameForPath = path:
|
keyNameForPath = path:
|
||||||
let
|
let
|
||||||
rev = lib.reverseList path;
|
rev = reverseList path;
|
||||||
name = builtins.head rev;
|
name = head rev;
|
||||||
host = lib.concatStringsSep "." (builtins.tail rev);
|
host = concatStringsSep "." (tail rev);
|
||||||
in
|
in
|
||||||
"${name}@${host}";
|
"${name}@${host}";
|
||||||
|
|
||||||
# [{ path :: [String], value :: String }] for the keys we want to install
|
# [{ path :: [String], value :: String }] for the keys we want to install
|
||||||
globalKeys = sane-lib.flattenAttrs sane-data.keys;
|
globalKeys = sane-lib.flattenAttrs sane-data.keys;
|
||||||
localKeys = sane-lib.flattenAttrs sane-data.keys.org.uninsane.local;
|
domainKeys = sane-lib.flattenAttrs (
|
||||||
in lib.mkMerge (builtins.map
|
mapAttrs (host: cfg: {
|
||||||
|
colin = cfg.ssh.user_pubkey;
|
||||||
|
root = cfg.ssh.host_pubkey;
|
||||||
|
}) config.sane.hosts.by-name
|
||||||
|
);
|
||||||
|
in mkMerge (map
|
||||||
({ path, value }: {
|
({ path, value }: {
|
||||||
"${keyNameForPath path}" = value;
|
"${keyNameForPath path}" = lib.mkIf (value != null) value;
|
||||||
})
|
})
|
||||||
(globalKeys ++ localKeys)
|
(globalKeys ++ domainKeys)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -3,12 +3,12 @@
|
|||||||
# installer docs: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/installation-device.nix
|
# installer docs: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/installation-device.nix
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
cfg = config.sane.users;
|
cfg = config.sane.guest;
|
||||||
fs = sane-lib.fs;
|
fs = sane-lib.fs;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
sane.users.guest.enable = mkOption {
|
sane.guest.enable = mkOption {
|
||||||
default = false;
|
default = false;
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
};
|
};
|
||||||
@@ -49,6 +49,8 @@ in
|
|||||||
|
|
||||||
shell = pkgs.zsh;
|
shell = pkgs.zsh;
|
||||||
|
|
||||||
|
packages = builtins.map (p: p.pkg) config.sane.packages.enabledUserPkgs;
|
||||||
|
|
||||||
# mount encrypted stuff at login
|
# mount encrypted stuff at login
|
||||||
# some other nix pam users:
|
# some other nix pam users:
|
||||||
# - <https://github.com/g00pix/nixconf/blob/32c04f6fa843fed97639dd3f09e157668d3eea1f/profiles/sshfs.nix>
|
# - <https://github.com/g00pix/nixconf/blob/32c04f6fa843fed97639dd3f09e157668d3eea1f/profiles/sshfs.nix>
|
||||||
@@ -66,6 +68,7 @@ in
|
|||||||
|
|
||||||
security.pam.mount.enable = true;
|
security.pam.mount.enable = true;
|
||||||
|
|
||||||
|
sane.users.colin.default = true;
|
||||||
# ensure ~ perms are known to sane.fs module.
|
# ensure ~ perms are known to sane.fs module.
|
||||||
# TODO: this is generic enough to be lifted up into sane.fs itself.
|
# TODO: this is generic enough to be lifted up into sane.fs itself.
|
||||||
sane.fs."/home/colin".dir.acl = {
|
sane.fs."/home/colin".dir.acl = {
|
||||||
@@ -74,7 +77,7 @@ in
|
|||||||
mode = config.users.users.colin.homeMode;
|
mode = config.users.users.colin.homeMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
sane.persist.home.plaintext = [
|
sane.user.persist.plaintext = [
|
||||||
"archive"
|
"archive"
|
||||||
"dev"
|
"dev"
|
||||||
# TODO: records should be private
|
# TODO: records should be private
|
||||||
@@ -86,25 +89,27 @@ in
|
|||||||
"Pictures"
|
"Pictures"
|
||||||
"Videos"
|
"Videos"
|
||||||
|
|
||||||
|
".cache/nix"
|
||||||
|
".cache/nix-index"
|
||||||
".cargo"
|
".cargo"
|
||||||
".rustup"
|
".rustup"
|
||||||
];
|
];
|
||||||
|
|
||||||
# convenience
|
# convenience
|
||||||
sane.fs."/home/colin/knowledge" = fs.wantedSymlinkTo "/home/colin/private/knowledge";
|
sane.user.fs."knowledge" = fs.wantedSymlinkTo "private/knowledge";
|
||||||
sane.fs."/home/colin/nixos" = fs.wantedSymlinkTo "/home/colin/dev/nixos";
|
sane.user.fs."nixos" = fs.wantedSymlinkTo "dev/nixos";
|
||||||
sane.fs."/home/colin/Videos/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Videos";
|
sane.user.fs."Videos/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Videos";
|
||||||
sane.fs."/home/colin/Videos/servo-incomplete" = fs.wantedSymlinkTo "/mnt/servo-media/incomplete";
|
sane.user.fs."Videos/servo-incomplete" = fs.wantedSymlinkTo "/mnt/servo-media/incomplete";
|
||||||
sane.fs."/home/colin/Music/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Music";
|
sane.user.fs."Music/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Music";
|
||||||
|
|
||||||
# used by password managers, e.g. unix `pass`
|
# used by password managers, e.g. unix `pass`
|
||||||
sane.fs."/home/colin/.password-store" = fs.wantedSymlinkTo "/home/colin/knowledge/secrets/accounts";
|
sane.user.fs.".password-store" = fs.wantedSymlinkTo "knowledge/secrets/accounts";
|
||||||
|
|
||||||
sane.persist.sys.plaintext = mkIf cfg.guest.enable [
|
sane.persist.sys.plaintext = mkIf cfg.enable [
|
||||||
# intentionally allow other users to write to the guest folder
|
# intentionally allow other users to write to the guest folder
|
||||||
{ directory = "/home/guest"; user = "guest"; group = "users"; mode = "0775"; }
|
{ directory = "/home/guest"; user = "guest"; group = "users"; mode = "0775"; }
|
||||||
];
|
];
|
||||||
users.users.guest = mkIf cfg.guest.enable {
|
users.users.guest = mkIf cfg.enable {
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
home = "/home/guest";
|
home = "/home/guest";
|
||||||
subUidRanges = [
|
subUidRanges = [
|
||||||
@@ -125,8 +130,8 @@ in
|
|||||||
|
|
||||||
services.openssh = {
|
services.openssh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
permitRootLogin = "no";
|
settings.PermitRootLogin = "no";
|
||||||
passwordAuthentication = false;
|
settings.PasswordAuthentication = false;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,16 @@
|
|||||||
# trampoline from flake.nix into the specific host definition, while doing a tiny bit of common setup
|
# trampoline from flake.nix into the specific host definition, while doing a tiny bit of common setup
|
||||||
|
|
||||||
|
# args from flake-level `import`
|
||||||
{ hostName, localSystem }:
|
{ hostName, localSystem }:
|
||||||
{ ... }:
|
|
||||||
|
# module args
|
||||||
|
{ config, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./${hostName}
|
./by-name/${hostName}
|
||||||
./common
|
./common
|
||||||
|
./modules
|
||||||
];
|
];
|
||||||
|
|
||||||
networking.hostName = hostName;
|
networking.hostName = hostName;
|
||||||
|
15
hosts/modules/default.nix
Normal file
15
hosts/modules/default.nix
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{ ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./derived-secrets.nix
|
||||||
|
./gui
|
||||||
|
./hardware
|
||||||
|
./hostnames.nix
|
||||||
|
./hosts.nix
|
||||||
|
./nixcache.nix
|
||||||
|
./roles
|
||||||
|
./services
|
||||||
|
./wg-home.nix
|
||||||
|
];
|
||||||
|
}
|
47
hosts/modules/derived-secrets.nix
Normal file
47
hosts/modules/derived-secrets.nix
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (builtins) toString;
|
||||||
|
inherit (lib) mapAttrs mkOption types;
|
||||||
|
cfg = config.sane.derived-secrets;
|
||||||
|
secret = types.submodule {
|
||||||
|
options = {
|
||||||
|
len = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
};
|
||||||
|
encoding = mkOption {
|
||||||
|
type = types.enum [ "base64" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
sane.derived-secrets = mkOption {
|
||||||
|
type = types.attrsOf secret;
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
fs path => secret options.
|
||||||
|
for each entry, we create an item at the given path whose value is deterministic,
|
||||||
|
but also pseudo-random and not predictable by anyone without root access to the machine.
|
||||||
|
as PRNG source we use the host ssh key, and derived secrets are salted based on the destination path.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
sane.fs = mapAttrs (path: c: {
|
||||||
|
generated.script.script = ''
|
||||||
|
echo "$1" | cat /dev/stdin /etc/ssh/host_keys/ssh_host_ed25519_key \
|
||||||
|
| sha512sum \
|
||||||
|
| cut -c 1-${toString (c.len * 2)} \
|
||||||
|
| tr a-z A-Z \
|
||||||
|
| basenc -d --base16 \
|
||||||
|
| basenc --${c.encoding} \
|
||||||
|
> "$1"
|
||||||
|
'';
|
||||||
|
generated.script.scriptArgs = [ path ];
|
||||||
|
generated.acl.mode = "0600";
|
||||||
|
}) cfg;
|
||||||
|
};
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
{ lib, config, ... }:
|
{ lib, config, ... }:
|
||||||
|
|
||||||
with lib;
|
|
||||||
let
|
let
|
||||||
|
inherit (lib) mkDefault mkIf mkOption types;
|
||||||
cfg = config.sane.gui;
|
cfg = config.sane.gui;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@@ -14,15 +14,19 @@ in
|
|||||||
];
|
];
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
# doesn't directly create outputs. consumed by e.g. home-manager.nix module
|
|
||||||
sane.gui.enable = mkOption {
|
sane.gui.enable = mkOption {
|
||||||
default = false;
|
default = false;
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
|
description = ''
|
||||||
|
enables config used by any GUI, like display management or select packages.
|
||||||
|
the user should prefer to interact with specific GUIs like `sane.gui.sway`
|
||||||
|
and let those modules auto-set this flag when necessary.
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
sane.packages.enableGuiPkgs = lib.mkDefault true;
|
sane.packages.enableGuiPkgs = mkDefault true;
|
||||||
|
|
||||||
# preserve backlight brightness across power cycles
|
# preserve backlight brightness across power cycles
|
||||||
# see `man systemd-backlight`
|
# see `man systemd-backlight`
|
@@ -25,7 +25,7 @@ in
|
|||||||
networking.networkmanager.enable = true;
|
networking.networkmanager.enable = true;
|
||||||
networking.wireless.enable = lib.mkForce false;
|
networking.wireless.enable = lib.mkForce false;
|
||||||
};
|
};
|
||||||
# home-mananger.users.colin extras
|
# user extras:
|
||||||
# obtain these by running `dconf dump /` after manually customizing gnome
|
# obtain these by running `dconf dump /` after manually customizing gnome
|
||||||
# TODO: fix "is not of type `GVariant value'"
|
# TODO: fix "is not of type `GVariant value'"
|
||||||
# dconf.settings = lib.mkIf (gui == "gnome") {
|
# dconf.settings = lib.mkIf (gui == "gnome") {
|
@@ -59,6 +59,24 @@ in
|
|||||||
NIXOS_OZONE_WL = "1";
|
NIXOS_OZONE_WL = "1";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
programs.dconf.packages = [
|
||||||
|
(pkgs.writeTextFile {
|
||||||
|
name = "dconf-phosh-settings";
|
||||||
|
destination = "/etc/dconf/db/site.d/00_phosh_settings";
|
||||||
|
text = ''
|
||||||
|
[org/gnome/desktop/interface]
|
||||||
|
show-battery-percentage=true
|
||||||
|
|
||||||
|
[org/gnome/settings-daemon/plugins/power]
|
||||||
|
sleep-inactive-ac-timeout=5400
|
||||||
|
sleep-inactive-battery-timeout=5400
|
||||||
|
|
||||||
|
[sm/puri/phosh]
|
||||||
|
favorites=['gpodder.desktop', 'nheko.desktop', 'sublime-music.desktop', 'firefox.desktop', 'org.kde.konsole.desktop']
|
||||||
|
'';
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
sane.packages.extraUserPkgs = with pkgs; [
|
sane.packages.extraUserPkgs = with pkgs; [
|
||||||
phosh-mobile-settings
|
phosh-mobile-settings
|
||||||
|
|
@@ -1,6 +1,7 @@
|
|||||||
https://search.nixos.org/options?channel=unstable&query=
|
https://search.nixos.org/options?channel=unstable&query=
|
||||||
https://search.nixos.org/packages?channel=unstable&query=
|
https://search.nixos.org/packages?channel=unstable&query=
|
||||||
https://nixos.wiki/index.php?go=Go&search=
|
https://nixos.wiki/index.php?go=Go&search=
|
||||||
|
https://nixos.org/manual/nix/stable/language/builtins.html
|
||||||
https://github.com/nixos/nixpkgs/pulls?q=
|
https://github.com/nixos/nixpkgs/pulls?q=
|
||||||
https://nur.nix-community.org/
|
https://nur.nix-community.org/
|
||||||
https://nix-community.github.io/home-manager/options.html
|
https://nix-community.github.io/home-manager/options.html
|
642
hosts/modules/gui/sway.nix
Normal file
642
hosts/modules/gui/sway.nix
Normal file
@@ -0,0 +1,642 @@
|
|||||||
|
{ config, lib, pkgs, sane-lib, ... }:
|
||||||
|
|
||||||
|
# docs: https://nixos.wiki/wiki/Sway
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.sane.gui.sway;
|
||||||
|
# docs: https://github.com/Alexays/Waybar/wiki/Configuration
|
||||||
|
# format specifiers: https://fmt.dev/latest/syntax.html#syntax
|
||||||
|
waybar-config = [
|
||||||
|
{ # TOP BAR
|
||||||
|
layer = "top";
|
||||||
|
height = 40;
|
||||||
|
modules-left = ["sway/workspaces" "sway/mode"];
|
||||||
|
modules-center = ["sway/window"];
|
||||||
|
modules-right = ["custom/mediaplayer" "clock" "battery" "cpu" "network"];
|
||||||
|
"sway/window" = {
|
||||||
|
max-length = 50;
|
||||||
|
};
|
||||||
|
# include song artist/title. source: https://www.reddit.com/r/swaywm/comments/ni0vso/waybar_spotify_tracktitle/
|
||||||
|
"custom/mediaplayer" = {
|
||||||
|
exec = pkgs.writeShellScript "waybar-mediaplayer" ''
|
||||||
|
player_status=$(${pkgs.playerctl}/bin/playerctl status 2> /dev/null)
|
||||||
|
if [ "$player_status" = "Playing" ]; then
|
||||||
|
echo "$(${pkgs.playerctl}/bin/playerctl metadata artist) - $(${pkgs.playerctl}/bin/playerctl metadata title)"
|
||||||
|
elif [ "$player_status" = "Paused" ]; then
|
||||||
|
echo " $(${pkgs.playerctl}/bin/playerctl metadata artist) - $(${pkgs.playerctl}/bin/playerctl metadata title)"
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
interval = 2;
|
||||||
|
format = "{} ";
|
||||||
|
# return-type = "json";
|
||||||
|
on-click = "${pkgs.playerctl}/bin/playerctl play-pause";
|
||||||
|
on-scroll-up = "${pkgs.playerctl}/bin/playerctl next";
|
||||||
|
on-scroll-down = "${pkgs.playerctl}/bin/playerctl previous";
|
||||||
|
};
|
||||||
|
network = {
|
||||||
|
# docs: https://github.com/Alexays/Waybar/blob/master/man/waybar-network.5.scd
|
||||||
|
interval = 2;
|
||||||
|
max-length = 40;
|
||||||
|
# custom :> format specifier explained here: https://github.com/Alexays/Waybar/pull/472
|
||||||
|
format-ethernet = " {bandwidthUpBits:>}▲ {bandwidthDownBits:>}▼";
|
||||||
|
tooltip-format-ethernet = "{ifname} {bandwidthUpBits:>}▲ {bandwidthDownBits:>}▼";
|
||||||
|
|
||||||
|
format-wifi = "{ifname} ({signalStrength}%) {bandwidthUpBits:>}▲ {bandwidthDownBits:>}▼";
|
||||||
|
tooltip-format-wifi = "{essid} ({signalStrength}%) {bandwidthUpBits:>}▲ {bandwidthDownBits:>}▼";
|
||||||
|
|
||||||
|
format-disconnected = "";
|
||||||
|
};
|
||||||
|
cpu = {
|
||||||
|
format = " {usage:2}%";
|
||||||
|
tooltip = false;
|
||||||
|
};
|
||||||
|
battery = {
|
||||||
|
states = {
|
||||||
|
good = 95;
|
||||||
|
warning = 30;
|
||||||
|
critical = 10;
|
||||||
|
};
|
||||||
|
format = "{icon} {capacity}%";
|
||||||
|
format-icons = [
|
||||||
|
""
|
||||||
|
""
|
||||||
|
""
|
||||||
|
""
|
||||||
|
""
|
||||||
|
];
|
||||||
|
};
|
||||||
|
clock = {
|
||||||
|
format-alt = "{:%a, %d. %b %H:%M}";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
# waybar-config-text = lib.generators.toJSON {} waybar-config;
|
||||||
|
waybar-config-text = (pkgs.formats.json {}).generate "waybar-config.json" waybar-config;
|
||||||
|
|
||||||
|
# bare sway launcher
|
||||||
|
sway-launcher = pkgs.writeShellScriptBin "sway-launcher" ''
|
||||||
|
${pkgs.sway}/bin/sway --debug > /tmp/sway.log 2>&1
|
||||||
|
'';
|
||||||
|
# start sway and have it construct the gtkgreeter
|
||||||
|
sway-as-greeter = pkgs.writeShellScriptBin "sway-as-greeter" ''
|
||||||
|
${pkgs.sway}/bin/sway --debug --config ${sway-config-into-gtkgreet} > /tmp/sway-as-greeter.log 2>&1
|
||||||
|
'';
|
||||||
|
# (config file for the above)
|
||||||
|
sway-config-into-gtkgreet = pkgs.writeText "greetd-sway-config" ''
|
||||||
|
exec "${gtkgreet-launcher}"
|
||||||
|
'';
|
||||||
|
# gtkgreet which launches a layered sway instance
|
||||||
|
gtkgreet-launcher = pkgs.writeShellScript "gtkgreet-launcher" ''
|
||||||
|
# NB: the "command" field here is run in the user's shell.
|
||||||
|
# so that command must exist on the specific user's path who is logging in. it doesn't need to exist system-wide.
|
||||||
|
${pkgs.greetd.gtkgreet}/bin/gtkgreet --layer-shell --command sway-launcher
|
||||||
|
'';
|
||||||
|
greeter-session = {
|
||||||
|
# greeter session config
|
||||||
|
command = "${sway-as-greeter}/bin/sway-as-greeter";
|
||||||
|
# alternatives:
|
||||||
|
# - TTY: `command = "${pkgs.greetd.greetd}/bin/agreety --cmd ${pkgs.sway}/bin/sway";`
|
||||||
|
# - autologin: `command = "${pkgs.sway}/bin/sway"; user = "colin";`
|
||||||
|
# - Dumb Login (doesn't work)": `command = "${pkgs.greetd.dlm}/bin/dlm";`
|
||||||
|
};
|
||||||
|
greeterless-session = {
|
||||||
|
# no greeter
|
||||||
|
command = "${sway-launcher}/bin/sway-launcher";
|
||||||
|
user = "colin";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
sane.gui.sway.enable = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
sane.gui.sway.useGreeter = mkOption {
|
||||||
|
description = ''
|
||||||
|
launch sway via a greeter (like greetd's gtkgreet).
|
||||||
|
sway is usable without a greeter, but skipping the greeter means no PAM session.
|
||||||
|
'';
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
sane.gui.enable = true;
|
||||||
|
|
||||||
|
# swap in these lines to use SDDM instead of `services.greetd`.
|
||||||
|
# services.xserver.displayManager.sddm.enable = true;
|
||||||
|
# services.xserver.enable = true;
|
||||||
|
services.greetd = {
|
||||||
|
# greetd source/docs:
|
||||||
|
# - <https://git.sr.ht/~kennylevinsen/greetd>
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
default_session = if cfg.useGreeter then greeter-session else greeterless-session;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# we need the greeter's command to be on our PATH
|
||||||
|
users.users.colin.packages = [ sway-launcher ];
|
||||||
|
|
||||||
|
# some programs (e.g. fractal) **require** a "Secret Service Provider"
|
||||||
|
services.gnome.gnome-keyring.enable = true;
|
||||||
|
|
||||||
|
# unlike other DEs, sway configures no audio stack
|
||||||
|
# administer with pw-cli, pw-mon, pw-top commands
|
||||||
|
services.pipewire = {
|
||||||
|
enable = true;
|
||||||
|
alsa.enable = true;
|
||||||
|
alsa.support32Bit = true; # ??
|
||||||
|
pulse.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.useDHCP = false;
|
||||||
|
networking.networkmanager.enable = true;
|
||||||
|
networking.wireless.enable = lib.mkForce false;
|
||||||
|
|
||||||
|
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;
|
||||||
|
# start the components of gsd we need at login
|
||||||
|
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;
|
||||||
|
# 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" ];
|
||||||
|
|
||||||
|
programs.sway = {
|
||||||
|
enable = true;
|
||||||
|
wrapperFeatures.gtk = true;
|
||||||
|
};
|
||||||
|
sane.user.fs.".config/sway/config" =
|
||||||
|
let
|
||||||
|
fuzzel = "${pkgs.fuzzel}/bin/fuzzel";
|
||||||
|
sed = "${pkgs.gnused}/bin/sed";
|
||||||
|
wtype = "${pkgs.wtype}/bin/wtype";
|
||||||
|
kitty = "${pkgs.kitty}/bin/kitty";
|
||||||
|
launcher-cmd = fuzzel;
|
||||||
|
terminal-cmd = kitty;
|
||||||
|
lock-cmd = "${pkgs.swaylock}/bin/swaylock --indicator-idle-visible --indicator-radius 100 --indicator-thickness 30";
|
||||||
|
vol-up-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --change-volume +5";
|
||||||
|
vol-down-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --change-volume -5";
|
||||||
|
mute-cmd = "${pkgs.pulsemixer}/bin/pulsemixer --toggle-mute";
|
||||||
|
brightness-up-cmd = "${pkgs.brightnessctl}/bin/brightnessctl set +2%";
|
||||||
|
brightness-down-cmd = "${pkgs.brightnessctl}/bin/brightnessctl set 2%-";
|
||||||
|
screenshot-cmd = "${pkgs.sway-contrib.grimshot}/bin/grimshot copy area";
|
||||||
|
# "bookmarking"/snippets inspired by Luke Smith:
|
||||||
|
# - <https://www.youtube.com/watch?v=d_11QaTlf1I>
|
||||||
|
snip-file = ./snippets.txt;
|
||||||
|
# TODO: querying sops here breaks encapsulation
|
||||||
|
list-snips = "cat ${snip-file} ${config.sops.secrets.snippets.path}";
|
||||||
|
strip-comments = "${sed} 's/ #.*$//'";
|
||||||
|
snip-cmd = "${wtype} $(${list-snips} | ${fuzzel} -d -i -w 60 | ${strip-comments})";
|
||||||
|
# TODO: next splatmoji release should allow `-s none` to disable skin tones
|
||||||
|
emoji-cmd = "${pkgs.splatmoji}/bin/splatmoji -s medium-light type";
|
||||||
|
in sane-lib.fs.wantedText ''
|
||||||
|
### default font
|
||||||
|
font pango:monospace 8
|
||||||
|
|
||||||
|
### pixel boundary between windows
|
||||||
|
default_border pixel 3
|
||||||
|
default_floating_border pixel 2
|
||||||
|
hide_edge_borders smart
|
||||||
|
|
||||||
|
### defaults
|
||||||
|
focus_wrapping no
|
||||||
|
focus_follows_mouse yes
|
||||||
|
focus_on_window_activation smart
|
||||||
|
mouse_warping output
|
||||||
|
workspace_layout default
|
||||||
|
workspace_auto_back_and_forth no
|
||||||
|
|
||||||
|
### default colors (#border #background #text #indicator #childBorder)
|
||||||
|
client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577
|
||||||
|
client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a
|
||||||
|
client.unfocused #333333 #222222 #888888 #292d2e #222222
|
||||||
|
client.urgent #2f343a #900000 #ffffff #900000 #900000
|
||||||
|
client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c
|
||||||
|
client.background #ffffff
|
||||||
|
|
||||||
|
### key bindings
|
||||||
|
floating_modifier Mod1
|
||||||
|
## media keys
|
||||||
|
bindsym XF86AudioRaiseVolume exec ${vol-up-cmd}
|
||||||
|
bindsym XF86AudioLowerVolume exec ${vol-down-cmd}
|
||||||
|
bindsym Mod1+Page_Up exec ${vol-up-cmd}
|
||||||
|
bindsym Mod1+Page_Down exec ${vol-down-cmd}
|
||||||
|
bindsym XF86AudioMute exec ${mute-cmd}
|
||||||
|
bindsym XF86MonBrightnessUp exec ${brightness-up-cmd}
|
||||||
|
bindsym XF86MonBrightnessDown exec ${brightness-down-cmd}
|
||||||
|
## special functions
|
||||||
|
bindsym Mod1+Print exec ${screenshot-cmd}
|
||||||
|
bindsym Mod1+l exec ${lock-cmd}
|
||||||
|
bindsym Mod1+s exec ${snip-cmd}
|
||||||
|
bindsym Mod1+slash exec ${emoji-cmd}
|
||||||
|
bindsym Mod1+d exec ${launcher-cmd}
|
||||||
|
bindsym Mod1+Return exec ${terminal-cmd}
|
||||||
|
bindsym Mod1+Shift+q kill
|
||||||
|
bindsym Mod1+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'
|
||||||
|
bindsym Mod1+Shift+c reload
|
||||||
|
## layout
|
||||||
|
bindsym Mod1+b splith
|
||||||
|
bindsym Mod1+v splitv
|
||||||
|
bindsym Mod1+f fullscreen toggle
|
||||||
|
bindsym Mod1+a focus parent
|
||||||
|
bindsym Mod1+w layout tabbed
|
||||||
|
bindsym Mod1+e layout toggle split
|
||||||
|
bindsym Mod1+Shift+space floating toggle
|
||||||
|
bindsym Mod1+space focus mode_toggle
|
||||||
|
bindsym Mod1+r mode resize
|
||||||
|
## movement
|
||||||
|
bindsym Mod1+Up focus up
|
||||||
|
bindsym Mod1+Down focus down
|
||||||
|
bindsym Mod1+Left focus left
|
||||||
|
bindsym Mod1+Right focus right
|
||||||
|
bindsym Mod1+Shift+Up move up
|
||||||
|
bindsym Mod1+Shift+Down move down
|
||||||
|
bindsym Mod1+Shift+Left move left
|
||||||
|
bindsym Mod1+Shift+Right move right
|
||||||
|
## workspaces
|
||||||
|
bindsym Mod1+1 workspace number 1
|
||||||
|
bindsym Mod1+2 workspace number 2
|
||||||
|
bindsym Mod1+3 workspace number 3
|
||||||
|
bindsym Mod1+4 workspace number 4
|
||||||
|
bindsym Mod1+5 workspace number 5
|
||||||
|
bindsym Mod1+6 workspace number 6
|
||||||
|
bindsym Mod1+7 workspace number 7
|
||||||
|
bindsym Mod1+8 workspace number 8
|
||||||
|
bindsym Mod1+9 workspace number 9
|
||||||
|
bindsym Mod1+Shift+1 move container to workspace number 1
|
||||||
|
bindsym Mod1+Shift+2 move container to workspace number 2
|
||||||
|
bindsym Mod1+Shift+3 move container to workspace number 3
|
||||||
|
bindsym Mod1+Shift+4 move container to workspace number 4
|
||||||
|
bindsym Mod1+Shift+5 move container to workspace number 5
|
||||||
|
bindsym Mod1+Shift+6 move container to workspace number 6
|
||||||
|
bindsym Mod1+Shift+7 move container to workspace number 7
|
||||||
|
bindsym Mod1+Shift+8 move container to workspace number 8
|
||||||
|
bindsym Mod1+Shift+9 move container to workspace number 9
|
||||||
|
## "scratchpad" = ??
|
||||||
|
bindsym Mod1+Shift+minus move scratchpad
|
||||||
|
bindsym Mod1+minus scratchpad show
|
||||||
|
|
||||||
|
### defaults
|
||||||
|
mode "resize" {
|
||||||
|
bindsym Down resize grow height 10 px
|
||||||
|
bindsym Escape mode default
|
||||||
|
bindsym Left resize shrink width 10 px
|
||||||
|
bindsym Return mode default
|
||||||
|
bindsym Right resize grow width 10 px
|
||||||
|
bindsym Up resize shrink height 10 px
|
||||||
|
bindsym h resize shrink width 10 px
|
||||||
|
bindsym j resize grow height 10 px
|
||||||
|
bindsym k resize shrink height 10 px
|
||||||
|
bindsym l resize grow width 10 px
|
||||||
|
}
|
||||||
|
|
||||||
|
### lightly modified bars
|
||||||
|
bar {
|
||||||
|
# TODO: fonts was:
|
||||||
|
# config.fonts.fontconfig.defaultFonts; (monospace ++ emoji)
|
||||||
|
font pango:Hack, Font Awesome 6 Free, Twitter Color Emoji 24.000000
|
||||||
|
mode dock
|
||||||
|
hidden_state hide
|
||||||
|
position top
|
||||||
|
status_command ${pkgs.i3status}/bin/i3status
|
||||||
|
swaybar_command ${pkgs.waybar}/bin/waybar
|
||||||
|
workspace_buttons yes
|
||||||
|
strip_workspace_numbers no
|
||||||
|
tray_output primary
|
||||||
|
colors {
|
||||||
|
background #000000
|
||||||
|
statusline #ffffff
|
||||||
|
separator #666666
|
||||||
|
# #border #background #text
|
||||||
|
focused_workspace #4c7899 #285577 #ffffff
|
||||||
|
active_workspace #333333 #5f676a #ffffff
|
||||||
|
inactive_workspace #333333 #222222 #888888
|
||||||
|
urgent_workspace #2f343a #900000 #ffffff
|
||||||
|
binding_mode #2f343a #900000 #ffffff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
### displays
|
||||||
|
## DESKTOP
|
||||||
|
output "Samsung Electric Company S22C300 0x00007F35" {
|
||||||
|
pos 0,0
|
||||||
|
res 1920x1080
|
||||||
|
}
|
||||||
|
output "Goldstar Company Ltd LG ULTRAWIDE 0x00004E94" {
|
||||||
|
pos 1920,0
|
||||||
|
res 3440x1440
|
||||||
|
}
|
||||||
|
|
||||||
|
## LAPTOP
|
||||||
|
# sh/en TV
|
||||||
|
output "Pioneer Electronic Corporation VSX-524 0x00000101" {
|
||||||
|
pos 0,0
|
||||||
|
res 1920x1080
|
||||||
|
}
|
||||||
|
# internal display
|
||||||
|
output "Unknown 0x0637 0x00000000" {
|
||||||
|
pos 1920,0
|
||||||
|
res 1920x1080
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
sane.user.fs.".config/waybar/config" = sane-lib.fs.wantedSymlinkTo waybar-config-text;
|
||||||
|
|
||||||
|
# style docs: https://github.com/Alexays/Waybar/wiki/Styling
|
||||||
|
sane.user.fs.".config/waybar/style.css" = sane-lib.fs.wantedText ''
|
||||||
|
* {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* defaults below: https://github.com/Alexays/Waybar/blob/master/resources/style.css */
|
||||||
|
window#waybar {
|
||||||
|
background-color: rgba(43, 48, 59, 0.5);
|
||||||
|
border-bottom: 3px solid rgba(100, 114, 125, 0.5);
|
||||||
|
color: #ffffff;
|
||||||
|
transition-property: background-color;
|
||||||
|
transition-duration: .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
window#waybar.hidden {
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
window#waybar.empty {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
window#waybar.solo {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
window#waybar.termite {
|
||||||
|
background-color: #3F3F3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
window#waybar.chromium {
|
||||||
|
background-color: #000000;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#workspaces button {
|
||||||
|
padding: 0 5px;
|
||||||
|
background-color: transparent;
|
||||||
|
color: #ffffff;
|
||||||
|
/* Use box-shadow instead of border so the text isn't offset */
|
||||||
|
box-shadow: inset 0 -3px transparent;
|
||||||
|
/* Avoid rounded borders under each workspace name */
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */
|
||||||
|
#workspaces button:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
box-shadow: inset 0 -3px #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#workspaces button.focused {
|
||||||
|
background-color: #64727D;
|
||||||
|
box-shadow: inset 0 -3px #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#workspaces button.urgent {
|
||||||
|
background-color: #eb4d4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mode {
|
||||||
|
background-color: #64727D;
|
||||||
|
border-bottom: 3px solid #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#clock,
|
||||||
|
#battery,
|
||||||
|
#cpu,
|
||||||
|
#memory,
|
||||||
|
#disk,
|
||||||
|
#temperature,
|
||||||
|
#backlight,
|
||||||
|
#network,
|
||||||
|
#pulseaudio,
|
||||||
|
#custom-media,
|
||||||
|
#tray,
|
||||||
|
#mode,
|
||||||
|
#idle_inhibitor,
|
||||||
|
#mpd {
|
||||||
|
padding: 0 10px;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#window,
|
||||||
|
#workspaces {
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If workspaces is the leftmost module, omit left margin */
|
||||||
|
.modules-left > widget:first-child > #workspaces {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If workspaces is the rightmost module, omit right margin */
|
||||||
|
.modules-right > widget:last-child > #workspaces {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#clock {
|
||||||
|
background-color: #64727D;
|
||||||
|
}
|
||||||
|
|
||||||
|
#battery {
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#battery.charging, #battery.plugged {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #26A65B;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes blink {
|
||||||
|
to {
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#battery.critical:not(.charging) {
|
||||||
|
background-color: #f53c3c;
|
||||||
|
color: #ffffff;
|
||||||
|
animation-name: blink;
|
||||||
|
animation-duration: 0.5s;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
animation-direction: alternate;
|
||||||
|
}
|
||||||
|
|
||||||
|
label:focus {
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cpu {
|
||||||
|
background-color: #2ecc71;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#memory {
|
||||||
|
background-color: #9b59b6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#disk {
|
||||||
|
background-color: #964B00;
|
||||||
|
}
|
||||||
|
|
||||||
|
#backlight {
|
||||||
|
background-color: #90b1b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#network {
|
||||||
|
background-color: #2980b9;
|
||||||
|
}
|
||||||
|
|
||||||
|
#network.disconnected {
|
||||||
|
background-color: #f53c3c;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pulseaudio {
|
||||||
|
background-color: #f1c40f;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pulseaudio.muted {
|
||||||
|
background-color: #90b1b1;
|
||||||
|
color: #2a5c45;
|
||||||
|
}
|
||||||
|
|
||||||
|
#custom-media {
|
||||||
|
background-color: #66cc99;
|
||||||
|
color: #2a5c45;
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#custom-media.custom-spotify {
|
||||||
|
background-color: #66cc99;
|
||||||
|
}
|
||||||
|
|
||||||
|
#custom-media.custom-vlc {
|
||||||
|
background-color: #ffa000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#temperature {
|
||||||
|
background-color: #f0932b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#temperature.critical {
|
||||||
|
background-color: #eb4d4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tray {
|
||||||
|
background-color: #2980b9;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tray > .passive {
|
||||||
|
-gtk-icon-effect: dim;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tray > .needs-attention {
|
||||||
|
-gtk-icon-effect: highlight;
|
||||||
|
background-color: #eb4d4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#idle_inhibitor {
|
||||||
|
background-color: #2d3436;
|
||||||
|
}
|
||||||
|
|
||||||
|
#idle_inhibitor.activated {
|
||||||
|
background-color: #ecf0f1;
|
||||||
|
color: #2d3436;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mpd {
|
||||||
|
background-color: #66cc99;
|
||||||
|
color: #2a5c45;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mpd.disconnected {
|
||||||
|
background-color: #f53c3c;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mpd.stopped {
|
||||||
|
background-color: #90b1b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mpd.paused {
|
||||||
|
background-color: #51a37a;
|
||||||
|
}
|
||||||
|
|
||||||
|
#language {
|
||||||
|
background: #00b093;
|
||||||
|
color: #740864;
|
||||||
|
padding: 0 5px;
|
||||||
|
margin: 0 5px;
|
||||||
|
min-width: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#keyboard-state {
|
||||||
|
background: #97e1ad;
|
||||||
|
color: #000000;
|
||||||
|
padding: 0 0px;
|
||||||
|
margin: 0 5px;
|
||||||
|
min-width: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#keyboard-state > label {
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#keyboard-state > label.locked {
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
# style = ''
|
||||||
|
# * {
|
||||||
|
# border: none;
|
||||||
|
# border-radius: 0;
|
||||||
|
# font-family: Source Code Pro;
|
||||||
|
# }
|
||||||
|
# window#waybar {
|
||||||
|
# background: #16191C;
|
||||||
|
# color: #AAB2BF;
|
||||||
|
# }
|
||||||
|
# #workspaces button {
|
||||||
|
# padding: 0 5px;
|
||||||
|
# }
|
||||||
|
# .custom-spotify {
|
||||||
|
# padding: 0 10px;
|
||||||
|
# margin: 0 4px;
|
||||||
|
# background-color: #1DB954;
|
||||||
|
# color: black;
|
||||||
|
# }
|
||||||
|
# '';
|
||||||
|
|
||||||
|
sane.packages.extraUserPkgs = with pkgs; [
|
||||||
|
swaylock
|
||||||
|
swayidle # (unused)
|
||||||
|
wl-clipboard
|
||||||
|
mako # notification daemon
|
||||||
|
xdg-utils # for xdg-open
|
||||||
|
# user stuff
|
||||||
|
# pavucontrol
|
||||||
|
sway-contrib.grimshot
|
||||||
|
gnome.gnome-bluetooth
|
||||||
|
gnome.gnome-control-center
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./all.nix
|
|
||||||
./x86_64.nix
|
./x86_64.nix
|
||||||
];
|
];
|
||||||
}
|
}
|
@@ -1,8 +1,7 @@
|
|||||||
{ lib, pkgs, ... }:
|
{ lib, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
|
||||||
{
|
{
|
||||||
config = mkIf (pkgs.system == "x86_64-linux") {
|
config = lib.mkIf (pkgs.system == "x86_64-linux") {
|
||||||
boot.initrd.availableKernelModules = [
|
boot.initrd.availableKernelModules = [
|
||||||
"xhci_pci" "ahci" "sd_mod" "sdhci_pci" # nixos-generate-config defaults
|
"xhci_pci" "ahci" "sd_mod" "sdhci_pci" # nixos-generate-config defaults
|
||||||
"usb_storage" # rpi needed this to boot from usb storage, i think.
|
"usb_storage" # rpi needed this to boot from usb storage, i think.
|
21
hosts/modules/hostnames.nix
Normal file
21
hosts/modules/hostnames.nix
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# give each host a shortname that all the other hosts know, to allow easy comms.
|
||||||
|
networking.hosts = lib.mkMerge [
|
||||||
|
(lib.mapAttrs' (host: cfg: {
|
||||||
|
# bare-name for LAN addresses
|
||||||
|
# if using router's DNS, these mappings will already exist.
|
||||||
|
# if using a different DNS provider (which servo does), then we need to explicity provide them.
|
||||||
|
# ugly hack. would be better to get servo to somehow use the router's DNS
|
||||||
|
name = cfg.lan-ip;
|
||||||
|
value = [ host ];
|
||||||
|
}) config.sane.hosts.by-name)
|
||||||
|
(lib.mapAttrs' (host: cfg: {
|
||||||
|
# -hn suffixed name for communication over my wg-home VPN.
|
||||||
|
# hn = "home network"
|
||||||
|
name = cfg.wg-home.ip;
|
||||||
|
value = [ "${host}-hn" ];
|
||||||
|
}) config.sane.hosts.by-name)
|
||||||
|
];
|
||||||
|
}
|
100
hosts/modules/hosts.nix
Normal file
100
hosts/modules/hosts.nix
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) attrValues filterAttrs mkMerge mkOption types;
|
||||||
|
cfg = config.sane.hosts;
|
||||||
|
|
||||||
|
host = types.submodule ({ config, ... }: {
|
||||||
|
options = {
|
||||||
|
ssh.user_pubkey = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
ssh pubkey that the primary user of this machine will use when connecting to other machines.
|
||||||
|
e.g. "ssh-ed25519 AAAA<base64>".
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
ssh.host_pubkey = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
ssh pubkey which this host will present to connections initiated against it.
|
||||||
|
e.g. "ssh-ed25519 AAAA<base64>".
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
wg-home.pubkey = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
wireguard public key for the wg-home VPN.
|
||||||
|
e.g. "pWtnKW7f7sNIZQ2M83uJ7cHg3IL1tebE3IoVkCgjkXM=".
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
wg-home.ip = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
IP address to use on the wg-home VPN.
|
||||||
|
e.g. "10.0.10.5";
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
wg-home.endpoint = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
lan-ip = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
ip address when on the lan.
|
||||||
|
e.g. "192.168.0.5";
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
sane.hosts.by-name = mkOption {
|
||||||
|
type = types.attrsOf host;
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
map of hostname => attrset of information specific to that host,
|
||||||
|
like its ssh pubkey, etc.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
# TODO: this should be populated per-host
|
||||||
|
sane.hosts.by-name."desko" = {
|
||||||
|
ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPU5GlsSfbaarMvDA20bxpSZGWviEzXGD8gtrIowc1pX";
|
||||||
|
ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFw9NoRaYrM6LbDd3aFBc4yyBlxGQn8HjeHd/dZ3CfHk";
|
||||||
|
wg-home.pubkey = "17PMZssYi0D4t2d0vbmhjBKe1sGsE8kT8/dod0Q2CXc=";
|
||||||
|
wg-home.ip = "10.0.10.22";
|
||||||
|
lan-ip = "192.168.0.22";
|
||||||
|
};
|
||||||
|
|
||||||
|
sane.hosts.by-name."lappy" = {
|
||||||
|
ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu";
|
||||||
|
ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc";
|
||||||
|
wg-home.pubkey = "FTUWGw2p4/cEcrrIE86PWVnqctbv8OYpw8Gt3+dC/lk=";
|
||||||
|
wg-home.ip = "10.0.10.20";
|
||||||
|
lan-ip = "192.168.0.20";
|
||||||
|
};
|
||||||
|
|
||||||
|
sane.hosts.by-name."moby" = {
|
||||||
|
ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrR+gePnl0nV/vy7I5BzrGeyVL+9eOuXHU1yNE3uCwU";
|
||||||
|
ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO1N/IT3nQYUD+dBlU1sTEEVMxfOyMkrrDeyHcYgnJvw";
|
||||||
|
wg-home.pubkey = "I7XIR1hm8bIzAtcAvbhWOwIAabGkuEvbWH/3kyIB1yA=";
|
||||||
|
wg-home.ip = "10.0.10.48";
|
||||||
|
lan-ip = "192.168.0.48";
|
||||||
|
};
|
||||||
|
|
||||||
|
sane.hosts.by-name."servo" = {
|
||||||
|
ssh.user_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPS1qFzKurAdB9blkWomq8gI1g0T3sTs9LsmFOj5VtqX";
|
||||||
|
ssh.host_pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOfdSmFkrVT6DhpgvFeQKm3Fh9VKZ9DbLYOPOJWYQ0E8";
|
||||||
|
wg-home.pubkey = "roAw+IUFVtdpCcqa4khB385Qcv9l5JAB//730tyK4Wk=";
|
||||||
|
wg-home.ip = "10.0.10.5";
|
||||||
|
wg-home.endpoint = "uninsane.org:51820";
|
||||||
|
lan-ip = "192.168.0.5";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
18
hosts/modules/roles/client/bluetooth-pairings.nix
Normal file
18
hosts/modules/roles/client/bluetooth-pairings.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
config = lib.mkIf config.sane.roles.client {
|
||||||
|
# persist external pairings by default
|
||||||
|
sane.persist.sys.plaintext = [ "/var/lib/bluetooth" ];
|
||||||
|
|
||||||
|
sane.fs."/var/lib/bluetooth".generated.acl.mode = "0700";
|
||||||
|
sane.fs."/var/lib/bluetooth/.secrets.stamp" = {
|
||||||
|
wantedBeforeBy = [ "bluetooth.service" ];
|
||||||
|
# XXX: install-bluetooth uses sed, but that's part of the default systemd unit path, it seems
|
||||||
|
generated.script.script = builtins.readFile ../../../../scripts/install-bluetooth + ''
|
||||||
|
touch "/var/lib/bluetooth/.secrets.stamp"
|
||||||
|
'';
|
||||||
|
generated.script.scriptArgs = [ "/run/secrets/bt" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
17
hosts/modules/roles/client/default.nix
Normal file
17
hosts/modules/roles/client/default.nix
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib) mkIf mkOption types;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./bluetooth-pairings.nix
|
||||||
|
./wifi-pairings.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
# option is consumed by the other imports in this dir
|
||||||
|
options.sane.roles.client = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
}
|
15
hosts/modules/roles/client/wifi-pairings.nix
Normal file
15
hosts/modules/roles/client/wifi-pairings.nix
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
config = lib.mkIf config.sane.roles.client {
|
||||||
|
sane.fs."/var/lib/iwd/.secrets.psk.stamp" = {
|
||||||
|
wantedBeforeBy = [ "iwd.service" ];
|
||||||
|
generated.acl.mode = "0600";
|
||||||
|
# XXX: install-iwd uses sed, but that's part of the default systemd unit path, it seems
|
||||||
|
generated.script.script = builtins.readFile ../../../../scripts/install-iwd + ''
|
||||||
|
touch "/var/lib/iwd/.secrets.psk.stamp"
|
||||||
|
'';
|
||||||
|
generated.script.scriptArgs = [ "/run/secrets/iwd" "/var/lib/iwd" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
6
hosts/modules/roles/default.nix
Normal file
6
hosts/modules/roles/default.nix
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./client
|
||||||
|
];
|
||||||
|
}
|
6
hosts/modules/services/default.nix
Normal file
6
hosts/modules/services/default.nix
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./duplicity.nix
|
||||||
|
];
|
||||||
|
}
|
80
hosts/modules/wg-home.nix
Normal file
80
hosts/modules/wg-home.nix
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (builtins) filter map;
|
||||||
|
inherit (lib) concatMap mapAttrsToList mkIf mkMerge mkOption optionalAttrs types;
|
||||||
|
cfg = config.sane.services.wg-home;
|
||||||
|
server-cfg = config.sane.hosts.by-name."servo".wg-home;
|
||||||
|
mkPeer = { ips, pubkey, endpoint }: {
|
||||||
|
publicKey = pubkey;
|
||||||
|
allowedIPs = map (k: "${k}/32") ips;
|
||||||
|
} // (optionalAttrs (endpoint != null) {
|
||||||
|
inherit endpoint;
|
||||||
|
# send keepalives every 25 seconds to keep NAT routes live.
|
||||||
|
# only need to do this from client -> server though, i think.
|
||||||
|
persistentKeepalive = 25;
|
||||||
|
# allows wireguard to notice DNS/hostname changes, with this much effective TTL.
|
||||||
|
dynamicEndpointRefreshSeconds = 600;
|
||||||
|
});
|
||||||
|
# make separate peers to route each given host
|
||||||
|
mkClientPeers = hosts: map (p: mkPeer {
|
||||||
|
inherit (p) pubkey endpoint;
|
||||||
|
ips = [ p.ip ];
|
||||||
|
}) hosts;
|
||||||
|
# make a single peer which routes all the given hosts
|
||||||
|
mkServerPeer = hosts: mkPeer {
|
||||||
|
inherit (server-cfg) pubkey endpoint;
|
||||||
|
ips = map (h: h.ip) hosts;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
sane.services.wg-home.enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
sane.services.wg-home.ip = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
# generate a (deterministic) wireguard private key
|
||||||
|
sane.derived-secrets."/run/wg-home.priv" = {
|
||||||
|
len = 32;
|
||||||
|
encoding = "base64";
|
||||||
|
};
|
||||||
|
|
||||||
|
# wireguard VPN which allows everything on my domain to speak to each other even when
|
||||||
|
# not behind a shared LAN.
|
||||||
|
# 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 ];
|
||||||
|
networking.wireguard.interfaces.wg-home = {
|
||||||
|
listenPort = 51820;
|
||||||
|
privateKeyFile = "/run/wg-home.priv";
|
||||||
|
preSetup =
|
||||||
|
let
|
||||||
|
gen-key = config.sane.fs."/run/wg-home.priv".unit;
|
||||||
|
in
|
||||||
|
"${pkgs.systemd}/bin/systemctl start '${gen-key}'";
|
||||||
|
|
||||||
|
ips = [
|
||||||
|
"${cfg.ip}/24"
|
||||||
|
];
|
||||||
|
|
||||||
|
peers =
|
||||||
|
let
|
||||||
|
all-peers = mapAttrsToList (_: hostcfg: hostcfg.wg-home) config.sane.hosts.by-name;
|
||||||
|
peer-list = filter (p: p.ip != null && p.ip != cfg.ip && p.pubkey != null) all-peers;
|
||||||
|
in
|
||||||
|
if cfg.ip == server-cfg.ip then
|
||||||
|
# if we're the server, then we maintain the entire client list
|
||||||
|
mkClientPeers peer-list
|
||||||
|
else
|
||||||
|
# but if we're a client, we maintain a single peer -- the server -- which does the actual routing
|
||||||
|
[ (mkServerPeer peer-list) ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user