Compare commits
1062 Commits
staging/im
...
staging/ni
Author | SHA1 | Date | |
---|---|---|---|
66156829d9 | |||
3c40fa6982 | |||
c1ddddddc0 | |||
aae118b476 | |||
7e402ce974 | |||
5b80308074 | |||
e5c94b410f | |||
209c18cb38 | |||
616a2dd19f | |||
5b0f898c62 | |||
a541e866a1 | |||
d3eb0bee26 | |||
2ca0f6ea62 | |||
66be38bfbf | |||
4785e54024 | |||
aecb55c79e | |||
1759d5a075 | |||
f50feb6c96 | |||
d2b50b53d4 | |||
4550299bdb | |||
67a23c01e9 | |||
077d11a0d6 | |||
49db12b8fd | |||
8cde4135b1 | |||
12cd61c9f7 | |||
c882fb673e | |||
19f022a682 | |||
839f51a6a2 | |||
9b2b261bd3 | |||
b2fe449c7f | |||
da5e3e6742 | |||
68763ade1f | |||
1fadd6b177 | |||
2ac9c98bc0 | |||
67b6dfc3d3 | |||
8dddf83eb7 | |||
e41ff28746 | |||
6d1baab11f | |||
a6f68ac90c | |||
3aa1a9f674 | |||
21d17c330f | |||
ae2e4931f3 | |||
c662936490 | |||
d6fb2ab5b4 | |||
8a28e347f5 | |||
a8eaaa4e7a | |||
0289dee658 | |||
c8aa6a057f | |||
dd17843c76 | |||
ae7e372b97 | |||
af9d435517 | |||
4d92458db3 | |||
19944c2a46 | |||
3b5d08f808 | |||
c748de74a0 | |||
951e3a617a | |||
11d5af99b2 | |||
7dadea94da | |||
abfd516025 | |||
e2e044a8f4 | |||
bacc17e333 | |||
6e483c9ed9 | |||
ace9d71d0e | |||
54c7d00621 | |||
ec77cdaa49 | |||
72e8d62145 | |||
6344c3da8b | |||
88f91bd2d4 | |||
dfc4ac2f86 | |||
43ec95f54a | |||
25f4661b29 | |||
56f7011ada | |||
85c8292f9a | |||
2db988b67c | |||
6301ea3a16 | |||
1596685d2b | |||
4f494228d3 | |||
12d120cd81 | |||
dc0c3ff887 | |||
aa3515ade2 | |||
16cee4e8d4 | |||
3a942ad8a4 | |||
8973cb22b7 | |||
e0bd579e44 | |||
a96e10617f | |||
14a4d8d577 | |||
3f9261d765 | |||
9b5c39e3c5 | |||
2e9eb51893 | |||
3135b92257 | |||
7ef504d14b | |||
fa952e076a | |||
bb7462523b | |||
44d3623165 | |||
42aca2483e | |||
998647c8b5 | |||
e24e76fd8f | |||
d3a7bfda7f | |||
76d875ef3c | |||
b74c4550d5 | |||
beef453802 | |||
2da544a39e | |||
32dcfde7e9 | |||
e0c2e8c149 | |||
95635be1d5 | |||
c2682fdbf3 | |||
d43d02bff5 | |||
4e6deae299 | |||
e850bb4f5f | |||
f76c180ed6 | |||
e8efc855bb | |||
7684ae91e0 | |||
b124035281 | |||
68bc670613 | |||
3881f79af0 | |||
a47e785ae7 | |||
f8d02687b9 | |||
23e39481a4 | |||
9769aea3b3 | |||
7bbec9d6f5 | |||
f8a2691ca0 | |||
d024637edf | |||
6501f4c0d7 | |||
c85a429388 | |||
99963c1133 | |||
5c52a25ccf | |||
4a782db808 | |||
f88bbfbb81 | |||
b403348e43 | |||
51ca72da84 | |||
38d921dbc9 | |||
fb427e55e8 | |||
bf56200345 | |||
7c31407ead | |||
b39a250e22 | |||
0822ed34d7 | |||
147b1c50b2 | |||
55875816d0 | |||
e25a4bbee6 | |||
dbb9e00bed | |||
6b1c3d02c1 | |||
4a448a1bf1 | |||
452a55c5e1 | |||
d10f70aff7 | |||
38423183ee | |||
5c3be90b82 | |||
eabeef9f30 | |||
f5dcca5166 | |||
d9a23dfc1b | |||
adb2162a9c | |||
ed020b56c0 | |||
ff01155efc | |||
af42cbd575 | |||
974656a80a | |||
318efe09e2 | |||
88bce722d5 | |||
74e3aa02b9 | |||
05ee8f92b3 | |||
a5fafee4dd | |||
4afdc11882 | |||
310f5982cb | |||
b6ae9f3646 | |||
0270ccdebd | |||
efd45c58f1 | |||
596aaf93f6 | |||
943008ae5b | |||
9d6629ad12 | |||
9e21101207 | |||
5997283cef | |||
3c2715648c | |||
265642c8da | |||
d7bed3bec2 | |||
079ab08642 | |||
e34c9cc190 | |||
6ff2c8acae | |||
04e8e72ae3 | |||
5b33c85e75 | |||
083d905f4c | |||
dd25c26845 | |||
3bdbd9db7b | |||
a077009064 | |||
46baec344d | |||
a23f5c148c | |||
ada8b75670 | |||
852a3e7686 | |||
6dbcc89c2e | |||
d661a0776a | |||
e71079b354 | |||
99eb0962ad | |||
9c79791428 | |||
f09a10a168 | |||
4ddf381d41 | |||
d5ffa6d796 | |||
24364992e1 | |||
b9afd1e340 | |||
5936ea5008 | |||
c4bf887fe6 | |||
20e2ff1fe7 | |||
59a2259105 | |||
bfcbea5ca1 | |||
0376b15a2f | |||
26c3441344 | |||
51c7ccd782 | |||
74ed7bff11 | |||
836b74991a | |||
fbae81eca7 | |||
89f28e63b4 | |||
f89f136041 | |||
d220aadc2d | |||
94a8c00a40 | |||
3e94a0d0f0 | |||
094356cae2 | |||
a78c516817 | |||
e0047150cc | |||
5bf80a701d | |||
b44c0e774e | |||
6b9bbe278f | |||
afdf3442b4 | |||
b5b32fde95 | |||
96eb427ea7 | |||
8ffb7b5893 | |||
1aed894d2e | |||
13ee861b0d | |||
35d6f40263 | |||
185f1f8f11 | |||
18ebfb9d9f | |||
a8584cf8dc | |||
57fcd33392 | |||
569a990488 | |||
915f792b74 | |||
897ba300b2 | |||
89f81da134 | |||
1b76f1d643 | |||
9f21fbceda | |||
ff081f3da6 | |||
b15fd0ced5 | |||
2450bb6f06 | |||
dc0ad98db6 | |||
7d581f93cc | |||
96d113ffac | |||
b247c920f6 | |||
dfa921035d | |||
0c59f4e59c | |||
3dda51db7d | |||
b5a6a7a57c | |||
f300cb1202 | |||
10a100c961 | |||
25d2234c69 | |||
fa5bc18721 | |||
7c1961eba8 | |||
b0c68308b7 | |||
6f7b7ddb84 | |||
1cc139c45c | |||
d06516a71b | |||
1c5a7b72ea | |||
afc916c9f8 | |||
7b141f6f58 | |||
94b7826099 | |||
fd82256bbc | |||
ec7f36913c | |||
6324d8004f | |||
4b8fddeb3f | |||
871975a597 | |||
1e6e41a9cb | |||
2f375b7778 | |||
df2e3a1b03 | |||
718a4b61d7 | |||
d617c0259f | |||
83e404f000 | |||
ba11bba909 | |||
af394b315e | |||
44195a7d87 | |||
44e356cf6b | |||
7aafc6719e | |||
f6579b865b | |||
8d5c917c79 | |||
4c74a95194 | |||
a6056aeb47 | |||
ac3e384b63 | |||
3338e93c87 | |||
97cb72db7c | |||
f7f6b80cd0 | |||
d60fe7a93c | |||
e2fa18b7c7 | |||
3226615885 | |||
dd99e66fb5 | |||
2e45145e72 | |||
9783646a0d | |||
c24f4d1659 | |||
f220771b58 | |||
cb9854c297 | |||
d422dcdd89 | |||
4e4e7e4991 | |||
9c09d03e5c | |||
1f0fbe29a8 | |||
131a828ed0 | |||
a4bcb44677 | |||
d385845dd5 | |||
66c42916c8 | |||
c6d4784dae | |||
b282e5beb2 | |||
20f4251c6e | |||
5d0630cad4 | |||
2dbf3b4732 | |||
8e8e63a33f | |||
6b7a8f9fec | |||
b85bdf26fd | |||
2fa76836b5 | |||
5c8cca6a52 | |||
1f2c9a9a5e | |||
337fb9e9d9 | |||
e7f02c057e | |||
8df87256a1 | |||
09a1d286d0 | |||
0662b06df6 | |||
b0a99da884 | |||
12fd7ebc41 | |||
f4a04ff6ba | |||
89e2a83067 | |||
ae78f2b6c2 | |||
198c40df66 | |||
a952f84ee4 | |||
c9e55a586b | |||
aa8c3affcd | |||
692f47d02d | |||
0ac17c32a3 | |||
2ff4df069e | |||
b11759a0a6 | |||
6af0d54e7b | |||
f87c115f7c | |||
099cd12bdd | |||
bf67def14a | |||
39e7e2230e | |||
4ff82f002b | |||
781a149542 | |||
b7f2f4f5c4 | |||
e3cb51951c | |||
94ac4ec0e9 | |||
348bd0f177 | |||
bae0e3df76 | |||
429951cfcc | |||
b23262b367 | |||
464e348545 | |||
62c1f4009b | |||
2373d28eb8 | |||
d76591349e | |||
4361bd45c7 | |||
be33684d5d | |||
d2ef8d113e | |||
54d29ca190 | |||
875482f395 | |||
dac245e032 | |||
e7edafcfec | |||
00af6104be | |||
40c9517dc6 | |||
c2915e29d4 | |||
b6edf768b9 | |||
27be182eb7 | |||
ddf1be7410 | |||
ad819e4cc0 | |||
6407f156b2 | |||
2f2c666b0b | |||
8760621440 | |||
0596b02f22 | |||
a5841192a2 | |||
f085c1d691 | |||
396d094520 | |||
6d419b8279 | |||
bf3e0ad790 | |||
0c07e03ad6 | |||
12f3fc333d | |||
4d96a1ed45 | |||
9aedb133bb | |||
5a15b76b61 | |||
5c17de6e83 | |||
8db4498ae8 | |||
001a5fc252 | |||
6f64e5d469 | |||
b1e9d8db80 | |||
5b39baf2db | |||
4e8ca1a30d | |||
1db3a29dac | |||
61ba1802ee | |||
059c4e9964 | |||
a09736e60b | |||
bdfdcfd164 | |||
7579d4b2c5 | |||
e90a8b7b6e | |||
50cec94164 | |||
5bb31aa5da | |||
2aef1c30bd | |||
471ef03289 | |||
bdcdba6a6d | |||
bf64948cc1 | |||
4331df28d2 | |||
2a148c1543 | |||
adf72fc9d4 | |||
96a66abcd5 | |||
8f40bdc9c0 | |||
3e782a5e73 | |||
f1b47e5de9 | |||
3c6c466d87 | |||
16bf03d8be | |||
ca1594a354 | |||
2e120f613f | |||
2c6f667a7e | |||
8e7586b902 | |||
7a0eed4ec3 | |||
ca1015d579 | |||
f89837f3aa | |||
2a1d6e1faa | |||
7918403d1b | |||
3fb76e720f | |||
a899cf6c9f | |||
40b26fc57e | |||
1be7119b73 | |||
4b41aa3718 | |||
71d6fe44a1 | |||
c5c1378f59 | |||
8fc57c4249 | |||
39eb1e3d07 | |||
e386406bc1 | |||
0cf4c3ff80 | |||
06e699a72b | |||
0c32f807e6 | |||
f6d3c102fa | |||
3e1a2243c7 | |||
4fe6f2aab3 | |||
dc1cd7a9a5 | |||
ead9fd87d7 | |||
4ac5c5f469 | |||
f3151320a3 | |||
403b177a80 | |||
f714235717 | |||
3ec01ba971 | |||
a51f8d45b3 | |||
cd375a9a05 | |||
0486c7f787 | |||
190571e565 | |||
94c31c4e8e | |||
e13af1c1c8 | |||
77587389c4 | |||
70d2d97525 | |||
65ed2afb23 | |||
b2419da057 | |||
243d38333d | |||
7ad75cacb9 | |||
6e9cd15517 | |||
9d052a62b4 | |||
862667648c | |||
2591314fdb | |||
dcd622bc1d | |||
e5cdcc4500 | |||
cb4ca7d26a | |||
9f5d1c0111 | |||
6fe29529b2 | |||
eae8ef11c8 | |||
edf21e6837 | |||
0ecc08b49d | |||
6eb8191514 | |||
3c6da51f84 | |||
6c10c14a32 | |||
8ae4be341a | |||
c94ed9d519 | |||
99373dcd83 | |||
98739bb061 | |||
46dabcd33f | |||
68d72eab16 | |||
f933581b0c | |||
1a639b320d | |||
c9ac005548 | |||
9a73293bd4 | |||
99e2ac1dbb | |||
a56b31cdac | |||
df9716e244 | |||
45f3d5a117 | |||
97a1b5732b | |||
59e4c84800 | |||
16e84cae9d | |||
d725dfb7f1 | |||
79b6c119ee | |||
be1d8c5d97 | |||
454e02c8ec | |||
3b37286e65 | |||
77388f35f6 | |||
a6c91db11b | |||
a96d0e9630 | |||
43f39674d6 | |||
d7fd7d7368 | |||
386c712a23 | |||
9d09a323be | |||
9beb6b52e5 | |||
f96f2ec960 | |||
fd080393f8 | |||
408cfc08a1 | |||
d34a03e060 | |||
8230389b21 | |||
6a735cc0bc | |||
fbc79d2527 | |||
76963d6aaf | |||
7f74951fb3 | |||
d698c7ca70 | |||
8e865999f8 | |||
f7b5423338 | |||
1ec3e1fb1c | |||
8346d21d42 | |||
3ed8e0cb44 | |||
583fcbce6e | |||
4a7513ba23 | |||
b51b01ff02 | |||
f9ceb7d8fd | |||
1a1bef5948 | |||
0625eb1bf8 | |||
b722a4bcc8 | |||
c744b976d0 | |||
8352d3aa8f | |||
dfebedbd6c | |||
3caa072d00 | |||
4ee31d075a | |||
d973cb939c | |||
78ab7b0b80 | |||
2fcb0ebfd0 | |||
7445adbea0 | |||
706cf3bac2 | |||
4b722a6c30 | |||
8350386ea8 | |||
0ee0b3c3bb | |||
8ce1fae67b | |||
f27202056e | |||
7f38cd7535 | |||
b56507d4c2 | |||
aab2a9cd26 | |||
b7c2dfea19 | |||
f1709c0355 | |||
7a67f3ed0f | |||
91054159d3 | |||
0eedcd0114 | |||
9305566330 | |||
0abbd006fc | |||
9d31a462a8 | |||
1c8659d145 | |||
503f097272 | |||
a55e8847ec | |||
2937cbc67a | |||
c92e67bda1 | |||
652e4ca93b | |||
07d3f60f26 | |||
cb20b4a56b | |||
0da3edfa52 | |||
9477160a2d | |||
b77bde5417 | |||
d2a3bec605 | |||
b519de1d6f | |||
1c867c5160 | |||
f8ab8b290e | |||
c8a8fe73ca | |||
03d7cf65a4 | |||
8ddfa91125 | |||
415a2e1a67 | |||
f4a1ede7d4 | |||
478002766e | |||
290a15e517 | |||
e923636181 | |||
017aa335b1 | |||
58b219546b | |||
499078e0f8 | |||
82d3e9686d | |||
02df87fc51 | |||
33ff993981 | |||
976f48268d | |||
ec26f11db4 | |||
15755a8a71 | |||
02067db774 | |||
e69734250e | |||
f78a02700f | |||
d776c4618a | |||
50812e5678 | |||
86293377d7 | |||
14922a40b2 | |||
e6a6d35adf | |||
5777e1a6e4 | |||
635a4b958b | |||
99c4fedbdc | |||
e70e8e144b | |||
aad572a058 | |||
4a886b9e9b | |||
ce60270821 | |||
8929311732 | |||
fdec1817c4 | |||
6cbeccf51f | |||
7491114915 | |||
5715795d1f | |||
bffe39b6b5 | |||
8b2a7d5fb4 | |||
251297b62e | |||
0e70f516b7 | |||
8ecdaa0a64 | |||
af5c0d0648 | |||
87ec775ddb | |||
71028911e3 | |||
5de54acd90 | |||
d54d1b9295 | |||
b740af17cd | |||
40e7d8a689 | |||
2f16e802d8 | |||
b048b47d54 | |||
bcfd8e1725 | |||
e0a6f8ea4a | |||
80f3d0472b | |||
b6685c9e6c | |||
0c2d8af448 | |||
7ce0c34f43 | |||
f2e8be3bd1 | |||
9b2e7b02cc | |||
1b3e0b95be | |||
f78968c73a | |||
d5d755a4b2 | |||
e08281c380 | |||
afb006f6ec | |||
a76cf03232 | |||
9c24f24306 | |||
736999eea6 | |||
979ed38506 | |||
46285852d0 | |||
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 | |||
110ab1a794 | |||
7d5a81e542 | |||
1af2a3f329 | |||
3fa9e910a9 | |||
6befc40700 | |||
29db2d8dc5 | |||
36d8052982 | |||
48115231a3 | |||
8b56ddd1ca | |||
c1457f5bfb | |||
7dfaf77a71 | |||
72dc7029e6 | |||
95f3215b00 | |||
baac8df8c2 | |||
dc6a08a12b | |||
2413e2eb5f | |||
7327128493 | |||
ed8059f4c4 | |||
3a72295610 | |||
e6d9edf27d | |||
78782d5f7e | |||
91275f3723 | |||
8115edea8d | |||
4c475bbf9c | |||
7040e1f07c | |||
aafa64942c | |||
a44a99e371 | |||
a7ff90c843 | |||
d4996d6f31 | |||
bd5209c655 | |||
9588108fd5 | |||
942e302afb | |||
2bd98e6764 | |||
7b9910f287 | |||
917afe209e | |||
cc5cf9b6f4 | |||
57d95dd298 | |||
0b78df53be | |||
c8dcb4ac59 | |||
241f4ae58f | |||
965d7eedbb | |||
cdc881e887 | |||
33967554a5 | |||
5af55ecdbf | |||
6ca3e7086e | |||
ca62f1b62f | |||
eef66df36d | |||
9ca6a1c907 | |||
dbb78088f4 | |||
f17ae1ca7b | |||
b2774a4004 | |||
0ae548d47c | |||
760505db20 | |||
71fc1a2fd7 | |||
a457fc1416 | |||
2c0b0f6947 | |||
f10de6c2c4 | |||
a6be200a82 | |||
fb57e9aa5b | |||
f5acbbd830 | |||
af77417531 | |||
eea80b575d | |||
6a209d27fd | |||
e8f778fecd | |||
488036beb3 | |||
00b681eca5 | |||
72d589cb2d | |||
ea5552daa7 | |||
fb7d94209c | |||
8f5b92685b | |||
32a4cb19fd | |||
031cfa2bcd | |||
e93fbea1e6 | |||
85a2fbc38a | |||
9e902c8eb2 | |||
dc15091ea7 | |||
c063ecd047 | |||
70a43c770d | |||
cc9e2d8e15 | |||
bb41fb95fe | |||
d852adf806 | |||
5443542cba | |||
81effb01a3 | |||
83f416999f | |||
dd34883246 | |||
e47f9e38ce | |||
0f0b728911 | |||
1839f87a4e | |||
53edf4e6af | |||
fb6e0ddb34 | |||
0a48d79174 | |||
b6208e1a19 | |||
e46ab4ec14 | |||
19c254c266 | |||
1d0cadce85 | |||
e8342b8044 | |||
40e642bfc3 | |||
f008565e22 | |||
4ea2835d9d | |||
493d317bb1 | |||
e446bfba58 | |||
a7bac5de18 | |||
b0950e90f4 | |||
d8cd0e1f57 | |||
fd7d67ee05 | |||
1a712b4d47 | |||
4520e1d1f5 | |||
841a2a3bcb | |||
fe816e9110 | |||
426e0c3ae2 | |||
a95b91a556 | |||
837e5438c3 | |||
8217b22c86 | |||
0b35ce4dec | |||
413f9a171b | |||
43a46af43b | |||
1a0f05bfd6 | |||
c18dd9636d | |||
0977721af5 | |||
122d3cd7e4 | |||
cd5f8054c0 | |||
3db388b105 | |||
2ba6116f10 | |||
592d17b725 | |||
4d9c15f9b8 | |||
abced7dd0d | |||
5c42365912 | |||
247ad326b2 | |||
170008f345 | |||
2c48e61854 | |||
f89f756489 | |||
c0da19951b | |||
5fb67306e4 | |||
5533b586d7 | |||
68c2eb7363 | |||
fd79026366 | |||
a76471cb1f | |||
c94b8299a6 | |||
175bc0709f | |||
7b02477486 | |||
d7c8638fea | |||
9d7d1acc80 | |||
787857d27f | |||
9c248a8a31 | |||
829680fb00 | |||
a9ee26388c | |||
2960b895b6 | |||
933063115b | |||
afe684ca2c | |||
93f1411522 | |||
01e44c1f7f | |||
618e9bd2fa | |||
fbc39d0584 | |||
2d7b3750cd | |||
e6ccd2e4f7 | |||
d4bf491e9c | |||
5a2bbcce3b | |||
327e6b536f | |||
bace7403e7 | |||
57f5521ef3 | |||
9e32211c12 | |||
edf6bd4455 | |||
a9a14786f9 | |||
eade5fe16e | |||
be222c1d70 | |||
88a33dd5de | |||
875e923197 | |||
54dd643cf0 | |||
3c726f148b | |||
e225e2e704 | |||
cf0bf8190e | |||
b8f7f68d4c | |||
7a3aae8c97 | |||
89e519810d | |||
0e920230ba | |||
6ffae00e17 | |||
be19985440 | |||
f7e3e7294a | |||
d745e3c1ee | |||
c1890ce82b | |||
53a0b621d8 | |||
aeb2f63d65 | |||
528ffdb58e | |||
b6887b305e | |||
08dfc80c98 |
@@ -8,7 +8,7 @@ keys:
|
||||
- &host_servo age1tzlyex2z6t88tg9h82943e39shxhmqeyr7ywhlwpdjmyqsndv3qq27x0rf
|
||||
- &host_moby age18vq5ktwgeaysucvw9t67drqmg5zd5c5k3le34yqxckkfj7wqdqgsd4ejmt
|
||||
creation_rules:
|
||||
- path_regex: secrets/universal*
|
||||
- path_regex: secrets/common*
|
||||
key_groups:
|
||||
- age:
|
||||
- *user_desko_colin
|
||||
@@ -26,19 +26,19 @@ creation_rules:
|
||||
- *user_lappy_colin
|
||||
- *user_servo_colin
|
||||
- *host_servo
|
||||
- path_regex: secrets/desko.yaml$
|
||||
- path_regex: secrets/desko*
|
||||
key_groups:
|
||||
- age:
|
||||
- *user_desko_colin
|
||||
- *user_lappy_colin
|
||||
- *host_desko
|
||||
- path_regex: secrets/lappy.yaml$
|
||||
- path_regex: secrets/lappy*
|
||||
key_groups:
|
||||
- age:
|
||||
- *user_lappy_colin
|
||||
- *user_desko_colin
|
||||
- *host_lappy
|
||||
- path_regex: secrets/moby.yaml$
|
||||
- path_regex: secrets/moby*
|
||||
key_groups:
|
||||
- age:
|
||||
- *user_desko_colin
|
||||
|
108
README.md
Normal file
108
README.md
Normal file
@@ -0,0 +1,108 @@
|
||||
## What's Here
|
||||
|
||||
this is the top-level repo from which i configure/deploy all my NixOS machines:
|
||||
- desktop
|
||||
- laptop
|
||||
- server
|
||||
- mobile phone
|
||||
|
||||
i enjoy a monorepo approach. this repo references [nixpkgs][nixpkgs], a couple 3rd party
|
||||
nix modules like [sops][sops], the sources for [uninsane.org][uninsane-org], and that's
|
||||
about it. custom derivations and modules (some of which i try to upstream) live
|
||||
directly here; even the sources for those packages is often kept here too.
|
||||
|
||||
[nixpkgs]: https://github.com/NixOS/nixpkgs
|
||||
[sops]: https://github.com/Mic92/sops-nix
|
||||
[uninsane-org]: https://uninsane.org
|
||||
|
||||
## Layout
|
||||
- `hosts/`
|
||||
- the bulk of config which isn't factored with external use in mind.
|
||||
- that is, if you were to add this repo to a flake.nix for your own use,
|
||||
you won't likely be depending on anything in this directory.
|
||||
- `integrations/`
|
||||
- code intended for consumption by external tools (e.g. the Nix User Repos)
|
||||
- `modules/`
|
||||
- config which is gated behind `enable` flags, in similar style to nixpkgs'
|
||||
`nixos/` directory.
|
||||
- if you depend on this repo, it's most likely for something in this directory.
|
||||
- `nixpatches/`
|
||||
- literally, diffs i apply atop upstream nixpkgs before performing further eval.
|
||||
- `overlays/`
|
||||
- exposed via the `overlays` output in `flake.nix`.
|
||||
- predominantly a list of `callPackage` directives.
|
||||
- `pkgs/`
|
||||
- derivations for things not yet packaged in nixpkgs.
|
||||
- derivations for things from nixpkgs which i need to `override` for some reason.
|
||||
- inline code for wholly custom packages (e.g. `pkgs/additional/sane-scripts/` for CLI tools
|
||||
that are highly specific to my setup).
|
||||
- `scripts/`
|
||||
- scripts which are referenced by other things in this repo.
|
||||
- these aren't generally user-facing, but they're factored out so that they can
|
||||
be invoked directly when i need to debug.
|
||||
- `secrets/`
|
||||
- encrypted keys, API tokens, anything which one or more of my machines needs
|
||||
read access to but shouldn't be world-readable.
|
||||
- not much to see here
|
||||
- `templates/`
|
||||
- exposed via the `templates` output in `flake.nix`.
|
||||
- used to instantiate short-lived environments.
|
||||
- used to auto-fill the boiler-plate portions of new packages.
|
||||
|
||||
|
||||
## Key Points of Interest
|
||||
|
||||
i.e. you might find value in using these in your own config:
|
||||
|
||||
- `modules/fs/`
|
||||
- use this to statically define leafs and nodes anywhere in the filesystem,
|
||||
not just inside `/nix/store`.
|
||||
- e.g. specify that `/var/www` should be:
|
||||
- owned by a specific user/group
|
||||
- set to a specific mode
|
||||
- symlinked to some other path
|
||||
- populated with some statically-defined data
|
||||
- populated according to some script
|
||||
- created as a dependency of some service (e.g. `nginx`)
|
||||
- values defined here are applied neither at evaluation time _nor_ at activation time.
|
||||
- rather, they become systemd services.
|
||||
- systemd manages dependencies
|
||||
- e.g. link `/var/www -> /mnt/my-drive/www` only _after_ `/mnt/my-drive/www` appears)
|
||||
- this is akin to using [Home Manager's][home-manager] file API -- the part which lets you
|
||||
statically define `~/.config` files -- just with a different philosophy.
|
||||
- `modules/persist/`
|
||||
- my alternative to the Impermanence module.
|
||||
- this builds atop `modules/fs/` to achieve things stock impermanence can't:
|
||||
- persist things to encrypted storage which is unlocked at login time (pam_mount).
|
||||
- "persist" cache directories -- to free up RAM -- but auto-wipe them on mount
|
||||
and encrypt them to ephemeral keys so they're unreadable post shutdown/unmount.
|
||||
- `modules/programs.nix`
|
||||
- like nixpkgs' `programs` options, but allows both system-wide or per-user deployment.
|
||||
- allows `fs` and `persist` config values to be gated behind program deployment:
|
||||
- e.g. `/home/<user>/.mozilla/firefox` is persisted only for users who
|
||||
`sane.programs.firefox.enableFor.user."<user>" = true;`
|
||||
- `modules/users.nix`
|
||||
- convenience layer atop the above modules so that you can just write
|
||||
`fs.".config/git"` instead of `fs."/home/colin/.config/git"`
|
||||
|
||||
some things in here could easily find broader use. if you would find benefit in
|
||||
them being factored out of my config, message me and we could work to make that happen.
|
||||
|
||||
[home-manager]: https://github.com/nix-community/home-manager
|
||||
|
||||
## Using This Repo In Your Own Config
|
||||
|
||||
this should be a pretty "standard" flake. just reference it, and import either
|
||||
- `nixosModules.sane` (for the modules)
|
||||
- `overlays.pkgs` (for the packages)
|
||||
|
||||
## Mirrors
|
||||
|
||||
this repo exists in a few known locations:
|
||||
- primary: <https://git.uninsane.org/colin/nix-files>
|
||||
- mirror: <https://github.com/nix-community/nur-combined/tree/master/repos/colinsane>
|
||||
|
||||
## Contact
|
||||
|
||||
if you want to contact me for questions, or collaborate to split something useful into a shared repo, etc,
|
||||
you can reach me via any method listed [here](https://uninsane.org/about).
|
73
TODO.md
Normal file
73
TODO.md
Normal file
@@ -0,0 +1,73 @@
|
||||
## BUGS
|
||||
- why i need to manually restart `wireguard-wg-ovpns` on servo periodically
|
||||
- else DNS fails
|
||||
|
||||
## REFACTORING:
|
||||
### sops/secrets
|
||||
- attach secrets to the thing they're used by (sane.programs)
|
||||
- rework secrets to leverage `sane.fs`
|
||||
- remove sops activation script as it's covered by my systemd sane.fs impl
|
||||
|
||||
### roles
|
||||
- allow any host to take the role of `uninsane.org`
|
||||
- will make it easier to test new services?
|
||||
|
||||
### upstreaming
|
||||
- bump nodejs version in lemmy-ui
|
||||
- add updateScripts to all my packages in nixpkgs
|
||||
- fix lightdm-mobile-greeter for newer libhandy
|
||||
- port zecwallet-lite to a from-source build
|
||||
- fix or abandon Whalebird
|
||||
|
||||
|
||||
## IMPROVEMENTS:
|
||||
### security/resilience
|
||||
- validate duplicity backups!
|
||||
- encrypt more ~ dirs (~/archives, ~/records, ..?)
|
||||
- best to do this after i know for sure i have good backups
|
||||
- have `sane.programs` be wrapped such that they run in a cgroup?
|
||||
- at least, only give them access to the portion of the fs they *need*.
|
||||
- Android takes approach of giving each app its own user: could hack that in here.
|
||||
- canaries for important services
|
||||
- e.g. daily email checks; daily backup checks
|
||||
|
||||
### user experience
|
||||
- firefox/librewolf: don't show browserpass/sponsorblock/metamask "first run" on every boot
|
||||
- moby: improve gPodder launch time
|
||||
- moby: replace jellyfin-desktop with jellyfin-vue?
|
||||
- allows (maybe) to cache media for offline use
|
||||
- "newer" jellyfin client
|
||||
- not packaged for nix
|
||||
- find a nice desktop ActivityPub client
|
||||
- package Nix/NixOS docs for Zeal
|
||||
- install [doc-browser](https://github.com/qwfy/doc-browser)
|
||||
- this supports both dash (zeal) *and* the datasets from <https://devdocs.io> (which includes nix!)
|
||||
- install [devhelp](https://wiki.gnome.org/Apps/Devhelp) (gnome)
|
||||
- auto-mount servo
|
||||
- have xdg-open parse `<repo:...> URIs (or adjust them so that it _can_ parse)
|
||||
- `sane.programs`: auto-populate defaults with everything from `pkgs`
|
||||
- zsh: disable "command not found" corrections
|
||||
- sxmo: allow rotation to the upside-down position
|
||||
- see: <repo:mil/sxmo-utils:scripts/core/sxmo_autorotate.sh>
|
||||
- all orientations *except* upside down are supported
|
||||
- sxmo: launch with auto-rotation enabled
|
||||
|
||||
### perf
|
||||
- why does nixos-rebuild switch take 5 minutes when net is flakey?
|
||||
- trying to auto-mount servo?
|
||||
- something to do with systemd services restarting/stalling
|
||||
- maybe wireguard & its refresh operation, specifically?
|
||||
- fix OOM for large builds like webkitgtk
|
||||
- these use significant /tmp space.
|
||||
- either place /tmp on encrypted-cleared-at-boot storage
|
||||
- which probably causes each CPU load for the encryption
|
||||
- **or set up encrypted swap**
|
||||
- encrypted swap could remove the need for my encrypted-cleared-at-boot stuff
|
||||
|
||||
|
||||
## NEW FEATURES:
|
||||
- add a FTP-accessible file share to servo
|
||||
- just /var/www?
|
||||
- migrate MAME cabinet to nix
|
||||
- boot it from PXE from servo?
|
||||
- enable IPv6
|
141
flake.lock
generated
141
flake.lock
generated
@@ -2,11 +2,11 @@
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1659877975,
|
||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||
"lastModified": 1678901627,
|
||||
"narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||
"rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -15,50 +15,14 @@
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"impermanence": {
|
||||
"locked": {
|
||||
"lastModified": 1668668915,
|
||||
"narHash": "sha256-QjY4ZZbs9shwO4LaLpvlU2bO9J1juYhO9NtV3nrbnYQ=",
|
||||
"owner": "nix-community",
|
||||
"repo": "impermanence",
|
||||
"rev": "5df9108b346f8a42021bf99e50de89c9caa251c3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "impermanence",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"mobile-nixos": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1670131242,
|
||||
"narHash": "sha256-T/o1/3gffr010fsqgNshs1NJJjsnUYvQnUZgm6hilsY=",
|
||||
"lastModified": 1683422260,
|
||||
"narHash": "sha256-79zaClbubRkBNlJ04OSADILuLQHH48N5fu296hEWYlw=",
|
||||
"owner": "nixos",
|
||||
"repo": "mobile-nixos",
|
||||
"rev": "5ee45cc1f8e43f4af14ee17ccef9156b0db8cd77",
|
||||
"rev": "ba4638836e94a8f16d1d1f9e8c0530b86078029c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -67,43 +31,46 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-serve": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1684319086,
|
||||
"narHash": "sha256-5wwlkWqP1cQUPXp/PJsi09FkgAule5yBghngRZZbUQg=",
|
||||
"owner": "edolstra",
|
||||
"repo": "nix-serve",
|
||||
"rev": "e6e3d09438e803daa5374ad8edf1271289348456",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "nix-serve",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1671722432,
|
||||
"narHash": "sha256-ojcZUekIQeOZkHHzR81st7qxX99dB1Eaaq6PU5MNeKc=",
|
||||
"lastModified": 1606086654,
|
||||
"narHash": "sha256-VFl+3eGIMqNp7cyOMJ6TjM/+UcsLKtodKoYexrlTJMI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "652e92b8064949a11bc193b90b74cb727f2a1405",
|
||||
"rev": "19db3e5ea2777daa874563b5986288151f502e27",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-unstable",
|
||||
"ref": "nixos-20.09",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1671883564,
|
||||
"narHash": "sha256-C15oAtyupmLB3coZY7qzEHXjhtUx/+77olVdqVMruAg=",
|
||||
"lastModified": 1684632198,
|
||||
"narHash": "sha256-SdxMPd0WmU9MnDBuuy7ouR++GftrThmSGL7PCQj/uVI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "dac57a4eccf1442e8bf4030df6fcbb55883cb682",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-22.11",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable_2": {
|
||||
"locked": {
|
||||
"lastModified": 1671923641,
|
||||
"narHash": "sha256-flPauiL5UrfRJD+1oAcEefpEIUqTqnyKScWe/UUU+lE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "939c05a176b8485971463c18c44f48e56a7801c9",
|
||||
"rev": "d0dade110dc7072d67ce27826cfe9ab2ab0cf247",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -113,30 +80,44 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-unpatched": {
|
||||
"locked": {
|
||||
"lastModified": 1684935479,
|
||||
"narHash": "sha256-6QMMsXMr2nhmOPHdti2j3KRHt+bai2zw+LJfdCl97Mk=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "f91ee3065de91a3531329a674a45ddcb3467a650",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"home-manager": "home-manager",
|
||||
"impermanence": "impermanence",
|
||||
"mobile-nixos": "mobile-nixos",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-stable": "nixpkgs-stable",
|
||||
"nix-serve": "nix-serve",
|
||||
"nixpkgs-unpatched": "nixpkgs-unpatched",
|
||||
"sops-nix": "sops-nix",
|
||||
"uninsane": "uninsane"
|
||||
"uninsane-dot-org": "uninsane-dot-org"
|
||||
}
|
||||
},
|
||||
"sops-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
"nixpkgs-unpatched"
|
||||
],
|
||||
"nixpkgs-stable": "nixpkgs-stable_2"
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1671937829,
|
||||
"narHash": "sha256-YtaNB+mLw0d67JFYNjRWM+/AL3JCXuD/DGlnTlyX1tY=",
|
||||
"lastModified": 1684637723,
|
||||
"narHash": "sha256-0vAxL7MVMhGbTkAyvzLvleELHjVsaS43p+PR1h9gzNQ=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "855b8d51fc3991bd817978f0f093aa6ae0fae738",
|
||||
"rev": "4ccdfb573f323a108a44c13bb7730e42baf962a9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -145,19 +126,19 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"uninsane": {
|
||||
"uninsane-dot-org": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
"nixpkgs-unpatched"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1666870107,
|
||||
"narHash": "sha256-b9eXZxSwhzdJI5uQgfrMhu4SY2POrPkinUg7F5gQVYo=",
|
||||
"lastModified": 1684528780,
|
||||
"narHash": "sha256-QdYxjcTCCLPv++1v9tJBL98nn/AFx0fmzlgzcLK6KRE=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "80c6ec95bd430e29d231cf745f19279bb76fb382",
|
||||
"revCount": 164,
|
||||
"rev": "f3747a1dad3d34880613821faf26357ba432d3d7",
|
||||
"revCount": 194,
|
||||
"type": "git",
|
||||
"url": "https://git.uninsane.org/colin/uninsane"
|
||||
},
|
||||
|
368
flake.nix
368
flake.nix
@@ -1,94 +1,155 @@
|
||||
# docs:
|
||||
# - <https://nixos.wiki/wiki/Flakes>
|
||||
# FLAKE FEEDBACK:
|
||||
# - 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>
|
||||
#
|
||||
#
|
||||
# COMMON OPERATIONS:
|
||||
# - update a specific flake input:
|
||||
# - `nix flake lock --update-input nixpkgs`
|
||||
|
||||
{
|
||||
# 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 = {
|
||||
nixpkgs-stable.url = "nixpkgs/nixos-22.11";
|
||||
nixpkgs.url = "nixpkgs/nixos-unstable";
|
||||
# <https://github.com/nixos/nixpkgs/tree/nixos-22.11>
|
||||
# nixpkgs-stable.url = "github:nixos/nixpkgs?ref=nixos-22.11";
|
||||
|
||||
# branch workflow:
|
||||
# - daily:
|
||||
# - nixos-unstable cut from master after enough packages have been built in caches.
|
||||
# - every 6 hours:
|
||||
# - master auto-merged into staging.
|
||||
# - staging-next auto-merged into staging.
|
||||
# - manually, approximately once per month:
|
||||
# - staging-next is cut from staging.
|
||||
# - staging-next merged into master.
|
||||
#
|
||||
# which branch to source from?
|
||||
# - for everyday development, prefer `nixos-unstable` branch, as it provides good caching.
|
||||
# - if need to test bleeding updates (e.g. if submitting code into staging):
|
||||
# - use `staging-next` if it's been cut (i.e. if there's an active staging-next -> master PR)
|
||||
# - use `staging` if no staging-next branch has been cut.
|
||||
#
|
||||
# <https://github.com/nixos/nixpkgs/tree/nixos-unstable>
|
||||
nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||
# nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=staging-next";
|
||||
# nixpkgs-unpatched.url = "github:nixos/nixpkgs?ref=staging";
|
||||
|
||||
mobile-nixos = {
|
||||
# <https://github.com/nixos/mobile-nixos>
|
||||
url = "github:nixos/mobile-nixos";
|
||||
flake = false;
|
||||
};
|
||||
home-manager = {
|
||||
url = "github:nix-community/home-manager/release-22.05";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
sops-nix = {
|
||||
# <https://github.com/Mic92/sops-nix>
|
||||
url = "github:Mic92/sops-nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
# inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unpatched";
|
||||
};
|
||||
impermanence.url = "github:nix-community/impermanence";
|
||||
uninsane = {
|
||||
uninsane-dot-org = {
|
||||
url = "git+https://git.uninsane.org/colin/uninsane";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
# inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unpatched";
|
||||
};
|
||||
nix-serve = {
|
||||
# <https://github.com/edolstra/nix-serve>
|
||||
url = "github:edolstra/nix-serve";
|
||||
};
|
||||
};
|
||||
|
||||
outputs = {
|
||||
self,
|
||||
nixpkgs,
|
||||
nixpkgs-stable,
|
||||
nixpkgs-unpatched,
|
||||
mobile-nixos,
|
||||
home-manager,
|
||||
sops-nix,
|
||||
impermanence,
|
||||
uninsane
|
||||
}: let
|
||||
patchedPkgs = system: nixpkgs.legacyPackages.${system}.applyPatches {
|
||||
name = "nixpkgs-patched-uninsane";
|
||||
src = nixpkgs;
|
||||
patches = import ./nixpatches/list.nix {
|
||||
inherit (nixpkgs.legacyPackages.${system}) fetchpatch;
|
||||
inherit (nixpkgs.lib) fakeHash;
|
||||
};
|
||||
};
|
||||
# return something which behaves like `pkgs`, for the provided system
|
||||
# `local` = architecture of builder. `target` = architecture of the system beying deployed to
|
||||
nixpkgsFor = local: target: import (patchedPkgs target) { crossSystem = target; localSystem = local; };
|
||||
# evaluate ONLY our overlay, for the provided system
|
||||
customPackagesFor = local: target: import ./pkgs/overlay.nix (nixpkgsFor local target) (nixpkgsFor local target);
|
||||
decl-host = { name, local, target }:
|
||||
uninsane-dot-org,
|
||||
nix-serve,
|
||||
...
|
||||
}@inputs:
|
||||
let
|
||||
nixosSystem = import ((patchedPkgs target) + "/nixos/lib/eval-config.nix");
|
||||
in (nixosSystem {
|
||||
# by default the local system is the same as the target, employing emulation when they differ
|
||||
system = target;
|
||||
specialArgs = { inherit mobile-nixos home-manager impermanence; };
|
||||
modules = [
|
||||
./modules
|
||||
(import ./hosts/instantiate.nix name)
|
||||
home-manager.nixosModule
|
||||
impermanence.nixosModule
|
||||
sops-nix.nixosModules.sops
|
||||
{
|
||||
nixpkgs.overlays = [
|
||||
(import "${mobile-nixos}/overlay/overlay.nix")
|
||||
uninsane.overlay
|
||||
(import ./pkgs/overlay.nix)
|
||||
(next: prev: rec {
|
||||
# non-emulated packages build *from* local *for* target.
|
||||
# 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.
|
||||
cross = (nixpkgsFor local target) // (customPackagesFor local target);
|
||||
stable = import nixpkgs-stable { system = target; };
|
||||
inherit (builtins) attrNames elem listToAttrs map mapAttrs;
|
||||
mapAttrs' = f: set:
|
||||
listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
|
||||
# mapAttrs but without the `name` argument
|
||||
mapAttrValues = f: mapAttrs (_: f);
|
||||
# rather than apply our nixpkgs patches as a flake input, do that here instead.
|
||||
# this (temporarily?) resolves the bad UX wherein a subflake residing in the same git
|
||||
# repo as the main flake causes the main flake to have an unstable hash.
|
||||
nixpkgs = (import ./nixpatches/flake.nix).outputs {
|
||||
self = nixpkgs;
|
||||
nixpkgs = nixpkgs-unpatched;
|
||||
};
|
||||
|
||||
# cross-compatible packages
|
||||
# gocryptfs = cross.gocryptfs;
|
||||
nixpkgsCompiledBy = system: nixpkgs.legacyPackages."${system}";
|
||||
|
||||
# pinned packages:
|
||||
# 2022/12/13: grpc does not build on aarch64-linux. https://github.com/NixOS/nixpkgs/issues/205887
|
||||
grpc = stable.grpc;
|
||||
# depends on grpc, so pinned.
|
||||
duplicity = stable.duplicity;
|
||||
evalHost = { name, local, target }: nixpkgs.lib.nixosSystem {
|
||||
system = target;
|
||||
modules = [
|
||||
(import ./hosts/instantiate.nix { localSystem = local; hostName = name; })
|
||||
self.nixosModules.default
|
||||
self.nixosModules.passthru
|
||||
{
|
||||
nixpkgs.overlays = [
|
||||
self.overlays.passthru
|
||||
self.overlays.sane-all
|
||||
];
|
||||
}
|
||||
({ lib, ... }: {
|
||||
# TODO: does the earlier `system` arg to nixosSystem make its way here?
|
||||
nixpkgs.hostPlatform.system = target;
|
||||
# nixpkgs.buildPlatform = local; # set by instantiate.nix instead
|
||||
# nixpkgs.config.replaceStdenv = { pkgs }: pkgs.ccacheStdenv;
|
||||
})
|
||||
];
|
||||
};
|
||||
in {
|
||||
nixosConfigurations =
|
||||
let
|
||||
hosts = {
|
||||
servo = { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
desko = { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
lappy = { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
moby = { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
|
||||
rescue = { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
};
|
||||
# cross-compiled builds: instead of emulating the host, build using a cross-compiler.
|
||||
# - these are faster to *build* than the emulated variants (useful when tweaking packages),
|
||||
# - but fewer of their packages can be found in upstream caches.
|
||||
cross = mapAttrValues evalHost hosts;
|
||||
emulated = mapAttrValues
|
||||
({name, local, target}: evalHost {
|
||||
inherit name target;
|
||||
local = null;
|
||||
})
|
||||
];
|
||||
}
|
||||
];
|
||||
});
|
||||
hosts;
|
||||
prefixAttrs = prefix: attrs: mapAttrs'
|
||||
(name: value: {
|
||||
name = prefix + name;
|
||||
inherit value;
|
||||
})
|
||||
attrs;
|
||||
in
|
||||
(prefixAttrs "cross-" cross) //
|
||||
(prefixAttrs "emulated-" emulated) // {
|
||||
# prefer native builds for these machines:
|
||||
inherit (emulated) servo desko lappy rescue;
|
||||
# prefer cross-compiled builds for these machines:
|
||||
inherit (cross) moby;
|
||||
};
|
||||
|
||||
decl-bootable-host = { name, local, target }: rec {
|
||||
nixosConfiguration = decl-host { inherit name local target; };
|
||||
# unofficial output
|
||||
# this produces a EFI-bootable .img file (GPT with a /boot partition and a system (/ or /nix) partition).
|
||||
# after building this:
|
||||
# - flash it to a bootable medium (SD card, flash drive, HDD)
|
||||
@@ -102,40 +163,149 @@
|
||||
# - if fs wasn't resized automatically, then `sudo btrfs filesystem resize max /`
|
||||
# - checkout this flake into /etc/nixos AND UPDATE THE FS UUIDS.
|
||||
# - `nixos-rebuild --flake './#<host>' switch`
|
||||
img = nixosConfiguration.config.system.build.img;
|
||||
};
|
||||
hosts.servo = decl-bootable-host { name = "servo"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
hosts.desko = decl-bootable-host { name = "desko"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
hosts.lappy = decl-bootable-host { name = "lappy"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
hosts.moby = decl-bootable-host { name = "moby"; local = "aarch64-linux"; target = "aarch64-linux"; };
|
||||
# special cross-compiled variant, to speed up deploys from an x86 box to the arm target
|
||||
# note that these *do* produce different store paths, because the closure for the tools used to cross compile
|
||||
# v.s. emulate differ.
|
||||
# so deploying foo-cross and then foo incurs some rebuilding.
|
||||
hosts.moby-cross = decl-bootable-host { name = "moby"; local = "x86_64-linux"; target = "aarch64-linux"; };
|
||||
hosts.rescue = decl-bootable-host { name = "rescue"; local = "x86_64-linux"; target = "x86_64-linux"; };
|
||||
in {
|
||||
nixosConfigurations = builtins.mapAttrs (name: value: value.nixosConfiguration) hosts;
|
||||
imgs = builtins.mapAttrs (name: value: value.img) hosts;
|
||||
packages = let
|
||||
allPkgsFor = sys: (customPackagesFor sys sys) // {
|
||||
nixpkgs = nixpkgsFor sys sys;
|
||||
uninsane = uninsane.packages."${sys}";
|
||||
imgs = mapAttrValues (host: host.config.system.build.img) self.nixosConfigurations;
|
||||
|
||||
# unofficial output
|
||||
host-pkgs = mapAttrValues (host: host.config.system.build.pkgs) self.nixosConfigurations;
|
||||
host-programs = mapAttrValues (host: mapAttrValues (p: p.package) host.config.sane.programs) self.nixosConfigurations;
|
||||
|
||||
overlays = {
|
||||
# N.B.: `nix flake check` requires every overlay to take `final: prev:` at defn site,
|
||||
# hence the weird redundancy.
|
||||
default = final: prev: self.overlays.pkgs final prev;
|
||||
sane-all = final: prev: import ./overlays/all.nix final prev;
|
||||
disable-flakey-tests = final: prev: import ./overlays/disable-flakey-tests.nix final prev;
|
||||
pkgs = final: prev: import ./overlays/pkgs.nix final prev;
|
||||
pins = final: prev: import ./overlays/pins.nix final prev;
|
||||
optimizations = final: prev: import ./overlays/optimizations.nix final prev;
|
||||
passthru = final: prev:
|
||||
let
|
||||
stable =
|
||||
if inputs ? "nixpkgs-stable" then (
|
||||
final': prev': {
|
||||
stable = inputs.nixpkgs-stable.legacyPackages."${prev'.stdenv.hostPlatform.system}";
|
||||
}
|
||||
) else (final': prev': {});
|
||||
mobile = (import "${mobile-nixos}/overlay/overlay.nix");
|
||||
uninsane = uninsane-dot-org.overlay;
|
||||
# nix-serve' = nix-serve.overlay;
|
||||
nix-serve' = next: prev: {
|
||||
# XXX(2023/03/02): upstream isn't compatible with modern `nix`. probably the perl bindings.
|
||||
# - we use the package built against `nixpkgs` specified in its flake rather than use its overlay,
|
||||
# to get around this.
|
||||
inherit (nix-serve.packages."${next.system}") nix-serve;
|
||||
};
|
||||
in
|
||||
(stable final prev)
|
||||
// (mobile final prev)
|
||||
// (uninsane final prev)
|
||||
// (nix-serve' final prev)
|
||||
;
|
||||
};
|
||||
in {
|
||||
x86_64-linux = allPkgsFor "x86_64-linux";
|
||||
aarch64-linux = allPkgsFor "aarch64-linux";
|
||||
};
|
||||
templates = {
|
||||
python-data = {
|
||||
# initialize with:
|
||||
# - `nix flake init -t '/home/colin/dev/nixos/#python-data'`
|
||||
# then enter with:
|
||||
# - `nix develop`
|
||||
path = ./templates/python-data;
|
||||
description = "python environment for data processing";
|
||||
|
||||
nixosModules = rec {
|
||||
default = sane;
|
||||
sane = import ./modules;
|
||||
passthru = { ... }: {
|
||||
imports = [
|
||||
sops-nix.nixosModules.sops
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# this includes both our native packages and all the nixpkgs packages.
|
||||
legacyPackages =
|
||||
let
|
||||
allPkgsFor = sys: (nixpkgsCompiledBy sys).appendOverlays [
|
||||
self.overlays.passthru self.overlays.pkgs
|
||||
];
|
||||
in {
|
||||
x86_64-linux = allPkgsFor "x86_64-linux";
|
||||
aarch64-linux = allPkgsFor "aarch64-linux";
|
||||
};
|
||||
|
||||
# extract only our own packages from the full set.
|
||||
# because of `nix flake check`, we flatten the package set and only surface x86_64-linux packages.
|
||||
packages = mapAttrs
|
||||
(system: allPkgs:
|
||||
allPkgs.lib.filterAttrs (name: pkg:
|
||||
# keep only packages which will pass `nix flake check`, i.e. keep only:
|
||||
# - derivations (not package sets)
|
||||
# - packages that build for the given platform
|
||||
(! elem name [ "feeds" "pythonPackagesExtensions" ])
|
||||
&& (allPkgs.lib.meta.availableOn allPkgs.stdenv.hostPlatform pkg)
|
||||
)
|
||||
(
|
||||
# expose sane packages and chosen inputs (uninsane.org)
|
||||
(import ./pkgs { pkgs = allPkgs; }) // {
|
||||
inherit (allPkgs) uninsane-dot-org;
|
||||
}
|
||||
)
|
||||
)
|
||||
# self.legacyPackages;
|
||||
{ inherit (self.legacyPackages) x86_64-linux; }
|
||||
;
|
||||
|
||||
apps."x86_64-linux" =
|
||||
let
|
||||
pkgs = self.legacyPackages."x86_64-linux";
|
||||
deployScript = action: pkgs.writeShellScript "deploy-moby" ''
|
||||
nixos-rebuild --flake '.#moby' build $@
|
||||
sudo nix sign-paths -r -k /run/secrets/nix_serve_privkey $(readlink ./result)
|
||||
nixos-rebuild --flake '.#moby' ${action} --target-host colin@moby-hn --use-remote-sudo $@
|
||||
'';
|
||||
in {
|
||||
update-feeds = {
|
||||
type = "app";
|
||||
program = "${pkgs.feeds.updateScript}";
|
||||
};
|
||||
|
||||
init-feed = {
|
||||
# use like `nix run '.#init-feed' uninsane.org`
|
||||
type = "app";
|
||||
program = "${pkgs.feeds.initFeedScript}";
|
||||
};
|
||||
|
||||
deploy-moby-test = {
|
||||
# `nix run '.#deploy-moby-test'`
|
||||
type = "app";
|
||||
program = ''${deployScript "test"}'';
|
||||
};
|
||||
deploy-moby = {
|
||||
# `nix run '.#deploy-moby-switch'`
|
||||
type = "app";
|
||||
program = ''${deployScript "switch"}'';
|
||||
};
|
||||
};
|
||||
|
||||
templates = {
|
||||
env.python-data = {
|
||||
# initialize with:
|
||||
# - `nix flake init -t '/home/colin/dev/nixos/#env.python-data'`
|
||||
# then enter with:
|
||||
# - `nix develop`
|
||||
path = ./templates/env/python-data;
|
||||
description = "python environment for data processing";
|
||||
};
|
||||
pkgs.rust-inline = {
|
||||
# initialize with:
|
||||
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.rust-inline'`
|
||||
path = ./templates/pkgs/rust-inline;
|
||||
description = "rust package and development environment (inline rust sources)";
|
||||
};
|
||||
pkgs.rust = {
|
||||
# initialize with:
|
||||
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.rust'`
|
||||
path = ./templates/pkgs/rust;
|
||||
description = "rust package fit to ship in nixpkgs";
|
||||
};
|
||||
pkgs.make = {
|
||||
# initialize with:
|
||||
# - `nix flake init -t '/home/colin/dev/nixos/#pkgs.make'`
|
||||
path = ./templates/pkgs/make;
|
||||
description = "default Makefile-based derivation";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
7
hosts/README.md
Normal file
7
hosts/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## directory structure
|
||||
- by-name/<hostname>: configuration which is evaluated _only_ for the given hostname
|
||||
- common/: configuration which applies to all hosts
|
||||
- modules/: nixpkgs-style modules which may be used by multiple hosts, but configured separately per host.
|
||||
- ideally no module here has effect unless `enable`d
|
||||
- however, `enable` may default to true
|
||||
- and in practice some of these modules surely aren't fully "disableable"
|
@@ -4,26 +4,27 @@
|
||||
./fs.nix
|
||||
];
|
||||
|
||||
# sane.packages.enableDevPkgs = true;
|
||||
sops.secrets.colin-passwd.neededForUsers = true;
|
||||
|
||||
sane.roles.build-machine.enable = true;
|
||||
sane.roles.ac = true;
|
||||
sane.roles.client = true;
|
||||
sane.roles.dev-machine = true;
|
||||
sane.services.wg-home.enable = true;
|
||||
sane.services.wg-home.ip = config.sane.hosts.by-name."desko".wg-home.ip;
|
||||
sane.services.duplicity.enable = true;
|
||||
sane.services.nixserve.secretKeyFile = config.sops.secrets.nix_serve_privkey.path;
|
||||
|
||||
sane.gui.sway.enable = true;
|
||||
sane.services.duplicity.enable = true;
|
||||
sane.services.nixserve.enable = true;
|
||||
sane.services.nixserve.sopsFile = ../../secrets/desko.yaml;
|
||||
sane.impermanence.enable = true;
|
||||
sane.programs.iphoneUtils.enableFor.user.colin = true;
|
||||
|
||||
sane.programs.guiApps.suggestedPrograms = [ "desktopGuiApps" ];
|
||||
|
||||
boot.loader.efi.canTouchEfiVariables = false;
|
||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||
|
||||
# needed to use libimobiledevice/ifuse, for iphone sync
|
||||
services.usbmuxd.enable = true;
|
||||
users.users.usbmux.uid = config.sane.allocations.usbmux-uid;
|
||||
users.groups.usbmux.gid = config.sane.allocations.usbmux-gid;
|
||||
|
||||
sops.secrets.colin-passwd = {
|
||||
sopsFile = ../../secrets/desko.yaml;
|
||||
neededForUsers = true;
|
||||
};
|
||||
|
||||
# don't enable wifi by default: it messes with connectivity.
|
||||
systemd.services.iwd.enable = false;
|
||||
@@ -35,15 +36,9 @@
|
||||
services.snapper.configs.nix = {
|
||||
# TODO: for the impermanent setup, we'd prefer to just do /nix/persist,
|
||||
# but that also requires setting up the persist dir as a subvol
|
||||
subvolume = "/nix";
|
||||
SUBVOLUME = "/nix";
|
||||
# TODO: ALLOW_USERS doesn't seem to work. still need `sudo snapper -c nix list`
|
||||
extraConfig = ''
|
||||
ALLOW_USERS = "colin";
|
||||
'';
|
||||
};
|
||||
|
||||
sops.secrets.duplicity_passphrase = {
|
||||
sopsFile = ../../secrets/desko.yaml;
|
||||
ALLOW_USERS = [ "colin" ];
|
||||
};
|
||||
|
||||
programs.steam = {
|
||||
@@ -52,7 +47,7 @@
|
||||
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
|
||||
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
|
||||
};
|
||||
sane.impermanence.home-dirs = [
|
||||
sane.user.persist.plaintext = [
|
||||
".steam"
|
||||
".local/share/Steam"
|
||||
];
|
@@ -1,7 +1,7 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
sane.impermanence.root-on-tmpfs = true;
|
||||
sane.persist.root-on-tmpfs = true;
|
||||
# we need a /tmp for building large nix things.
|
||||
# a cross-compiled kernel, particularly, will easily use 30+GB of tmp
|
||||
fileSystems."/tmp" = {
|
@@ -1,22 +1,26 @@
|
||||
{ pkgs, ... }:
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
./fs.nix
|
||||
./polyfill.nix
|
||||
];
|
||||
|
||||
# sane.packages.enableDevPkgs = true;
|
||||
sane.roles.client = true;
|
||||
sane.roles.dev-machine = true;
|
||||
sane.services.wg-home.enable = true;
|
||||
sane.services.wg-home.ip = config.sane.hosts.by-name."lappy".wg-home.ip;
|
||||
|
||||
# sane.users.guest.enable = true;
|
||||
# sane.guest.enable = true;
|
||||
sane.gui.sway.enable = true;
|
||||
sane.impermanence.enable = true;
|
||||
sane.nixcache.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = false;
|
||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||
|
||||
sops.secrets.colin-passwd = {
|
||||
sopsFile = ../../secrets/lappy.yaml;
|
||||
neededForUsers = true;
|
||||
};
|
||||
sane.programs.guiApps.suggestedPrograms = [
|
||||
"desktopGuiApps"
|
||||
"stepmania"
|
||||
];
|
||||
|
||||
sops.secrets.colin-passwd.neededForUsers = true;
|
||||
|
||||
# default config: https://man.archlinux.org/man/snapper-configs.5
|
||||
# defaults to something like:
|
||||
@@ -25,7 +29,8 @@
|
||||
services.snapper.configs.nix = {
|
||||
# TODO: for the impermanent setup, we'd prefer to just do /nix/persist,
|
||||
# but that also requires setting up the persist dir as a subvol
|
||||
subvolume = "/nix";
|
||||
SUBVOLUME = "/nix";
|
||||
ALLOW_USERS = [ "colin" ];
|
||||
};
|
||||
|
||||
# TODO: only here for debugging
|
@@ -1,7 +1,7 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
sane.impermanence.root-on-tmpfs = true;
|
||||
sane.persist.root-on-tmpfs = true;
|
||||
# we need a /tmp of default size (half RAM) for building large nix things
|
||||
fileSystems."/tmp" = {
|
||||
device = "none";
|
32
hosts/by-name/lappy/polyfill.nix
Normal file
32
hosts/by-name/lappy/polyfill.nix
Normal file
@@ -0,0 +1,32 @@
|
||||
# doesn't actually *enable* anything,
|
||||
# but sets up any modules such that if they *were* enabled, they'll act as expected.
|
||||
{ ... }:
|
||||
{
|
||||
sane.gui.sxmo = {
|
||||
greeter = "sway";
|
||||
settings = {
|
||||
# XXX: make sure the user is part of the `input` group!
|
||||
SXMO_LISGD_INPUT_DEVICE = "/dev/input/by-id/usb-Wacom_Co._Ltd._Pen_and_multitouch_sensor-event-if00";
|
||||
# these identifiers are from `swaymsg -t get_inputs`
|
||||
SXMO_VOLUME_BUTTON = "1:1:AT_Translated_Set_2_keyboard";
|
||||
# SXMO_VOLUME_BUTTON = "none";
|
||||
SXMO_POWER_BUTTON = "0:1:Power_Button";
|
||||
# SXMO_POWER_BUTTON = "none";
|
||||
SXMO_DISABLE_LEDS = "1";
|
||||
SXMO_UNLOCK_IDLE_TIME = "120"; # default
|
||||
# sxmo tries to determine device type from /proc/device-tree/compatible,
|
||||
# but that doesn't seem to exist on NixOS? (or maybe it just doesn't exist
|
||||
# on non-aarch64 builds).
|
||||
# the device type informs (at least):
|
||||
# - SXMO_WIFI_MODULE
|
||||
# - SXMO_RTW_SCAN_INTERVAL
|
||||
# - SXMO_SYS_FILES
|
||||
# - SXMO_TOUCHSCREEN_ID
|
||||
# - SXMO_MONITOR
|
||||
# - SXMO_ALSA_CONTROL_NAME
|
||||
# - SXMO_SWAY_SCALE
|
||||
# see <repo:mil/sxmo-utils:scripts/deviceprofiles>
|
||||
# SXMO_DEVICE_NAME = "pine64,pinephone-1.2";
|
||||
};
|
||||
};
|
||||
}
|
@@ -1,42 +1,43 @@
|
||||
{ config, pkgs, lib, mobile-nixos, ... }:
|
||||
{ config, pkgs, lib, ... }:
|
||||
{
|
||||
imports = [
|
||||
./firmware.nix
|
||||
./fs.nix
|
||||
./kernel.nix
|
||||
./polyfill.nix
|
||||
];
|
||||
|
||||
# cross-compiled documentation is *slow*.
|
||||
# no obvious way to natively compile docs (2022/09/29).
|
||||
# entrypoint is nixos/modules/misc/documentation.nix
|
||||
# doc building happens in nixos/doc/manual/default.nix
|
||||
# TODO: we could *maybe* inject pkgs.buildPackages.xyz = cross.buildPackages.xyz?
|
||||
documentation.nixos.enable = false;
|
||||
sane.roles.client = true;
|
||||
sane.services.wg-home.enable = true;
|
||||
sane.services.wg-home.ip = config.sane.hosts.by-name."moby".wg-home.ip;
|
||||
|
||||
# XXX colin: phosh doesn't work well with passwordless login,
|
||||
# so set this more reliable default password should anything go wrong
|
||||
users.users.colin.initialPassword = "147147";
|
||||
services.getty.autologinUser = "root"; # allows for emergency maintenance?
|
||||
|
||||
sops.secrets.colin-passwd = {
|
||||
sopsFile = ../../secrets/moby.yaml;
|
||||
neededForUsers = true;
|
||||
sops.secrets.colin-passwd.neededForUsers = true;
|
||||
|
||||
sane.programs.web-browser.config = {
|
||||
# compromise impermanence for the sake of usability
|
||||
persistCache = "private";
|
||||
persistData = "private";
|
||||
|
||||
# i don't do crypto stuff on moby
|
||||
addons.ether-metamask.enable = false;
|
||||
# addons.sideberry.enable = false;
|
||||
};
|
||||
|
||||
# usability compromises
|
||||
sane.impermanence.home-dirs = [
|
||||
config.sane.web-browser.dotDir
|
||||
sane.user.persist.plaintext = [
|
||||
# TODO: make this just generally conditional upon pulse being enabled?
|
||||
".config/pulse" # persist pulseaudio volume
|
||||
];
|
||||
|
||||
# sane.packages.enableGuiPkgs = false; # XXX faster builds/imaging for debugging
|
||||
sane.packages.extraUserPkgs = [
|
||||
pkgs.plasma5Packages.konsole # terminal
|
||||
];
|
||||
|
||||
sane.nixcache.enable = true;
|
||||
sane.impermanence.enable = true;
|
||||
sane.gui.phosh.enable = true;
|
||||
# sane.programs.consoleUtils.enableFor.user.colin = false;
|
||||
# sane.programs.guiApps.enableFor.user.colin = false;
|
||||
sane.programs.sequoia.enableFor.user.colin = false;
|
||||
sane.programs.tuiApps.enableFor.user.colin = false; # visidata, others, don't compile well
|
||||
|
||||
boot.loader.efi.canTouchEfiVariables = false;
|
||||
# /boot space is at a premium. default was 20.
|
||||
@@ -53,9 +54,10 @@
|
||||
|
||||
# without this some GUI apps fail: `DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory`
|
||||
# this is because they can't allocate enough video ram.
|
||||
# the default CMA seems to be 32M. 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.
|
||||
boot.kernelParams = [ "cma=256M" ];
|
||||
boot.kernelParams = [ "cma=512M" ];
|
||||
|
||||
# mobile-nixos' /lib/firmware includes:
|
||||
# rtl_bt (bluetooth)
|
@@ -1,7 +1,7 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
sane.impermanence.root-on-tmpfs = true;
|
||||
sane.persist.root-on-tmpfs = true;
|
||||
fileSystems."/nix" = {
|
||||
device = "/dev/disk/by-uuid/1f1271f8-53ce-4081-8a29-60a4a6b5d6f9";
|
||||
fsType = "btrfs";
|
83
hosts/by-name/moby/kernel.nix
Normal file
83
hosts/by-name/moby/kernel.nix
Normal file
@@ -0,0 +1,83 @@
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
# use the last commit on the 5.18 branch (5.18.14)
|
||||
# manjaro's changes between kernel patch versions tend to be minimal if any.
|
||||
manjaroBase = "https://gitlab.manjaro.org/manjaro-arm/packages/core/linux/-/raw/25bd828cd47b1c6e09fcbcf394a649b89d2876dd";
|
||||
manjaroPatch = name: sha256: {
|
||||
inherit name;
|
||||
patch = pkgs.fetchpatch {
|
||||
inherit name;
|
||||
url = "${manjaroBase}/${name}?inline=false";
|
||||
inherit sha256;
|
||||
};
|
||||
};
|
||||
|
||||
# the idea for patching off Manjaro's kernel comes from jakewaksbaum:
|
||||
# - https://git.sr.ht/~jakewaksbaum/pi/tree/af20aae5653545d6e67a459b59ee3e1ca8a680b0/item/kernel/default.nix
|
||||
# - he later abandoned this, i think because he's using the Pinephone Pro which received mainline support.
|
||||
manjaroPatches = [
|
||||
(manjaroPatch
|
||||
"1001-arm64-dts-allwinner-add-hdmi-sound-to-pine-devices.patch"
|
||||
"sha256-DApd791A+AxB28Ven/MVAyuyVphdo8KQDx8O7oxVPnc="
|
||||
)
|
||||
# these patches below are critical to enable wifi (RTL8723CS)
|
||||
# - the alternative is a wholly forked kernel by megi/megous:
|
||||
# - https://xnux.eu/howtos/build-pinephone-kernel.html#toc-how-to-build-megi-s-pinehpone-kernel
|
||||
# - i don't know if these patches are based on megi's or original
|
||||
(manjaroPatch
|
||||
"2001-Bluetooth-Add-new-quirk-for-broken-local-ext-features.patch"
|
||||
"sha256-CExhJuUWivegxPdnzKINEsKrMFx/m/1kOZFmlZ2SEOc="
|
||||
)
|
||||
(manjaroPatch
|
||||
"2002-Bluetooth-btrtl-add-support-for-the-RTL8723CS.patch"
|
||||
"sha256-dDdvOphTcP/Aog93HyH+L9m55laTgtjndPSE4/rnzUA="
|
||||
)
|
||||
(manjaroPatch
|
||||
"2004-arm64-dts-allwinner-enable-bluetooth-pinetab-pinepho.patch"
|
||||
"sha256-o43P3WzXyHK1PF+Kdter4asuyGAEKO6wf5ixcco2kCQ="
|
||||
)
|
||||
# XXX: this one has a Makefile, which hardcodes /sbin/depmod:
|
||||
# - drivers/staging/rtl8723cs/Makefile
|
||||
# - not sure if this is problematic?
|
||||
(manjaroPatch
|
||||
"2005-staging-add-rtl8723cs-driver.patch"
|
||||
"sha256-6ywm3dQQ5JYl60CLKarxlSUukwi4QzqctCj3tVgzFbo="
|
||||
)
|
||||
];
|
||||
in
|
||||
{
|
||||
# use Megi's kernel:
|
||||
# even with the Manjaro patches, stock 5.18 has a few issues on Pinephone:
|
||||
# - no battery charging
|
||||
# - phone rotation sensor is off by 90 degrees
|
||||
# - ambient light sensor causes screen brightness to be shakey
|
||||
# - phosh greeter may not appear after wake from sleep
|
||||
boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-megous;
|
||||
|
||||
# alternatively, use nixos' kernel and add the stuff we want:
|
||||
# # cross-compilation optimization:
|
||||
# boot.kernelPackages =
|
||||
# let p = (import nixpkgs { localSystem = "x86_64-linux"; });
|
||||
# in p.pkgsCross.aarch64-multiplatform.linuxPackages_5_18;
|
||||
# # non-cross:
|
||||
# # boot.kernelPackages = pkgs.linuxPackages_5_18;
|
||||
|
||||
# boot.kernelPatches = manjaroPatches ++ [
|
||||
# (patchDefconfig kernelConfig)
|
||||
# ];
|
||||
|
||||
nixpkgs.hostPlatform.linux-kernel = {
|
||||
# defaults:
|
||||
name = "aarch64-multiplatform";
|
||||
baseConfig = "defconfig";
|
||||
DTB = true;
|
||||
autoModules = true;
|
||||
preferBuiltin = true;
|
||||
# extraConfig = ...
|
||||
# ^-- raspberry pi stuff: we don't need it.
|
||||
|
||||
# target = "Image"; # <-- default
|
||||
target = "Image.gz"; # <-- compress the kernel image
|
||||
# target = "zImage"; # <-- confuses other parts of nixos :-(
|
||||
};
|
||||
}
|
23
hosts/by-name/moby/polyfill.nix
Normal file
23
hosts/by-name/moby/polyfill.nix
Normal file
@@ -0,0 +1,23 @@
|
||||
{ sane-lib, ... }:
|
||||
{
|
||||
sane.gui.sxmo = {
|
||||
settings = {
|
||||
# touch screen
|
||||
SXMO_LISGD_INPUT_DEVICE = "/dev/input/by-path/platform-1c2ac00.i2c-event";
|
||||
# vol and power are detected correctly by upstream
|
||||
};
|
||||
};
|
||||
# TODO: only populate this if sxmo is enabled?
|
||||
sane.user.fs.".config/sxmo/profile" = sane-lib.fs.wantedText ''
|
||||
# sourced by sxmo_init.sh
|
||||
. sxmo_common.sh
|
||||
|
||||
export SXMO_SWAY_SCALE=1.5
|
||||
export SXMO_ROTATION_GRAVITY=12800
|
||||
|
||||
export DEFAULT_COUNTRY=US
|
||||
export BROWSER=librewolf
|
||||
|
||||
export SXMO_BG_IMG="$(xdg_data_path sxmo/background.jpg)"
|
||||
'';
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
{ config, pkgs, ... }:
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
./fs.nix
|
||||
@@ -7,9 +7,8 @@
|
||||
boot.loader.generic-extlinux-compatible.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = false;
|
||||
sane.image.extraBootFiles = [ pkgs.bootpart-uefi-x86_64 ];
|
||||
|
||||
users.users.dhcpcd.uid = config.sane.allocations.dhcpcd-uid;
|
||||
users.groups.dhcpcd.gid = config.sane.allocations.dhcpcd-gid;
|
||||
# sane.persist.enable = false; # TODO: disable (but run `nix flake check` to ensure it works!)
|
||||
sane.nixcache.enable = false; # don't want to be calling out to dead machines that we're *trying* to rescue
|
||||
|
||||
# docs: https://nixos.org/manual/nixos/stable/options.html#opt-system.stateVersion
|
||||
system.stateVersion = "21.05";
|
@@ -1,29 +1,36 @@
|
||||
{ pkgs, ... }:
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./fs.nix
|
||||
./net.nix
|
||||
./users.nix
|
||||
./services
|
||||
];
|
||||
|
||||
sane.packages.extraUserPkgs = [
|
||||
sane.programs = {
|
||||
# for administering services
|
||||
pkgs.matrix-synapse
|
||||
pkgs.freshrss
|
||||
];
|
||||
sane.impermanence.enable = true;
|
||||
freshrss.enableFor.user.colin = true;
|
||||
matrix-synapse.enableFor.user.colin = true;
|
||||
signaldctl.enableFor.user.colin = true;
|
||||
};
|
||||
|
||||
sane.roles.ac = true;
|
||||
sane.roles.build-machine.enable = true;
|
||||
sane.roles.build-machine.emulation = false;
|
||||
sane.zsh.showDeadlines = false; # ~/knowledge doesn't always exist
|
||||
sane.services.dyn-dns.enable = true;
|
||||
sane.services.wg-home.enable = true;
|
||||
sane.services.wg-home.enableWan = true;
|
||||
sane.services.wg-home.ip = config.sane.hosts.by-name."servo".wg-home.ip;
|
||||
# sane.services.duplicity.enable = true; # TODO: re-enable after HW upgrade
|
||||
|
||||
# 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;
|
||||
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.
|
||||
# we just use the most aggressive of the two here:
|
||||
boot.kernel.sysctl = {
|
@@ -1,7 +1,7 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
sane.impermanence.root-on-tmpfs = true;
|
||||
sane.persist.root-on-tmpfs = true;
|
||||
# we need a /tmp for building large nix things
|
||||
fileSystems."/tmp" = {
|
||||
device = "none";
|
||||
@@ -27,7 +27,7 @@
|
||||
};
|
||||
|
||||
# slow, external storage (for archiving, etc)
|
||||
fileSystems."/nix/persist/ext" = {
|
||||
fileSystems."/mnt/persist/ext" = {
|
||||
device = "/dev/disk/by-uuid/aa272cff-0fcc-498e-a4cb-0d95fb60631b";
|
||||
fsType = "btrfs";
|
||||
options = [
|
||||
@@ -36,27 +36,31 @@
|
||||
];
|
||||
};
|
||||
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.stores."ext" = {
|
||||
origin = "/mnt/persist/ext/persist";
|
||||
storeDescription = "external HDD storage";
|
||||
};
|
||||
sane.fs."/mnt/persist/ext".mount = {};
|
||||
|
||||
sane.persist.sys.plaintext = [
|
||||
# TODO: this is overly broad; only need media and share directories to be persisted
|
||||
{ user = "colin"; group = "users"; directory = "/var/lib/uninsane"; }
|
||||
];
|
||||
# direct these media directories to external storage
|
||||
environment.persistence."/nix/persist/ext/persist" = {
|
||||
directories = [
|
||||
({
|
||||
user = "colin";
|
||||
group = "users";
|
||||
mode = "0777";
|
||||
directory = "/var/lib/uninsane/media/Videos";
|
||||
})
|
||||
({
|
||||
user = "colin";
|
||||
group = "users";
|
||||
mode = "0777";
|
||||
directory = "/var/lib/uninsane/media/freeleech";
|
||||
})
|
||||
];
|
||||
};
|
||||
# make sure large media is stored to the HDD
|
||||
sane.persist.sys.ext = [
|
||||
{
|
||||
user = "colin";
|
||||
group = "users";
|
||||
mode = "0777";
|
||||
directory = "/var/lib/uninsane/media/Videos";
|
||||
}
|
||||
{
|
||||
user = "colin";
|
||||
group = "users";
|
||||
mode = "0777";
|
||||
directory = "/var/lib/uninsane/media/freeleech";
|
||||
}
|
||||
];
|
||||
|
||||
# in-memory compressed RAM (seems to be dynamically sized)
|
||||
# zramSwap = {
|
@@ -3,6 +3,8 @@
|
||||
{
|
||||
networking.domain = "uninsane.org";
|
||||
|
||||
sane.services.wan-ports.openFirewall = true;
|
||||
|
||||
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
|
||||
# Per-interface useDHCP will be mandatory in the future, so this generated config
|
||||
# replicates the default behaviour.
|
||||
@@ -11,9 +13,6 @@
|
||||
# XXX colin: probably don't need this. wlan0 won't be populated unless i touch a value in networking.interfaces.wlan0
|
||||
networking.wireless.enable = false;
|
||||
|
||||
# networking.firewall.enable = false;
|
||||
networking.firewall.enable = true;
|
||||
|
||||
# this is needed to forward packets from the VPN to the host
|
||||
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
|
||||
|
||||
@@ -33,6 +32,14 @@
|
||||
# - getent ahostsv4 www.google.com
|
||||
# - try fix: <https://serverfault.com/questions/765989/connect-to-3rd-party-vpn-server-but-dont-use-it-as-the-default-route/766290#766290>
|
||||
services.resolved.enable = true;
|
||||
# without DNSSEC:
|
||||
# - dig matrix.org => works
|
||||
# - curl https://matrix.org => works
|
||||
# with default DNSSEC:
|
||||
# - dig matrix.org => works
|
||||
# - curl https://matrix.org => fails
|
||||
# i don't know why. this might somehow be interfering with the DNS run on this device (trust-dns)
|
||||
services.resolved.dnssec = "false";
|
||||
networking.nameservers = [
|
||||
# use systemd-resolved resolver
|
||||
# full resolver (which understands /etc/hosts) lives on 127.0.0.53
|
||||
@@ -52,18 +59,18 @@
|
||||
|
||||
# services.resolved.extraConfig = ''
|
||||
# # 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.
|
||||
# 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
|
||||
# '';
|
||||
|
||||
# OVPN CONFIG (https://www.ovpn.com):
|
||||
# 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?)
|
||||
networking.wireguard.enable = true;
|
||||
networking.wireguard.interfaces.wg0 = let
|
||||
networking.wireguard.interfaces.wg-ovpns = let
|
||||
ip = "${pkgs.iproute2}/bin/ip";
|
||||
in-ns = "${ip} netns exec ovpns";
|
||||
iptables = "${pkgs.iptables}/bin/iptables";
|
||||
@@ -159,13 +166,10 @@
|
||||
# create a new routing table that we can use to proxy traffic out of the root namespace
|
||||
# through the ovpns namespace, and to the WAN via VPN.
|
||||
networking.iproute2.rttablesExtraConfig = ''
|
||||
5 ovpns
|
||||
5 ovpns
|
||||
'';
|
||||
networking.iproute2.enable = true;
|
||||
|
||||
sops.secrets."wg_ovpns_privkey" = {
|
||||
sopsFile = ../../secrets/servo.yaml;
|
||||
};
|
||||
|
||||
# HURRICANE ELECTRIC CONFIG:
|
||||
# networking.sits = {
|
34
hosts/by-name/servo/services/calibre.nix
Normal file
34
hosts/by-name/servo/services/calibre.nix
Normal file
@@ -0,0 +1,34 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cweb-cfg = config.services.calibre-web;
|
||||
inherit (cweb-cfg) user group;
|
||||
inherit (cweb-cfg.listen) ip port;
|
||||
svc-dir = "/var/lib/${cweb-cfg.dataDir}";
|
||||
in
|
||||
# XXX: disabled because of runtime errors like:
|
||||
# > File "/nix/store/c7jqvx980nlg9xhxi065cba61r2ain9y-calibre-web-0.6.19/lib/python3.10/site-packages/calibreweb/cps/db.py", line 926, in speaking_language
|
||||
# > languages = self.session.query(Languages) \
|
||||
# > AttributeError: 'NoneType' object has no attribute 'query'
|
||||
lib.mkIf false
|
||||
{
|
||||
sane.persist.sys.plaintext = [
|
||||
{ inherit user group; mode = "0700"; directory = svc-dir; }
|
||||
];
|
||||
|
||||
services.calibre-web.enable = true;
|
||||
services.calibre-web.listen.ip = "127.0.0.1";
|
||||
# XXX: externally populate `${svc-dir}/metadata.db` (once) from
|
||||
# <https://github.com/janeczku/calibre-web/blob/master/library/metadata.db>
|
||||
# i don't know why you have to do this??
|
||||
# services.calibre-web.options.calibreLibrary = svc-dir;
|
||||
|
||||
services.nginx.virtualHosts."calibre.uninsane.org" = {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://${ip}:${builtins.toString port}";
|
||||
};
|
||||
};
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."calibre" = "native";
|
||||
}
|
@@ -6,7 +6,7 @@ lib.mkIf false
|
||||
systemd.services.ddns-afraid = {
|
||||
description = "update dynamic DNS entries for freedns.afraid.org";
|
||||
serviceConfig = {
|
||||
EnvironmentFile = config.sops.secrets.ddns_afraid.path;
|
||||
EnvironmentFile = config.sops.secrets."ddns_afraid.env".path;
|
||||
# TODO: ProtectSystem = "strict";
|
||||
# TODO: ProtectHome = "full";
|
||||
# TODO: PrivateTmp = true;
|
||||
@@ -24,8 +24,4 @@ lib.mkIf false
|
||||
OnUnitActiveSec = "10min";
|
||||
};
|
||||
};
|
||||
|
||||
sops.secrets."ddns_afraid" = {
|
||||
sopsFile = ../../../secrets/servo.yaml;
|
||||
};
|
||||
}
|
@@ -6,7 +6,7 @@ lib.mkIf false
|
||||
systemd.services.ddns-he = {
|
||||
description = "update dynamic DNS entries for HurricaneElectric";
|
||||
serviceConfig = {
|
||||
EnvironmentFile = config.sops.secrets.ddns_he.path;
|
||||
EnvironmentFile = config.sops.secrets."ddns_he.env".path;
|
||||
# TODO: ProtectSystem = "strict";
|
||||
# TODO: ProtectHome = "full";
|
||||
# TODO: PrivateTmp = true;
|
||||
@@ -27,8 +27,4 @@ lib.mkIf false
|
||||
OnUnitActiveSec = "10min";
|
||||
};
|
||||
};
|
||||
|
||||
sops.secrets."ddns_he" = {
|
||||
sopsFile = ../../../secrets/servo.yaml;
|
||||
};
|
||||
}
|
@@ -1,8 +1,10 @@
|
||||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
./calibre.nix
|
||||
./ddns-afraid.nix
|
||||
./ddns-he.nix
|
||||
./email
|
||||
./ejabberd.nix
|
||||
./freshrss.nix
|
||||
./gitea.nix
|
||||
@@ -11,12 +13,14 @@
|
||||
./jackett.nix
|
||||
./jellyfin.nix
|
||||
./kiwix-serve.nix
|
||||
./komga.nix
|
||||
./lemmy.nix
|
||||
./matrix
|
||||
./navidrome.nix
|
||||
./nixserve.nix
|
||||
./nginx.nix
|
||||
./pict-rs.nix
|
||||
./pleroma.nix
|
||||
./postfix.nix
|
||||
./postgres.nix
|
||||
./prosody.nix
|
||||
./transmission.nix
|
@@ -19,10 +19,10 @@
|
||||
# XXX: avatar support works in MUCs but not DMs
|
||||
# lib.mkIf false
|
||||
{
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.sys.plaintext = [
|
||||
{ user = "ejabberd"; group = "ejabberd"; directory = "/var/lib/ejabberd"; }
|
||||
];
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
sane.services.wan-ports.tcp = [
|
||||
3478 # STUN/TURN
|
||||
5222 # XMPP client -> server
|
||||
5223 # XMPPS client -> server (XMPP over TLS)
|
||||
@@ -33,19 +33,22 @@
|
||||
5349 # STUN/TURN (TLS)
|
||||
5443 # web services (file uploads, websockets, admin)
|
||||
];
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
sane.services.wan-ports.udp = [
|
||||
3478 # STUN/TURN
|
||||
];
|
||||
# TODO: forward these TURN ports!
|
||||
networking.firewall.allowedTCPPortRanges = [{
|
||||
from = 49152; # TURN
|
||||
to = 65535;
|
||||
to = 49408;
|
||||
}];
|
||||
networking.firewall.allowedUDPPortRanges = [{
|
||||
from = 49152; # TURN
|
||||
to = 65535;
|
||||
to = 49408;
|
||||
}];
|
||||
|
||||
# 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" ];
|
||||
|
||||
security.acme.certs."uninsane.org".extraDomainNames = [
|
||||
@@ -75,33 +78,33 @@
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
# XXX: SRV records have to point to something with a A/AAAA record; no CNAMEs
|
||||
A."xmpp" = [ "%NATIVE%" ];
|
||||
CNAME."muc.xmpp" = [ "xmpp" ];
|
||||
CNAME."pubsub.xmpp" = [ "xmpp" ];
|
||||
CNAME."upload.xmpp" = [ "xmpp" ];
|
||||
CNAME."vjid.xmpp" = [ "xmpp" ];
|
||||
A."xmpp" = "%NATIVE%";
|
||||
CNAME."muc.xmpp" = "xmpp";
|
||||
CNAME."pubsub.xmpp" = "xmpp";
|
||||
CNAME."upload.xmpp" = "xmpp";
|
||||
CNAME."vjid.xmpp" = "xmpp";
|
||||
|
||||
# _Service._Proto.Name TTL Class SRV Priority Weight Port Target
|
||||
# - <https://xmpp.org/extensions/xep-0368.html>
|
||||
# something's requesting the SRV records for muc.xmpp, so let's include it
|
||||
# nothing seems to request XMPP SRVs for the other records (except @)
|
||||
# lower numerical priority field tells clients to prefer this method
|
||||
SRV."_xmpps-client._tcp.muc.xmpp" = [ "3 50 5223 xmpp" ];
|
||||
SRV."_xmpps-server._tcp.muc.xmpp" = [ "3 50 5270 xmpp" ];
|
||||
SRV."_xmpp-client._tcp.muc.xmpp" = [ "5 50 5222 xmpp" ];
|
||||
SRV."_xmpp-server._tcp.muc.xmpp" = [ "5 50 5269 xmpp" ];
|
||||
SRV."_xmpps-client._tcp.muc.xmpp" = "3 50 5223 xmpp";
|
||||
SRV."_xmpps-server._tcp.muc.xmpp" = "3 50 5270 xmpp";
|
||||
SRV."_xmpp-client._tcp.muc.xmpp" = "5 50 5222 xmpp";
|
||||
SRV."_xmpp-server._tcp.muc.xmpp" = "5 50 5269 xmpp";
|
||||
|
||||
SRV."_xmpps-client._tcp" = [ "3 50 5223 xmpp" ];
|
||||
SRV."_xmpps-server._tcp" = [ "3 50 5270 xmpp" ];
|
||||
SRV."_xmpp-client._tcp" = [ "5 50 5222 xmpp" ];
|
||||
SRV."_xmpp-server._tcp" = [ "5 50 5269 xmpp" ];
|
||||
SRV."_xmpps-client._tcp" = "3 50 5223 xmpp";
|
||||
SRV."_xmpps-server._tcp" = "3 50 5270 xmpp";
|
||||
SRV."_xmpp-client._tcp" = "5 50 5222 xmpp";
|
||||
SRV."_xmpp-server._tcp" = "5 50 5269 xmpp";
|
||||
|
||||
SRV."_stun._udp" = [ "5 50 3478 xmpp" ];
|
||||
SRV."_stun._tcp" = [ "5 50 3478 xmpp" ];
|
||||
SRV."_stuns._tcp" = [ "5 50 5349 xmpp" ];
|
||||
SRV."_turn._udp" = [ "5 50 3478 xmpp" ];
|
||||
SRV."_turn._tcp" = [ "5 50 3478 xmpp" ];
|
||||
SRV."_turns._tcp" = [ "5 50 5349 xmpp" ];
|
||||
SRV."_stun._udp" = "5 50 3478 xmpp";
|
||||
SRV."_stun._tcp" = "5 50 3478 xmpp";
|
||||
SRV."_stuns._tcp" = "5 50 5349 xmpp";
|
||||
SRV."_turn._udp" = "5 50 3478 xmpp";
|
||||
SRV."_turn._tcp" = "5 50 3478 xmpp";
|
||||
SRV."_turns._tcp" = "5 50 5349 xmpp";
|
||||
};
|
||||
|
||||
# TODO: allocate UIDs/GIDs ?
|
37
hosts/by-name/servo/services/email/default.nix
Normal file
37
hosts/by-name/servo/services/email/default.nix
Normal file
@@ -0,0 +1,37 @@
|
||||
# nix configs to reference:
|
||||
# - <https://gitlab.com/simple-nixos-mailserver/nixos-mailserver>
|
||||
# - <https://github.com/nix-community/nur-combined/-/tree/master/repos/eh5/machines/srv-m/mail-rspamd.nix>
|
||||
# - postfix / dovecot / rspamd / stalwart-jmap / sogo
|
||||
#
|
||||
# rspamd:
|
||||
# - nixos: <https://nixos.wiki/wiki/Rspamd>
|
||||
# - guide: <https://rspamd.com/doc/quickstart.html>
|
||||
# - non-nixos example: <https://dataswamp.org/~solene/2021-07-13-smtpd-rspamd.html>
|
||||
#
|
||||
#
|
||||
# my rough understanding of the pieces:
|
||||
# - postfix handles SMTP protocol with the rest of the world.
|
||||
# - dovecot implements IMAP protocol.
|
||||
# - client auth (i.e. validate that user@uninsane.org is who they claim)
|
||||
# - "folders" (INBOX, JUNK) are internal to dovecot?
|
||||
# or where do folders live, on-disk?
|
||||
#
|
||||
# - non-local clients (i.e. me) interact with BOTH postfix and dovecot, but primarily dovecot:
|
||||
# - mail reading is done via IMAP (so, dovecot)
|
||||
# - mail sending is done via SMTP/submission port (so, postfix)
|
||||
# - but postfix delegates authorization of that outgoing mail to dovecot, on the server side
|
||||
#
|
||||
# - local clients (i.e. sendmail) interact only with postfix
|
||||
|
||||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
./dovecot.nix
|
||||
./postfix.nix
|
||||
];
|
||||
|
||||
|
||||
#### SPAM FILTERING
|
||||
# services.rspamd.enable = true;
|
||||
# services.rspamd.postfix.enable = true;
|
||||
}
|
135
hosts/by-name/servo/services/email/dovecot.nix
Normal file
135
hosts/by-name/servo/services/email/dovecot.nix
Normal file
@@ -0,0 +1,135 @@
|
||||
# dovecot config options: <https://doc.dovecot.org/configuration_manual/>
|
||||
#
|
||||
# sieve docs:
|
||||
# - sieve language examples: <https://doc.dovecot.org/configuration_manual/sieve/examples/>
|
||||
# - sieve protocol/language: <https://proton.me/support/sieve-advanced-custom-filters>
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
sane.services.wan-ports.tcp = [
|
||||
# exposed over non-vpn imap.uninsane.org
|
||||
143 # IMAP
|
||||
993 # IMAPS
|
||||
];
|
||||
|
||||
# exists only to manage certs for dovecot
|
||||
services.nginx.virtualHosts."imap.uninsane.org" = {
|
||||
enableACME = true;
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
CNAME."imap" = "native";
|
||||
};
|
||||
|
||||
sops.secrets."dovecot_passwd" = {
|
||||
owner = config.users.users.dovecot2.name;
|
||||
# TODO: debug why mail can't be sent without this being world-readable
|
||||
mode = "0444";
|
||||
};
|
||||
|
||||
# inspired by https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/
|
||||
services.dovecot2.enable = true;
|
||||
# services.dovecot2.enableLmtp = true;
|
||||
services.dovecot2.sslServerCert = "/var/lib/acme/imap.uninsane.org/fullchain.pem";
|
||||
services.dovecot2.sslServerKey = "/var/lib/acme/imap.uninsane.org/key.pem";
|
||||
services.dovecot2.enablePAM = false;
|
||||
|
||||
# sieve scripts require me to set a user for... idk why?
|
||||
services.dovecot2.mailUser = "colin";
|
||||
services.dovecot2.mailGroup = "users";
|
||||
users.users.colin.isSystemUser = lib.mkForce false;
|
||||
|
||||
services.dovecot2.extraConfig =
|
||||
let
|
||||
passwdFile = config.sops.secrets.dovecot_passwd.path;
|
||||
in
|
||||
''
|
||||
passdb {
|
||||
driver = passwd-file
|
||||
args = ${passwdFile}
|
||||
}
|
||||
userdb {
|
||||
driver = passwd-file
|
||||
args = ${passwdFile}
|
||||
}
|
||||
|
||||
# allow postfix to query our auth db
|
||||
service auth {
|
||||
unix_listener auth {
|
||||
mode = 0660
|
||||
user = postfix
|
||||
group = postfix
|
||||
}
|
||||
}
|
||||
auth_mechanisms = plain login
|
||||
|
||||
# accept incoming messaging from postfix
|
||||
# service lmtp {
|
||||
# unix_listener dovecot-lmtp {
|
||||
# mode = 0600
|
||||
# user = postfix
|
||||
# group = postfix
|
||||
# }
|
||||
# }
|
||||
|
||||
# plugin {
|
||||
# sieve_plugins = sieve_imapsieve
|
||||
# }
|
||||
|
||||
mail_debug = yes
|
||||
auth_debug = yes
|
||||
# verbose_ssl = yes
|
||||
'';
|
||||
|
||||
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
|
||||
# - Junk: works ("mark" -> "move to Junk")
|
||||
# aerc
|
||||
# - Drafts: works
|
||||
# - Sent: works
|
||||
# - Trash: no; deleted messages are actually deleted
|
||||
# use `:move trash` instead
|
||||
# - Junk: ?
|
||||
# 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"; };
|
||||
Junk = { specialUse = "Junk"; auto = "create"; };
|
||||
};
|
||||
|
||||
services.dovecot2.mailPlugins = {
|
||||
perProtocol = {
|
||||
# imap.enable = [
|
||||
# "imap_sieve"
|
||||
# ];
|
||||
lda.enable = [
|
||||
"sieve"
|
||||
];
|
||||
# lmtp.enable = [
|
||||
# "sieve"
|
||||
# ];
|
||||
};
|
||||
};
|
||||
services.dovecot2.modules = [
|
||||
pkgs.dovecot_pigeonhole # enables sieve execution (?)
|
||||
];
|
||||
services.dovecot2.sieveScripts = {
|
||||
# if any messages fail to pass (or lack) DKIM, move them to Junk
|
||||
# XXX the key name ("after") is only used to order sieve execution/ordering
|
||||
after = builtins.toFile "ensuredkim.sieve" ''
|
||||
require "fileinto";
|
||||
|
||||
if not header :contains "Authentication-Results" "dkim=pass" {
|
||||
fileinto "Junk";
|
||||
stop;
|
||||
}
|
||||
'';
|
||||
};
|
||||
}
|
@@ -1,4 +1,6 @@
|
||||
{ config, lib, ... }:
|
||||
# postfix config options: <https://www.postfix.org/postconf.5.html>
|
||||
|
||||
{ lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
submissionOptions = {
|
||||
@@ -16,7 +18,7 @@ let
|
||||
};
|
||||
in
|
||||
{
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.sys.plaintext = [
|
||||
# TODO: mode? could be more granular
|
||||
{ user = "opendkim"; group = "opendkim"; directory = "/var/lib/opendkim"; }
|
||||
{ user = "root"; group = "root"; directory = "/var/lib/postfix"; }
|
||||
@@ -26,18 +28,13 @@ in
|
||||
# "/var/lib/dovecot"
|
||||
];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
sane.services.wan-ports.tcp = [
|
||||
# exposed over vpn mx.uninsane.org
|
||||
25 # SMTP
|
||||
143 # IMAP
|
||||
465 # SMTPS
|
||||
587 # SMTPS/submission
|
||||
993 # IMAPS
|
||||
];
|
||||
|
||||
# exists only to manage certs for dovecot
|
||||
services.nginx.virtualHosts."imap.uninsane.org" = {
|
||||
enableACME = true;
|
||||
};
|
||||
# exists only to manage certs for Postfix
|
||||
services.nginx.virtualHosts."mx.uninsane.org" = {
|
||||
enableACME = true;
|
||||
@@ -45,22 +42,21 @@ in
|
||||
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
MX."@" = [ "10 mx.uninsane.org." ];
|
||||
MX."@" = "10 mx.uninsane.org.";
|
||||
# XXX: RFC's specify that the MX record CANNOT BE A CNAME
|
||||
A."mx" = [ "185.157.162.178" ];
|
||||
CNAME."imap" = [ "native" ];
|
||||
A."mx" = "185.157.162.178";
|
||||
|
||||
# Sender Policy Framework:
|
||||
# +mx => mail passes if it originated from the MX
|
||||
# +a => mail passes if it originated from the A address of this domain
|
||||
# +ip4:.. => mail passes if it originated from this IP
|
||||
# -all => mail fails if none of these conditions were met
|
||||
TXT."@" = [ "v=spf1 a mx -all" ];
|
||||
TXT."@" = "v=spf1 a mx -all";
|
||||
|
||||
# DKIM public key:
|
||||
TXT."mx._domainkey" = [
|
||||
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkSyMufc2KrRx3j17e/LyB+3eYSBRuEFT8PUka8EDX04QzCwDPdkwgnj3GNDvnB5Ktb05Cf2SJ/S1OLqNsINxJRWtkVfZd/C339KNh9wrukMKRKNELL9HLUw0bczOI4gKKFqyrRE9qm+4csCMAR79Te9FCjGV/jVnrkLdPT0GtFwIDAQAB"
|
||||
];
|
||||
TXT."mx._domainkey" =
|
||||
"v=DKIM1;k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkSyMufc2KrRx3j17e/LyB+3eYSBRuEFT8PUka8EDX04QzCwDPdkwgnj3GNDvnB5Ktb05Cf2SJ/S1OLqNsINxJRWtkVfZd/C339KNh9wrukMKRKNELL9HLUw0bczOI4gKKFqyrRE9qm+4csCMAR79Te9FCjGV/jVnrkLdPT0GtFwIDAQAB"
|
||||
;
|
||||
|
||||
# DMARC fields <https://datatracker.ietf.org/doc/html/rfc7489>:
|
||||
# p=none|quarantine|reject: what to do with failures
|
||||
@@ -75,9 +71,9 @@ in
|
||||
# pct = sampling ratio for punishing failures (default 100 for 100%)
|
||||
# rf = report format
|
||||
# ri = report interval
|
||||
TXT."_dmarc" = [
|
||||
TXT."_dmarc" =
|
||||
"v=DMARC1;p=quarantine;sp=reject;rua=mailto:admin+mail@uninsane.org;ruf=mailto:admin+mail@uninsane.org;fo=1:d:s"
|
||||
];
|
||||
;
|
||||
};
|
||||
|
||||
services.postfix.enable = true;
|
||||
@@ -92,32 +88,56 @@ in
|
||||
@uninsane.org colin
|
||||
'';
|
||||
|
||||
services.postfix.extraConfig = ''
|
||||
services.postfix.config = {
|
||||
# smtpd_milters = local:/run/opendkim/opendkim.sock
|
||||
# milter docs: http://www.postfix.org/MILTER_README.html
|
||||
# mail filters for receiving email and authorized SMTP clients
|
||||
# mail filters for receiving email and from authorized SMTP clients (i.e. via submission)
|
||||
# smtpd_milters = inet:185.157.162.190:8891
|
||||
smtpd_milters = unix:/run/opendkim/opendkim.sock
|
||||
# opendkim.sock will add a Authentication-Results header, with `dkim=pass|fail|...` value to received messages
|
||||
smtpd_milters = "unix:/run/opendkim/opendkim.sock";
|
||||
# mail filters for sendmail
|
||||
non_smtpd_milters = $smtpd_milters
|
||||
milter_default_action = accept
|
||||
inet_protocols = ipv4
|
||||
smtp_tls_security_level = may
|
||||
'';
|
||||
non_smtpd_milters = "$smtpd_milters";
|
||||
|
||||
# what to do when a milter exits unexpectedly:
|
||||
milter_default_action = "accept";
|
||||
|
||||
inet_protocols = "ipv4";
|
||||
smtp_tls_security_level = "may";
|
||||
|
||||
# hand received mail over to dovecot so that it can run sieves & such
|
||||
mailbox_command = ''${pkgs.dovecot}/libexec/dovecot/dovecot-lda -f "$SENDER" -a "$RECIPIENT"'';
|
||||
|
||||
# hand received mail over to dovecot
|
||||
# virtual_alias_maps = [
|
||||
# "hash:/etc/postfix/virtual"
|
||||
# ];
|
||||
# mydestination = "";
|
||||
# virtual_mailbox_domains = [ "localhost" "uninsane.org" ];
|
||||
# # virtual_mailbox_maps = "hash:/etc/postfix/virtual";
|
||||
# virtual_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp";
|
||||
|
||||
# anti-spam options: <https://www.postfix.org/SMTPD_ACCESS_README.html>
|
||||
# reject_unknown_sender_domain: causes postfix to `dig <sender> MX` and make sure that exists.
|
||||
# but may cause problems receiving mail from google & others who load-balance?
|
||||
# - <https://unix.stackexchange.com/questions/592131/how-to-reject-email-from-unknown-domains-with-postfix-on-centos>
|
||||
# smtpd_sender_restrictions = reject_unknown_sender_domain
|
||||
};
|
||||
|
||||
services.postfix.enableSubmission = true;
|
||||
services.postfix.submissionOptions = submissionOptions;
|
||||
services.postfix.enableSubmissions = true;
|
||||
services.postfix.submissionsOptions = submissionOptions;
|
||||
|
||||
systemd.services.postfix.after = [ "wireguard-wg0.service" ];
|
||||
systemd.services.postfix.partOf = [ "wireguard-wg0.service" ];
|
||||
systemd.services.postfix.after = [ "wireguard-wg-ovpns.service" ];
|
||||
systemd.services.postfix.partOf = [ "wireguard-wg-ovpns.service" ];
|
||||
systemd.services.postfix.serviceConfig = {
|
||||
# run this behind the OVPN static VPN
|
||||
NetworkNamespacePath = "/run/netns/ovpns";
|
||||
};
|
||||
|
||||
|
||||
#### OPENDKIM
|
||||
|
||||
services.opendkim.enable = true;
|
||||
# services.opendkim.domains = "csl:uninsane.org";
|
||||
services.opendkim.domains = "uninsane.org";
|
||||
@@ -132,8 +152,8 @@ in
|
||||
# keeping this the same as the hostname seems simplest
|
||||
services.opendkim.selector = "mx";
|
||||
|
||||
systemd.services.opendkim.after = [ "wireguard-wg0.service" ];
|
||||
systemd.services.opendkim.partOf = [ "wireguard-wg0.service" ];
|
||||
systemd.services.opendkim.after = [ "wireguard-wg-ovpns.service" ];
|
||||
systemd.services.opendkim.partOf = [ "wireguard-wg-ovpns.service" ];
|
||||
systemd.services.opendkim.serviceConfig = {
|
||||
# run this behind the OVPN static VPN
|
||||
NetworkNamespacePath = "/run/netns/ovpns";
|
||||
@@ -141,40 +161,6 @@ in
|
||||
UMask = lib.mkForce "0011";
|
||||
};
|
||||
|
||||
# inspired by https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/
|
||||
services.dovecot2.enable = true;
|
||||
services.dovecot2.sslServerCert = "/var/lib/acme/imap.uninsane.org/fullchain.pem";
|
||||
services.dovecot2.sslServerKey = "/var/lib/acme/imap.uninsane.org/key.pem";
|
||||
services.dovecot2.enablePAM = false;
|
||||
services.dovecot2.extraConfig =
|
||||
let
|
||||
passwdFile = config.sops.secrets.dovecot_passwd.path;
|
||||
in
|
||||
''
|
||||
passdb {
|
||||
driver = passwd-file
|
||||
args = ${passwdFile}
|
||||
}
|
||||
userdb {
|
||||
driver = passwd-file
|
||||
args = ${passwdFile}
|
||||
}
|
||||
|
||||
# allow postfix to query our auth db
|
||||
service auth {
|
||||
unix_listener auth {
|
||||
mode = 0660
|
||||
user = postfix
|
||||
group = postfix
|
||||
}
|
||||
}
|
||||
auth_mechanisms = plain login
|
||||
|
||||
|
||||
mail_debug = yes
|
||||
auth_debug = yes
|
||||
# verbose_ssl = yes
|
||||
'';
|
||||
|
||||
#### OUTGOING MESSAGE REWRITING:
|
||||
services.postfix.enableHeaderChecks = true;
|
||||
@@ -196,11 +182,4 @@ in
|
||||
# pattern = "/^Subject:.*activate your account/";
|
||||
# }
|
||||
];
|
||||
|
||||
sops.secrets.dovecot_passwd = {
|
||||
sopsFile = ../../../secrets/servo.yaml;
|
||||
owner = config.users.users.dovecot2.name;
|
||||
# TODO: debug why mail can't be sent without this being world-readable
|
||||
mode = "0444";
|
||||
};
|
||||
}
|
@@ -9,19 +9,16 @@
|
||||
# $ sudo -u freshrss -g freshrss FRESHRSS_DATA_PATH=/var/lib/freshrss ./result/cli/export-opml-for-user.php --user admin
|
||||
# ```
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, pkgs, sane-lib, ... }:
|
||||
{
|
||||
sops.secrets.freshrss_passwd = {
|
||||
sopsFile = ../../../secrets/servo.yaml;
|
||||
sops.secrets."freshrss_passwd" = {
|
||||
owner = config.users.users.freshrss.name;
|
||||
mode = "400";
|
||||
mode = "0400";
|
||||
};
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.sys.plaintext = [
|
||||
{ user = "freshrss"; group = "freshrss"; directory = "/var/lib/freshrss"; }
|
||||
];
|
||||
|
||||
users.users.freshrss.uid = config.sane.allocations.freshrss-uid;
|
||||
users.groups.freshrss.gid = config.sane.allocations.freshrss-gid;
|
||||
services.freshrss.enable = true;
|
||||
services.freshrss.baseUrl = "https://rss.uninsane.org";
|
||||
services.freshrss.virtualHost = "rss.uninsane.org";
|
||||
@@ -29,9 +26,11 @@
|
||||
|
||||
systemd.services.freshrss-import-feeds =
|
||||
let
|
||||
feeds = sane-lib.feeds;
|
||||
fresh = config.systemd.services.freshrss-config;
|
||||
feeds = import ../../../modules/home-manager/feeds.nix { inherit lib; };
|
||||
opml = pkgs.writeText "sane-freshrss.opml" (feeds.feedsToOpml feeds.all);
|
||||
all-feeds = config.sane.feeds;
|
||||
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
|
||||
opml = pkgs.writeText "sane-freshrss.opml" (feeds.feedsToOpml wanted-feeds);
|
||||
in {
|
||||
inherit (fresh) wantedBy environment;
|
||||
serviceConfig = {
|
||||
@@ -42,7 +41,10 @@
|
||||
description = "import sane RSS feed list";
|
||||
after = [ "freshrss-config.service" ];
|
||||
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}
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -57,5 +59,5 @@
|
||||
# the routing is handled by services.freshrss.virtualHost
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."rss" = [ "native" ];
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."rss" = "native";
|
||||
}
|
@@ -1,25 +1,37 @@
|
||||
# config options: <https://docs.gitea.io/en-us/administration/config-cheat-sheet/>
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.sys.plaintext = [
|
||||
# TODO: mode? could be more granular
|
||||
{ user = "git"; group = "gitea"; directory = "/var/lib/gitea"; }
|
||||
];
|
||||
users.groups.gitea.gid = config.sane.allocations.gitea-gid;
|
||||
services.gitea.enable = true;
|
||||
services.gitea.user = "git"; # default is 'gitea'
|
||||
services.gitea.database.type = "postgres";
|
||||
services.gitea.database.user = "git";
|
||||
services.gitea.appName = "Perfectly Sane Git";
|
||||
services.gitea.domain = "git.uninsane.org";
|
||||
services.gitea.rootUrl = "https://git.uninsane.org/";
|
||||
services.gitea.settings.session.COOKIE_SECURE = 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 = {
|
||||
# options: "Trace", "Debug", "Info", "Warn", "Error", "Critical"
|
||||
log.LEVEL = "Warn";
|
||||
server = {
|
||||
# options: "home", "explore", "organizations", "login" or URL fragment (or full URL)
|
||||
LANDING_PAGE = "explore";
|
||||
DOMAIN = "git.uninsane.org";
|
||||
ROOT_URL = "https://git.uninsane.org/";
|
||||
};
|
||||
service = {
|
||||
# timeout for email approval. 5760 = 4 days
|
||||
@@ -34,6 +46,7 @@
|
||||
ENABLE_CAPTCHA = true;
|
||||
NOREPLY_ADDRESS = "noreply.anonymous.git@uninsane.org";
|
||||
};
|
||||
session.COOKIE_SECURE = true;
|
||||
repository = {
|
||||
DEFAULT_BRANCH = "master";
|
||||
};
|
||||
@@ -48,6 +61,8 @@
|
||||
};
|
||||
#"ui.meta" = ... to customize html author/description/etc
|
||||
mailer = {
|
||||
# alternative is to use nixos-level config:
|
||||
# services.gitea.mailerPasswordFile = ...
|
||||
ENABLED = true;
|
||||
MAILER_TYPE = "sendmail";
|
||||
FROM = "notify.git@uninsane.org";
|
||||
@@ -59,8 +74,6 @@
|
||||
FORMAT = "RFC3339";
|
||||
};
|
||||
};
|
||||
# options: "Trace", "Debug", "Info", "Warn", "Error", "Critical"
|
||||
services.gitea.settings.log.LEVEL = "Warn";
|
||||
|
||||
systemd.services.gitea.serviceConfig = {
|
||||
# nix default is AF_UNIX AF_INET AF_INET6.
|
||||
@@ -85,5 +98,5 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."git" = [ "native" ];
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."git" = "native";
|
||||
}
|
@@ -64,5 +64,5 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."sink" = [ "native" ];
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."sink" = "native";
|
||||
}
|
@@ -10,7 +10,7 @@
|
||||
|
||||
lib.mkIf false # i don't actively use ipfs anymore
|
||||
{
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.sys.plaintext = [
|
||||
# TODO: mode? could be more granular
|
||||
{ user = "261"; group = "261"; directory = "/var/lib/ipfs"; }
|
||||
];
|
||||
@@ -34,7 +34,7 @@ lib.mkIf false # i don't actively use ipfs anymore
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."ipfs" = [ "native" ];
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."ipfs" = "native";
|
||||
|
||||
# services.ipfs.enable = true;
|
||||
services.kubo.localDiscovery = true;
|
@@ -1,14 +1,14 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.sys.plaintext = [
|
||||
# TODO: mode? we only need this to save Indexer creds ==> migrate to config?
|
||||
{ user = "root"; group = "root"; directory = "/var/lib/jackett"; }
|
||||
];
|
||||
services.jackett.enable = true;
|
||||
|
||||
systemd.services.jackett.after = [ "wireguard-wg0.service" ];
|
||||
systemd.services.jackett.partOf = [ "wireguard-wg0.service" ];
|
||||
systemd.services.jackett.after = [ "wireguard-wg-ovpns.service" ];
|
||||
systemd.services.jackett.partOf = [ "wireguard-wg-ovpns.service" ];
|
||||
systemd.services.jackett.serviceConfig = {
|
||||
# run this behind the OVPN static VPN
|
||||
NetworkNamespacePath = "/run/netns/ovpns";
|
||||
@@ -27,6 +27,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jackett" = [ "native" ];
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jackett" = "native";
|
||||
}
|
||||
|
115
hosts/by-name/servo/services/jellyfin.nix
Normal file
115
hosts/by-name/servo/services/jellyfin.nix
Normal file
@@ -0,0 +1,115 @@
|
||||
# configuration options (today i don't store my config in nix):
|
||||
#
|
||||
# - jellyfin-web can be statically configured (result/share/jellyfin-web/config.json)
|
||||
# - <https://jellyfin.org/docs/general/clients/web-config>
|
||||
# - configure server list, plugins, "menuLinks", colors
|
||||
#
|
||||
# - jellfyin server is configured in /var/lib/jellfin/
|
||||
# - root/default/<LibraryType>/
|
||||
# - <LibraryName>.mblink: contains the directory name where this library lives
|
||||
# - options.xml: contains preferences which were defined in the web UI during import
|
||||
# - e.g. `EnablePhotos`, `EnableChapterImageExtraction`, etc.
|
||||
# - config/encoding.xml: transcoder settings
|
||||
# - config/system.xml: misc preferences like log file duration, audiobook resume settings, etc.
|
||||
# - data/jellyfin.db: maybe account definitions? internal state?
|
||||
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
# identical to:
|
||||
# services.jellyfin.openFirewall = true;
|
||||
# N.B.: these are all for the LAN, so we don't go through `sane.services.wan-ports`.
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
# https://jellyfin.org/docs/general/networking/index.html
|
||||
1900 # UPnP service discovery
|
||||
7359 # Jellyfin-specific (?) client discovery
|
||||
];
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
8096 # HTTP (for the LAN)
|
||||
8920 # HTTPS (for the LAN)
|
||||
];
|
||||
sane.persist.sys.plaintext = [
|
||||
{ user = "jellyfin"; group = "jellyfin"; mode = "0700"; directory = "/var/lib/jellyfin"; }
|
||||
];
|
||||
sane.fs."/var/lib/jellyfin/config/logging.json" = {
|
||||
# "Emby.Dlna" logging: <https://jellyfin.org/docs/general/networking/dlna>
|
||||
symlink.text = ''
|
||||
{
|
||||
"Serilog": {
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Warning",
|
||||
"System": "Warning",
|
||||
"Emby.Dlna": "Debug",
|
||||
"Emby.Dlna.Eventing": "Debug"
|
||||
}
|
||||
},
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "Console",
|
||||
"Args": {
|
||||
"outputTemplate": "[{Timestamp:HH:mm:ss}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message:lj}{NewLine}{Exception}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Enrich": [ "FromLogContext", "WithThreadId" ]
|
||||
}
|
||||
}
|
||||
'';
|
||||
wantedBeforeBy = [ "jellyfin.service" ];
|
||||
};
|
||||
|
||||
# Jellyfin multimedia server
|
||||
# this is mostly taken from the official jellfin.org docs
|
||||
services.nginx.virtualHosts."jelly.uninsane.org" = {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
# inherit kTLS;
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8096";
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
|
||||
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
|
||||
proxy_buffering off;
|
||||
'';
|
||||
};
|
||||
# locations."/web/" = {
|
||||
# proxyPass = "http://127.0.0.1:8096/web/index.html";
|
||||
# extraConfig = ''
|
||||
# proxy_set_header Host $host;
|
||||
# proxy_set_header X-Real-IP $remote_addr;
|
||||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
# proxy_set_header X-Forwarded-Proto $scheme;
|
||||
# proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
# proxy_set_header X-Forwarded-Host $http_host;
|
||||
# '';
|
||||
# };
|
||||
locations."/socket" = {
|
||||
proxyPass = "http://127.0.0.1:8096";
|
||||
extraConfig = ''
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."jelly" = "native";
|
||||
|
||||
services.jellyfin.enable = true;
|
||||
}
|
@@ -13,5 +13,5 @@
|
||||
locations."/".proxyPass = "http://127.0.0.1:8013";
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."w" = [ "native" ];
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."w" = "native";
|
||||
}
|
22
hosts/by-name/servo/services/komga.nix
Normal file
22
hosts/by-name/servo/services/komga.nix
Normal file
@@ -0,0 +1,22 @@
|
||||
{ config, ... }:
|
||||
let
|
||||
svc-cfg = config.services.komga;
|
||||
inherit (svc-cfg) user group port stateDir;
|
||||
in
|
||||
{
|
||||
sane.persist.sys.plaintext = [
|
||||
{ inherit user group; mode = "0700"; directory = stateDir; }
|
||||
];
|
||||
|
||||
services.komga.enable = true;
|
||||
services.komga.port = 11319; # chosen at random
|
||||
|
||||
services.nginx.virtualHosts."komga.uninsane.org" = {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${builtins.toString port}";
|
||||
};
|
||||
};
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."komga" = "native";
|
||||
}
|
58
hosts/by-name/servo/services/lemmy.nix
Normal file
58
hosts/by-name/servo/services/lemmy.nix
Normal file
@@ -0,0 +1,58 @@
|
||||
# docs:
|
||||
# - <repo:LemmyNet/lemmy:docker/federation/nginx.conf>
|
||||
# - <repo:LemmyNet/lemmy:docker/nginx.conf>
|
||||
# - <repo:LemmyNet/lemmy-ansible:templates/nginx.conf>
|
||||
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
inherit (builtins) toString;
|
||||
inherit (lib) mkForce;
|
||||
uiPort = 1234; # default ui port is 1234
|
||||
backendPort = 8536; # default backend port is 8536
|
||||
# - i guess the "backend" port is used for federation?
|
||||
in {
|
||||
services.lemmy = {
|
||||
enable = true;
|
||||
settings.hostname = "lemmy.uninsane.org";
|
||||
settings.federation.enabled = true;
|
||||
# federation.debug forces outbound federation queries to be run synchronously
|
||||
# settings.federation.debug = true;
|
||||
settings.port = backendPort;
|
||||
ui.port = uiPort;
|
||||
database.createLocally = true;
|
||||
nginx.enable = true;
|
||||
};
|
||||
|
||||
systemd.services.lemmy.serviceConfig = {
|
||||
# fix to use a normal user so we can configure perms correctly
|
||||
DynamicUser = mkForce false;
|
||||
User = "lemmy";
|
||||
Group = "lemmy";
|
||||
};
|
||||
systemd.services.lemmy.environment = {
|
||||
RUST_BACKTRACE = "full";
|
||||
# RUST_LOG = "debug";
|
||||
# upstream defaults LEMMY_DATABASE_URL = "postgres:///lemmy?host=/run/postgresql";
|
||||
# - Postgres complains that we didn't specify a user
|
||||
# lemmy formats the url as:
|
||||
# - postgres://{user}:{password}@{host}:{port}/{database}
|
||||
# SO suggests (https://stackoverflow.com/questions/3582552/what-is-the-format-for-the-postgresql-connection-string-url):
|
||||
# - postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]
|
||||
# LEMMY_DATABASE_URL = "postgres://lemmy@/run/postgresql"; # connection to server on socket "/run/postgresql/.s.PGSQL.5432" failed: FATAL: database "run/postgresql" does not exist
|
||||
# LEMMY_DATABASE_URL = "postgres://lemmy?host=/run/postgresql"; # no PostgreSQL user name specified in startup packet
|
||||
# LEMMY_DATABASE_URL = mkForce "postgres://lemmy@?host=/run/postgresql"; # WORKS
|
||||
LEMMY_DATABASE_URL = mkForce "postgres://lemmy@/lemmy?host=/run/postgresql";
|
||||
};
|
||||
users.groups.lemmy = {};
|
||||
users.users.lemmy = {
|
||||
group = "lemmy";
|
||||
isSystemUser = true;
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."lemmy.uninsane.org" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."lemmy" = "native";
|
||||
}
|
@@ -1,17 +1,21 @@
|
||||
# docs: https://nixos.wiki/wiki/Matrix
|
||||
# docs: https://nixos.org/manual/nixos/stable/index.html#module-services-matrix-synapse
|
||||
# docs: <https://nixos.wiki/wiki/Matrix>
|
||||
# docs: <https://nixos.org/manual/nixos/stable/index.html#module-services-matrix-synapse>
|
||||
# example config: <https://github.com/matrix-org/synapse/blob/develop/docs/sample_config.yaml>
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./discord-puppet.nix
|
||||
# ./irc.nix
|
||||
./irc.nix
|
||||
./signal.nix
|
||||
];
|
||||
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.sys.plaintext = [
|
||||
{ user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/matrix-synapse"; }
|
||||
];
|
||||
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.server_name = "uninsane.org";
|
||||
|
||||
@@ -38,11 +42,14 @@
|
||||
}
|
||||
];
|
||||
|
||||
services.matrix-synapse.settings.x_forwarded = true; # because we proxy matrix behind nginx
|
||||
services.matrix-synapse.settings.max_upload_size = "100M"; # default is "50M"
|
||||
|
||||
services.matrix-synapse.settings.admin_contact = "admin.matrix@uninsane.org";
|
||||
services.matrix-synapse.settings.registrations_require_3pid = [ "email" ];
|
||||
|
||||
services.matrix-synapse.extraConfigFiles = [
|
||||
config.sops.secrets.matrix_synapse_secrets.path
|
||||
config.sops.secrets."matrix_synapse_secrets.yaml".path
|
||||
];
|
||||
|
||||
# services.matrix-synapse.extraConfigFiles = [builtins.toFile "matrix-synapse-extra-config" ''
|
||||
@@ -91,6 +98,10 @@
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8008";
|
||||
extraConfig = ''
|
||||
# allow uploading large files (matrix enforces a separate limit, downstream)
|
||||
client_max_body_size 512m;
|
||||
'';
|
||||
};
|
||||
# redirect browsers to the web client.
|
||||
# i don't think native matrix clients ever fetch the root.
|
||||
@@ -122,13 +133,12 @@
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
CNAME."matrix" = [ "native" ];
|
||||
CNAME."web.matrix" = [ "native" ];
|
||||
CNAME."matrix" = "native";
|
||||
CNAME."web.matrix" = "native";
|
||||
};
|
||||
|
||||
|
||||
sops.secrets.matrix_synapse_secrets = {
|
||||
sopsFile = ../../../../secrets/servo.yaml;
|
||||
sops.secrets."matrix_synapse_secrets.yaml" = {
|
||||
owner = config.users.users.matrix-synapse.name;
|
||||
};
|
||||
}
|
@@ -1,6 +1,11 @@
|
||||
{ lib, ... }:
|
||||
|
||||
# XXX mx-discord-puppet uses nodejs_14 which is EOL
|
||||
# - mx-discord-puppet is abandoned upstream _and_ in nixpkgs
|
||||
# - recommended to use mautrix-discord: <https://github.com/NixOS/nixpkgs/pull/200462>
|
||||
lib.mkIf false
|
||||
{
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.sys.plaintext = [
|
||||
{ user = "matrix-synapse"; group = "matrix-synapse"; directory = "/var/lib/mx-puppet-discord"; }
|
||||
];
|
||||
|
||||
@@ -43,6 +48,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
# TODO: should use a dedicated user
|
||||
systemd.services.mx-puppet-discord.serviceConfig = {
|
||||
# fix up to not use /var/lib/private, but just /var/lib
|
||||
DynamicUser = lib.mkForce false;
|
@@ -0,0 +1,13 @@
|
||||
diff --git a/src/irc/ConnectionInstance.ts b/src/irc/ConnectionInstance.ts
|
||||
index 688036ca..3373fa27 100644
|
||||
--- a/src/irc/ConnectionInstance.ts
|
||||
+++ b/src/irc/ConnectionInstance.ts
|
||||
@@ -149,7 +149,7 @@ export class ConnectionInstance {
|
||||
if (this.dead) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
- ircReason = ircReason || reason;
|
||||
+ ircReason = "bye"; // don't reveal through the IRC quit message that we're a bridge
|
||||
log.info(
|
||||
"disconnect()ing %s@%s - %s", this.nick, this.domain, reason
|
||||
);
|
50
hosts/by-name/servo/services/matrix/irc-no-reveal-mxid.patch
Normal file
50
hosts/by-name/servo/services/matrix/irc-no-reveal-mxid.patch
Normal file
@@ -0,0 +1,50 @@
|
||||
diff --git a/config.schema.yml b/config.schema.yml
|
||||
index 2e71c8d6..42ba8ba1 100644
|
||||
--- a/config.schema.yml
|
||||
+++ b/config.schema.yml
|
||||
@@ -433,7 +433,7 @@ properties:
|
||||
type: "boolean"
|
||||
realnameFormat:
|
||||
type: "string"
|
||||
- enum: ["mxid","reverse-mxid"]
|
||||
+ enum: ["mxid","reverse-mxid","localpart"]
|
||||
ipv6:
|
||||
type: "object"
|
||||
properties:
|
||||
diff --git a/src/irc/IdentGenerator.ts b/src/irc/IdentGenerator.ts
|
||||
index 7a2b5cf1..50f7815a 100644
|
||||
--- a/src/irc/IdentGenerator.ts
|
||||
+++ b/src/irc/IdentGenerator.ts
|
||||
@@ -74,6 +74,9 @@ export class IdentGenerator {
|
||||
else if (server.getRealNameFormat() === "reverse-mxid") {
|
||||
realname = IdentGenerator.sanitiseRealname(IdentGenerator.switchAroundMxid(matrixUser));
|
||||
}
|
||||
+ else if (server.getRealNameFormat() == "localpart") {
|
||||
+ realname = IdentGenerator.sanitiseRealname(matrixUser.localpart);
|
||||
+ }
|
||||
else {
|
||||
throw Error('Invalid value for realNameFormat');
|
||||
}
|
||||
diff --git a/src/irc/IrcServer.ts b/src/irc/IrcServer.ts
|
||||
index 2af73ab4..895b9783 100644
|
||||
--- a/src/irc/IrcServer.ts
|
||||
+++ b/src/irc/IrcServer.ts
|
||||
@@ -101,7 +101,7 @@ export interface IrcServerConfig {
|
||||
};
|
||||
lineLimit: number;
|
||||
userModes?: string;
|
||||
- realnameFormat?: "mxid"|"reverse-mxid";
|
||||
+ realnameFormat?: "mxid"|"reverse-mxid"|"localpart";
|
||||
pingTimeoutMs: number;
|
||||
pingRateMs: number;
|
||||
kickOn: {
|
||||
@@ -289,7 +289,7 @@ export class IrcServer {
|
||||
return this.config.ircClients.userModes || "";
|
||||
}
|
||||
|
||||
- public getRealNameFormat(): "mxid"|"reverse-mxid" {
|
||||
+ public getRealNameFormat(): "mxid"|"reverse-mxid"|"localpart" {
|
||||
return this.config.ircClients.realnameFormat || "mxid";
|
||||
}
|
||||
|
||||
|
156
hosts/by-name/servo/services/matrix/irc.nix
Normal file
156
hosts/by-name/servo/services/matrix/irc.nix
Normal file
@@ -0,0 +1,156 @@
|
||||
# config docs:
|
||||
# - <https://github.com/matrix-org/matrix-appservice-irc/blob/develop/config.sample.yaml>
|
||||
# TODO: /quit message for bridged users reveals to IRC users that i'm using a bridge;
|
||||
# probably want to remove that.
|
||||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
ircServer = { name, additionalAddresses ? [], sasl ? true }: let
|
||||
lowerName = lib.toLower name;
|
||||
in {
|
||||
# XXX sasl: appservice doesn't support NickServ identification (only SASL, or PASS if sasl = false)
|
||||
inherit name additionalAddresses sasl;
|
||||
port = 6697;
|
||||
ssl = true;
|
||||
botConfig = {
|
||||
# bot has no presence in IRC channel; only real Matrix users
|
||||
enabled = false;
|
||||
# this is the IRC username/nickname *of the bot* (not visible in channels): not of the end-user.
|
||||
# the irc username/nick of a mapped Matrix user is determined further down in `ircClients` section.
|
||||
# if `enabled` is false, then this name probably never shows up on the IRC side (?)
|
||||
nick = "uninsane";
|
||||
username = "uninsane";
|
||||
joinChannelsIfNoUsers = false;
|
||||
};
|
||||
dynamicChannels = {
|
||||
enabled = true;
|
||||
aliasTemplate = "#irc_${lowerName}_$CHANNEL";
|
||||
published = false; # false => irc rooms aren't listed in homeserver public rooms list
|
||||
federate = false; # false => Matrix users from other homeservers can't join IRC channels
|
||||
};
|
||||
ircClients = {
|
||||
nickTemplate = "$LOCALPARTsane"; # @colin:uninsane.org (Matrix) -> colinsane (IRC)
|
||||
realnameFormat = "reverse-mxid"; # @colin:uninsane.org (Matrix) -> org.uninsane:colin (IRC)
|
||||
# realnameFormat = "localpart"; # @colin:uninsane.org (Matrix) -> colin (IRC) -- but requires the mxid patch below
|
||||
# by default, Matrix will convert messages greater than (3) lines into a pastebin-like URL to send to IRC.
|
||||
lineLimit = 20;
|
||||
# Rizon in particular allows only 4 connections from one IP before a 30min ban.
|
||||
# that's effectively reduced to 2 during a netsplit, or maybe during a restart.
|
||||
# - https://wiki.rizon.net/index.php?title=Connection/Session_Limit_Exemptions
|
||||
# especially, misconfigurations elsewhere in this config may cause hundreds of connections
|
||||
# so this is a safeguard.
|
||||
maxClients = 2;
|
||||
# don't have the bridge disconnect me from IRC when idle.
|
||||
idleTimeout = 0;
|
||||
concurrentReconnectLimit = 2;
|
||||
reconnectIntervalMs = 60000;
|
||||
kickOn = {
|
||||
# remove Matrix user from room when...
|
||||
channelJoinFailure = false;
|
||||
ircConnectionFailure = false;
|
||||
userQuit = true;
|
||||
};
|
||||
};
|
||||
matrixClients = {
|
||||
userTemplate = "@irc_${lowerName}_$NICK"; # the :uninsane.org part is appended automatically
|
||||
};
|
||||
|
||||
# this will let this user message the appservice with `!join #<IRCChannel>` and the rest "Just Works"
|
||||
"@colin:uninsane.org" = "admin";
|
||||
|
||||
membershipLists = {
|
||||
enabled = true;
|
||||
global = {
|
||||
ircToMatrix = {
|
||||
initial = true;
|
||||
incremental = true;
|
||||
requireMatrixJoined = false;
|
||||
};
|
||||
matrixToIrc = {
|
||||
initial = true;
|
||||
incremental = true;
|
||||
};
|
||||
};
|
||||
ignoreIdleUsersOnStartup = {
|
||||
enabled = false; # false => always bridge users, even if idle
|
||||
};
|
||||
};
|
||||
# sync room description?
|
||||
bridgeInfoState = {
|
||||
enabled = true;
|
||||
initial = true;
|
||||
};
|
||||
|
||||
# for per-user IRC password:
|
||||
# - invite @irc_${lowerName}_NickServ:uninsane.org to a DM and type `help` => register
|
||||
# - invite the matrix-appservice-irc user to a DM and type `!help` => add PW to database
|
||||
# to validate that i'm authenticated on the IRC network, DM @irc_${lowerName}_NickServ:uninsane.org:
|
||||
# - send: `STATUS colinsane`
|
||||
# - response should be `3`: "user recognized as owner via password identification"
|
||||
# passwordEncryptionKeyPath = "/path/to/privkey"; # appservice will generate its own if unspecified
|
||||
};
|
||||
in
|
||||
{
|
||||
|
||||
nixpkgs.overlays = [
|
||||
(next: prev: {
|
||||
matrix-appservice-irc = prev.matrix-appservice-irc.overrideAttrs (super: {
|
||||
patches = super.patches or [] ++ [
|
||||
./irc-no-reveal-bridge.patch
|
||||
# ./irc-no-reveal-mxid.patch
|
||||
];
|
||||
});
|
||||
})
|
||||
];
|
||||
|
||||
sane.persist.sys.plaintext = [
|
||||
# TODO: mode?
|
||||
{ user = "matrix-appservice-irc"; group = "matrix-appservice-irc"; directory = "/var/lib/matrix-appservice-irc"; }
|
||||
];
|
||||
|
||||
services.matrix-synapse.settings.app_service_config_files = [
|
||||
"/var/lib/matrix-appservice-irc/registration.yml" # auto-created by irc appservice
|
||||
];
|
||||
|
||||
services.matrix-appservice-irc.enable = true;
|
||||
services.matrix-appservice-irc.registrationUrl = "http://127.0.0.1:8009";
|
||||
services.matrix-appservice-irc.settings = {
|
||||
homeserver = {
|
||||
url = "http://127.0.0.1:8008";
|
||||
dropMatrixMessagesAfterSecs = 300;
|
||||
domain = "uninsane.org";
|
||||
enablePresence = true;
|
||||
bindPort = 9999;
|
||||
bindHost = "127.0.0.1";
|
||||
};
|
||||
|
||||
ircService = {
|
||||
servers = {
|
||||
"irc.esper.net" = ircServer {
|
||||
name = "esper";
|
||||
sasl = false;
|
||||
# notable channels:
|
||||
# - #merveilles
|
||||
};
|
||||
"irc.libera.chat" = ircServer {
|
||||
name = "libera";
|
||||
sasl = false;
|
||||
# notable channels:
|
||||
# - #hare
|
||||
};
|
||||
"irc.myanonamouse.net" = ircServer {
|
||||
name = "MyAnonamouse";
|
||||
additionalAddresses = [ "irc2.myanonamouse.net" ];
|
||||
sasl = false;
|
||||
};
|
||||
"irc.oftc.net" = ircServer {
|
||||
name = "oftc";
|
||||
# notable channels:
|
||||
# - #sxmo
|
||||
# - #sxmo-offtopic
|
||||
};
|
||||
"irc.rizon.net" = ircServer { name = "Rizon"; };
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
37
hosts/by-name/servo/services/matrix/signal.nix
Normal file
37
hosts/by-name/servo/services/matrix/signal.nix
Normal file
@@ -0,0 +1,37 @@
|
||||
# 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"; }
|
||||
];
|
||||
|
||||
# allow synapse to read the registration file
|
||||
users.users.matrix-synapse.extraGroups = [ "mautrix-signal" ];
|
||||
|
||||
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" = {
|
||||
mode = "0440";
|
||||
owner = config.users.users.mautrix-signal.name;
|
||||
group = config.users.users.matrix-synapse.name;
|
||||
};
|
||||
}
|
@@ -1,8 +1,8 @@
|
||||
{ ... }:
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
sane.impermanence.dirs = [
|
||||
{ user = "navidrome"; group = "navidrome"; directory = "/var/lib/private/navidrome"; }
|
||||
sane.persist.sys.plaintext = [
|
||||
{ user = "navidrome"; group = "navidrome"; directory = "/var/lib/navidrome"; }
|
||||
];
|
||||
services.navidrome.enable = true;
|
||||
services.navidrome.settings = {
|
||||
@@ -15,6 +15,20 @@
|
||||
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" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
@@ -22,5 +36,5 @@
|
||||
locations."/".proxyPass = "http://127.0.0.1:4533";
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."music" = [ "native" ];
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."music" = "native";
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
# docs: https://nixos.wiki/wiki/Nginx
|
||||
{ config, pkgs, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
# make the logs for this host "public" so that they show up in e.g. metrics
|
||||
publog = vhost: vhost // {
|
||||
publog = vhost: lib.attrsets.unionOfDisjoint vhost {
|
||||
extraConfig = (vhost.extraConfig or "") + ''
|
||||
access_log /var/log/nginx/public.log vcombined;
|
||||
'';
|
||||
@@ -13,7 +13,7 @@ let
|
||||
in
|
||||
{
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
sane.services.wan-ports.tcp = [ 80 443 ];
|
||||
|
||||
services.nginx.enable = true;
|
||||
services.nginx.appendConfig = ''
|
||||
@@ -120,9 +120,7 @@ in
|
||||
security.acme.acceptTerms = true;
|
||||
security.acme.defaults.email = "admin.acme@uninsane.org";
|
||||
|
||||
users.users.acme.uid = config.sane.allocations.acme-uid;
|
||||
users.groups.acme.gid = config.sane.allocations.acme-gid;
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.sys.plaintext = [
|
||||
# TODO: mode?
|
||||
{ user = "acme"; group = "acme"; directory = "/var/lib/acme"; }
|
||||
{ user = "colin"; group = "users"; directory = "/var/www/sites"; }
|
@@ -14,8 +14,8 @@
|
||||
'';
|
||||
};
|
||||
|
||||
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.sopsFile = ../../../secrets/servo.yaml;
|
||||
sane.services.nixserve.secretKeyFile = config.sops.secrets.nix_serve_privkey.path;
|
||||
}
|
23
hosts/by-name/servo/services/pict-rs.nix
Normal file
23
hosts/by-name/servo/services/pict-rs.nix
Normal file
@@ -0,0 +1,23 @@
|
||||
# pict-rs is an image database/store used by Lemmy.
|
||||
# i don't explicitly activate it here -- just adjust its defaults to be a bit friendlier
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.services.pict-rs;
|
||||
in
|
||||
{
|
||||
sane.persist.sys.plaintext = lib.mkIf cfg.enable [
|
||||
{ user = "pict-rs"; group = "pict-rs"; directory = cfg.dataDir; }
|
||||
];
|
||||
|
||||
systemd.services.pict-rs.serviceConfig = {
|
||||
# fix to use a normal user so we can configure perms correctly
|
||||
DynamicUser = lib.mkForce false;
|
||||
User = "pict-rs";
|
||||
Group = "pict-rs";
|
||||
};
|
||||
users.groups.pict-rs = {};
|
||||
users.users.pict-rs = {
|
||||
group = "pict-rs";
|
||||
isSystemUser = true;
|
||||
};
|
||||
}
|
@@ -6,12 +6,10 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.sys.plaintext = [
|
||||
# TODO: mode? could be more granular
|
||||
{ user = "pleroma"; group = "pleroma"; directory = "/var/lib/pleroma"; }
|
||||
];
|
||||
users.users.pleroma.uid = config.sane.allocations.pleroma-uid;
|
||||
users.groups.pleroma.gid = config.sane.allocations.pleroma-gid;
|
||||
services.pleroma.enable = true;
|
||||
services.pleroma.secretConfigFile = config.sops.secrets.pleroma_secrets.path;
|
||||
services.pleroma.configs = [
|
||||
@@ -113,7 +111,7 @@
|
||||
''
|
||||
];
|
||||
|
||||
systemd.services.pleroma.path = [
|
||||
systemd.services.pleroma.path = [
|
||||
# something inside pleroma invokes `sh` w/o specifying it by path, so this is needed to allow pleroma to start
|
||||
pkgs.bash
|
||||
# used by Pleroma to strip geo tags from uploads
|
||||
@@ -137,6 +135,11 @@
|
||||
# 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
|
||||
# TODO: enable publog?
|
||||
services.nginx.virtualHosts."fed.uninsane.org" = {
|
||||
@@ -179,10 +182,9 @@
|
||||
};
|
||||
};
|
||||
|
||||
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 = {
|
||||
sopsFile = ../../../secrets/servo.yaml;
|
||||
sops.secrets."pleroma_secrets" = {
|
||||
owner = config.users.users.pleroma.name;
|
||||
};
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.sys.plaintext = [
|
||||
# TODO: mode?
|
||||
{ user = "postgres"; group = "postgres"; directory = "/var/lib/postgresql"; }
|
||||
];
|
@@ -9,10 +9,10 @@
|
||||
# nixnet runs ejabberd, so revisiting that.
|
||||
lib.mkIf false
|
||||
{
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.sys.plaintext = [
|
||||
{ user = "prosody"; group = "prosody"; directory = "/var/lib/prosody"; }
|
||||
];
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
sane.services.wan-ports.tcp = [
|
||||
5222 # XMPP client -> server
|
||||
5269 # XMPP server -> server
|
||||
5280 # bosh
|
@@ -1,7 +1,7 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
sane.impermanence.dirs = [
|
||||
sane.persist.sys.plaintext = [
|
||||
# TODO: mode? we need this specifically for the stats tracking in .config/
|
||||
{ user = "transmission"; group = "transmission"; directory = "/var/lib/transmission"; }
|
||||
];
|
||||
@@ -27,7 +27,7 @@
|
||||
# units in kBps
|
||||
speed-limit-down = 3000;
|
||||
speed-limit-down-enabled = true;
|
||||
speed-limit-up = 300;
|
||||
speed-limit-up = 600;
|
||||
speed-limit-up-enabled = true;
|
||||
|
||||
# see: https://git.zknt.org/mirror/transmission/commit/cfce6e2e3a9b9d31a9dafedd0bdc8bf2cdb6e876?lang=bg-BG
|
||||
@@ -40,8 +40,8 @@
|
||||
# transmission will by default not allow the world to read its files.
|
||||
services.transmission.downloadDirPermissions = "775";
|
||||
|
||||
systemd.services.transmission.after = [ "wireguard-wg0.service" ];
|
||||
systemd.services.transmission.partOf = [ "wireguard-wg0.service" ];
|
||||
systemd.services.transmission.after = [ "wireguard-wg-ovpns.service" ];
|
||||
systemd.services.transmission.partOf = [ "wireguard-wg-ovpns.service" ];
|
||||
systemd.services.transmission.serviceConfig = {
|
||||
# run this behind the OVPN static VPN
|
||||
NetworkNamespacePath = "/run/netns/ovpns";
|
||||
@@ -75,6 +75,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."bt" = ["native"];
|
||||
sane.services.trust-dns.zones."uninsane.org".inet.CNAME."bt" = "native";
|
||||
}
|
||||
|
@@ -6,9 +6,10 @@
|
||||
sane.services.trust-dns.listenAddrsIPv4 = [
|
||||
# specify each address explicitly, instead of using "*".
|
||||
# this ensures responses are sent from the address at which the request was received.
|
||||
"192.168.0.5"
|
||||
config.sane.hosts.by-name."servo".lan-ip
|
||||
"10.0.1.5"
|
||||
];
|
||||
sane.services.trust-dns.quiet = true;
|
||||
|
||||
sane.services.trust-dns.zones."uninsane.org".TTL = 900;
|
||||
|
||||
@@ -21,25 +22,25 @@
|
||||
# Retry = how long secondary NS should wait until re-querying master after a failure (must be < Refresh)
|
||||
# Expire = how long secondary NS should continue to reply to queries after master fails (> Refresh + Retry)
|
||||
sane.services.trust-dns.zones."uninsane.org".inet = {
|
||||
SOA."@" = [''
|
||||
SOA."@" = ''
|
||||
ns1.uninsane.org. admin-dns.uninsane.org. (
|
||||
2022122101 ; Serial
|
||||
4h ; Refresh
|
||||
30m ; Retry
|
||||
7d ; Expire
|
||||
5m) ; Negative response TTL
|
||||
''];
|
||||
TXT."rev" = [ "2022122101" ];
|
||||
'';
|
||||
TXT."rev" = "2022122101";
|
||||
|
||||
# XXX NS records must also not be CNAME
|
||||
# it's best that we keep this identical, or a superset of, what org. lists as our NS.
|
||||
# so, org. can specify ns2/ns3 as being to the VPN, with no mention of ns1. we provide ns1 here.
|
||||
A."ns1" = [ "%NATIVE%" ];
|
||||
A."ns2" = [ "185.157.162.178" ];
|
||||
A."ns3" = [ "185.157.162.178" ];
|
||||
A."ovpns" = [ "185.157.162.178" ];
|
||||
A."native" = [ "%NATIVE%" ];
|
||||
A."@" = [ "%NATIVE%" ];
|
||||
A."ns1" = "%NATIVE%";
|
||||
A."ns2" = "185.157.162.178";
|
||||
A."ns3" = "185.157.162.178";
|
||||
A."ovpns" = "185.157.162.178";
|
||||
A."native" = "%NATIVE%";
|
||||
A."@" = "%NATIVE%";
|
||||
NS."@" = [
|
||||
"ns1.uninsane.org."
|
||||
"ns2.uninsane.org."
|
@@ -8,11 +8,8 @@ lib.mkIf false
|
||||
{
|
||||
sops.secrets."mediawiki_pw" = {
|
||||
owner = config.users.users.mediawiki.name;
|
||||
sopsFile = ../../../secrets/servo.yaml;
|
||||
};
|
||||
|
||||
users.users.mediawiki.uid = config.sane.allocations.mediawiki-uid;
|
||||
|
||||
services.mediawiki.enable = true;
|
||||
services.mediawiki.name = "Uninsane Wiki";
|
||||
services.mediawiki.passwordFile = config.sops.secrets.mediawiki_pw.path;
|
@@ -1,18 +0,0 @@
|
||||
{ lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
# TODO: don't need to depend on binsh if we were to use a nix-style shebang
|
||||
system.activationScripts.linkBluetoothKeys = let
|
||||
unwrapped = ../../scripts/install-bluetooth;
|
||||
install-bluetooth = pkgs.writeShellApplication {
|
||||
name = "install-bluetooth";
|
||||
runtimeInputs = with pkgs; [ coreutils gnused ];
|
||||
text = ''${unwrapped} "$@"'';
|
||||
};
|
||||
in (lib.stringAfter
|
||||
[ "setupSecrets" "binsh" ]
|
||||
''
|
||||
${install-bluetooth}/bin/install-bluetooth /run/secrets/bt
|
||||
''
|
||||
);
|
||||
}
|
@@ -1,56 +1,77 @@
|
||||
{ pkgs, ... }:
|
||||
{ lib, pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
./bluetooth.nix
|
||||
./feeds.nix
|
||||
./fs.nix
|
||||
./hardware
|
||||
./i2p.nix
|
||||
./hardware.nix
|
||||
./home
|
||||
./ids.nix
|
||||
./machine-id.nix
|
||||
./net.nix
|
||||
./persist.nix
|
||||
./programs
|
||||
./secrets.nix
|
||||
./ssh.nix
|
||||
./users.nix
|
||||
./vpn.nix
|
||||
];
|
||||
|
||||
sane.home-manager.enable = true;
|
||||
sane.nixcache.enable-trusted-keys = true;
|
||||
sane.packages.enableConsolePkgs = true;
|
||||
sane.packages.enableSystemPkgs = true;
|
||||
sane.nixcache.enable = lib.mkDefault true;
|
||||
sane.persist.enable = lib.mkDefault true;
|
||||
sane.programs.sysadminUtils.enableFor.system = lib.mkDefault true;
|
||||
sane.programs.consoleUtils.enableFor.user.colin = lib.mkDefault true;
|
||||
|
||||
sane.impermanence.dirs = [
|
||||
"/var/log"
|
||||
"/var/backup" # for e.g. postgres dumps
|
||||
# TODO: move elsewhere
|
||||
"/var/lib/alsa" # preserve output levels, default devices
|
||||
"/var/lib/bluetooth" # preserve bluetooth handshakes
|
||||
"/var/lib/colord" # preserve color calibrations (?)
|
||||
"/var/lib/machines" # maybe not needed, but would be painful to add a VM and forget.
|
||||
];
|
||||
# some services which use private directories error if the parent (/var/lib/private) isn't 700.
|
||||
sane.fs."/var/lib/private".dir.acl.mode = "0700";
|
||||
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
nixpkgs.config.allowBroken = true; # NIXPKGS_ALLOW_BROKEN
|
||||
|
||||
# time.timeZone = "America/Los_Angeles";
|
||||
time.timeZone = "Etc/UTC"; # DST is too confusing for me => use a stable timezone
|
||||
|
||||
# allow `nix flake ...` command
|
||||
# TODO: is this still required?
|
||||
nix.extraOptions = ''
|
||||
experimental-features = nix-command flakes
|
||||
'';
|
||||
# allow `nix-shell` (and probably nix-index?) to locate our patched and custom packages
|
||||
nix.nixPath = [
|
||||
"nixpkgs=${pkgs.path}"
|
||||
"nixpkgs-overlays=${../..}/overlays"
|
||||
];
|
||||
# hardlinks identical files in the nix store to save 25-35% disk space.
|
||||
# unclear _when_ this occurs. it's not a service.
|
||||
# does the daemon continually scan the nix store?
|
||||
# does the builder use some content-addressed db to efficiently dedupe?
|
||||
nix.settings.auto-optimise-store = true;
|
||||
|
||||
# TODO: move this into home-manager?
|
||||
fonts = {
|
||||
enableDefaultFonts = true;
|
||||
fonts = with pkgs; [ font-awesome twitter-color-emoji hack-font ];
|
||||
fonts = with pkgs; [ font-awesome noto-fonts-emoji hack-font ];
|
||||
fontconfig.enable = true;
|
||||
fontconfig.defaultFonts = {
|
||||
emoji = [ "Font Awesome 6 Free" "Twitter Color Emoji" ];
|
||||
emoji = [ "Font Awesome 6 Free" "Noto Color Emoji" ];
|
||||
monospace = [ "Hack" ];
|
||||
serif = [ "DejaVu Serif" ];
|
||||
sansSerif = [ "DejaVu Sans" ];
|
||||
};
|
||||
};
|
||||
|
||||
# XXX: twitter-color-emoji doesn't cross-compile; but not-fonts-emoji does
|
||||
# fonts = {
|
||||
# enableDefaultFonts = true;
|
||||
# fonts = with pkgs; [ font-awesome twitter-color-emoji hack-font ];
|
||||
# fontconfig.enable = true;
|
||||
# fontconfig.defaultFonts = {
|
||||
# emoji = [ "Font Awesome 6 Free" "Twitter Color Emoji" ];
|
||||
# monospace = [ "Hack" ];
|
||||
# serif = [ "DejaVu Serif" ];
|
||||
# sansSerif = [ "DejaVu Sans" ];
|
||||
# };
|
||||
# };
|
||||
|
||||
# disable non-required packages like nano, perl, rsync, strace
|
||||
environment.defaultPackages = [];
|
||||
|
||||
@@ -66,8 +87,20 @@
|
||||
# NIXOS_OZONE_WL = "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
|
||||
# hopefully picked up by gdb automatically?
|
||||
|
246
hosts/common/feeds.nix
Normal file
246
hosts/common/feeds.nix
Normal file
@@ -0,0 +1,246 @@
|
||||
# candidates:
|
||||
# - The Nonlinear Library (podcast): <https://forum.effectivealtruism.org/posts/JTZTBienqWEAjGDRv/listen-to-more-ea-content-with-the-nonlinear-library>
|
||||
# - has ~10 posts per day, text-to-speech; i would need better tagging before adding this
|
||||
# - <https://www.metaculus.com/questions/11102/introducing-the-metaculus-journal-podcast/>
|
||||
# - dead since 2022/10 - 2023/03
|
||||
|
||||
{ lib, sane-data, ... }:
|
||||
let
|
||||
hourly = { freq = "hourly"; };
|
||||
daily = { freq = "daily"; };
|
||||
weekly = { freq = "weekly"; };
|
||||
infrequent = { freq = "infrequent"; };
|
||||
|
||||
art = { cat = "art"; };
|
||||
humor = { cat = "humor"; };
|
||||
pol = { cat = "pol"; }; # or maybe just "social"
|
||||
rat = { cat = "rat"; };
|
||||
tech = { cat = "tech"; };
|
||||
uncat = { cat = "uncat"; };
|
||||
|
||||
text = { format = "text"; };
|
||||
img = { format = "image"; };
|
||||
|
||||
mkRss = format: url: { inherit url format; } // uncat // infrequent;
|
||||
# format-specific helpers
|
||||
mkText = mkRss "text";
|
||||
mkImg = mkRss "image";
|
||||
mkPod = mkRss "podcast";
|
||||
|
||||
# host-specific helpers
|
||||
mkSubstack = subdomain: { substack = subdomain; };
|
||||
|
||||
fromDb = name:
|
||||
let
|
||||
raw = sane-data.feeds."${name}";
|
||||
in {
|
||||
url = raw.url;
|
||||
# not sure the exact mapping with velocity here: entries per day?
|
||||
freq = lib.mkIf (raw.velocity or 0 != 0) (lib.mkDefault (
|
||||
if raw.velocity > 2 then
|
||||
"hourly"
|
||||
else if raw.velocity > 0.5 then
|
||||
"daily"
|
||||
else if raw.velocity > 0.1 then
|
||||
"weekly"
|
||||
else
|
||||
"infrequent"
|
||||
));
|
||||
} // lib.optionalAttrs (raw.is_podcast or false) {
|
||||
format = "podcast";
|
||||
} // lib.optionalAttrs (raw.title or "" != "") {
|
||||
title = lib.mkDefault raw.title;
|
||||
};
|
||||
|
||||
podcasts = [
|
||||
(fromDb "lexfridman.com/podcast" // rat)
|
||||
## Astral Codex Ten
|
||||
(fromDb "sscpodcast.libsyn.com" // rat)
|
||||
## Less Wrong Curated
|
||||
(fromDb "feeds.libsyn.com/421877" // rat)
|
||||
## Econ Talk
|
||||
(fromDb "feeds.simplecast.com/wgl4xEgL" // rat)
|
||||
## Cory Doctorow -- both podcast & text entries
|
||||
(fromDb "craphound.com" // pol)
|
||||
## Maggie Killjoy -- referenced by Cory Doctorow
|
||||
(fromDb "omny.fm/shows/cool-people-who-did-cool-stuff" // pol)
|
||||
(fromDb "congressionaldish.libsyn.com" // pol)
|
||||
# (mkPod "https://podcasts.la.utexas.edu/this-is-democracy/feed/podcast/" // pol // weekly)
|
||||
## Civboot -- https://anchor.fm/civboot
|
||||
(fromDb "anchor.fm/s/34c7232c/podcast/rss" // tech)
|
||||
## Emerge: making sense of what's next -- <https://www.whatisemerging.com/emergepodcast>
|
||||
(mkPod "https://anchor.fm/s/21bc734/podcast/rss" // pol // infrequent)
|
||||
(fromDb "feeds.feedburner.com/80000HoursPodcast" // rat)
|
||||
## Daniel Huberman on sleep
|
||||
(fromDb "feeds.megaphone.fm/hubermanlab" // uncat)
|
||||
## Multidisciplinary Association for Psychedelic Studies
|
||||
(fromDb "mapspodcast.libsyn.com" // uncat)
|
||||
(fromDb "allinchamathjason.libsyn.com" // pol)
|
||||
(fromDb "acquired.libsyn.com" // tech)
|
||||
## ACQ2 - more "Acquired" episodes
|
||||
(fromDb "acquiredlpbonussecretsecret.libsyn.com" // tech)
|
||||
# The Intercept - Deconstructed; also available: <rss.acast.com/deconstructed>
|
||||
(fromDb "rss.prod.firstlook.media/deconstructed/podcast.rss" // pol)
|
||||
## The Daily
|
||||
(mkPod "https://feeds.simplecast.com/54nAGcIl" // pol // daily)
|
||||
# The Intercept - Intercepted; also available: <https://rss.acast.com/intercepted-with-jeremy-scahill>
|
||||
(fromDb "rss.prod.firstlook.media/intercepted/podcast.rss" // pol)
|
||||
(fromDb "podcast.posttv.com/itunes/post-reports.xml" // pol)
|
||||
## Eric Weinstein
|
||||
(fromDb "rss.art19.com/the-portal" // rat)
|
||||
(fromDb "darknetdiaries.com" // tech)
|
||||
## Radiolab -- also available here, but ONLY OVER HTTP: <http://feeds.wnyc.org/radiolab>
|
||||
(fromDb "feeds.feedburner.com/radiolab" // pol)
|
||||
## Sam Harris
|
||||
(fromDb "wakingup.libsyn.com" // pol)
|
||||
## 99% Invisible -- also available here: <https://feeds.simplecast.com/BqbsxVfO>
|
||||
(fromDb "feeds.99percentinvisible.org/99percentinvisible" // pol)
|
||||
(fromDb "rss.acast.com/ft-tech-tonic" // tech)
|
||||
(fromDb "feeds.feedburner.com/dancarlin/history" // rat)
|
||||
(fromDb "rss.art19.com/60-minutes" // pol)
|
||||
## The Verge - Decoder
|
||||
(fromDb "feeds.megaphone.fm/recodedecode" // tech)
|
||||
## Matrix (chat) Live
|
||||
(fromDb "feed.podbean.com/matrixlive/feed.xml" // tech)
|
||||
## Michael Malice - Your Welcome -- also available here: <https://origin.podcastone.com/podcast?categoryID2=2232>
|
||||
(fromDb "rss.art19.com/your-welcome" // pol)
|
||||
(fromDb "seattlenice.buzzsprout.com" // pol)
|
||||
## Sci-Fi? has Peter Watts; author of No Moods, Ads or Cutesy Fucking Icons (rifters.com)
|
||||
(fromDb "talesfromthebridge.buzzsprout.com" // tech)
|
||||
## UnNamed Reverse Engineering Podcast
|
||||
(fromDb "reverseengineering.libsyn.com/rss" // tech)
|
||||
## The Witch Trials of J.K. Rowling
|
||||
## - <https://www.thefp.com/witchtrials>
|
||||
(mkPod "https://feeds.megaphone.fm/RUNMED9919162779" // pol // infrequent)
|
||||
];
|
||||
|
||||
texts = [
|
||||
# AGGREGATORS (> 1 post/day)
|
||||
(fromDb "lwn.net" // tech)
|
||||
(fromDb "lesswrong.com" // rat)
|
||||
# (fromDb "econlib.org" // pol)
|
||||
|
||||
# AGGREGATORS (< 1 post/day)
|
||||
(fromDb "palladiummag.com" // uncat)
|
||||
(fromDb "profectusmag.com" // uncat)
|
||||
(fromDb "semiaccurate.com" // tech)
|
||||
(mkText "https://linuxphoneapps.org/blog/atom.xml" // tech // infrequent)
|
||||
(fromDb "tuxphones.com" // tech)
|
||||
(fromDb "spectrum.ieee.org" // tech)
|
||||
(fromDb "theregister.com" // tech)
|
||||
(fromDb "thisweek.gnome.org" // tech)
|
||||
# more nixos stuff here, but unclear how to subscribe: <https://nixos.org/blog/categories.html>
|
||||
(mkText "https://nixos.org/blog/announcements-rss.xml" // tech // infrequent)
|
||||
(mkText "https://nixos.org/blog/stories-rss.xml" // tech // weekly)
|
||||
## 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
|
||||
(fromDb "rifters.com/crawl" // uncat)
|
||||
|
||||
# DEVELOPERS
|
||||
(fromDb "blog.jmp.chat" // tech)
|
||||
(fromDb "uninsane.org" // tech)
|
||||
(fromDb "ascii.textfiles.com" // tech) # Jason Scott
|
||||
(fromDb "xn--gckvb8fzb.com" // tech)
|
||||
(fromDb "mg.lol" // tech)
|
||||
# (fromDb "drewdevault.com" // tech)
|
||||
## Ken Shirriff
|
||||
(fromDb "righto.com" // tech)
|
||||
## shared blog by a few NixOS devs, notably onny
|
||||
(fromDb "project-insanity.org" // tech)
|
||||
## Vitalik Buterin
|
||||
(fromDb "vitalik.ca" // tech)
|
||||
## ian (Sanctuary)
|
||||
(fromDb "sagacioussuricata.com" // tech)
|
||||
## Bunnie Juang
|
||||
(fromDb "bunniestudios.com" // tech)
|
||||
(fromDb "blog.danieljanus.pl" // tech)
|
||||
(fromDb "ianthehenry.com" // tech)
|
||||
(fromDb "bitbashing.io" // tech)
|
||||
(fromDb "idiomdrottning.org" // uncat)
|
||||
(mkText "https://anish.lakhwara.com/home.html" // tech // weekly)
|
||||
(fromDb "jefftk.com" // tech)
|
||||
(fromDb "pomeroyb.com" // tech)
|
||||
(mkText "https://til.simonwillison.net/tils/feed.atom" // tech // weekly)
|
||||
|
||||
# TECH PROJECTS
|
||||
(fromDb "blog.rust-lang.org" // tech)
|
||||
|
||||
# (TECH; POL) COMMENTATORS
|
||||
## Matt Webb -- engineering-ish, but dreamy
|
||||
(fromDb "interconnected.org/home/feed" // rat)
|
||||
(fromDb "edwardsnowden.substack.com" // pol // text)
|
||||
## Julia Evans
|
||||
(mkText "https://jvns.ca/atom.xml" // tech // weekly)
|
||||
(mkText "http://benjaminrosshoffman.com/feed" // pol // weekly)
|
||||
## Ben Thompson
|
||||
(mkText "https://www.stratechery.com/rss" // pol // weekly)
|
||||
## Balaji
|
||||
(fromDb "balajis.com" // pol)
|
||||
(fromDb "ben-evans.com/benedictevans" // pol)
|
||||
(fromDb "lynalden.com" // pol)
|
||||
(fromDb "austinvernon.site" // tech)
|
||||
(mkSubstack "oversharing" // pol // daily)
|
||||
(mkSubstack "byrnehobart" // pol // infrequent)
|
||||
# (mkSubstack "doomberg" // tech // weekly) # articles are all pay-walled
|
||||
## David Rosenthal
|
||||
(fromDb "blog.dshr.org" // pol)
|
||||
## Matt Levine
|
||||
(mkText "https://www.bloomberg.com/opinion/authors/ARbTQlRLRjE/matthew-s-levine.rss" // pol // weekly)
|
||||
(fromDb "stpeter.im/atom.xml" // pol)
|
||||
## Peter Saint-Andre -- side project of stpeter.im
|
||||
(fromDb "philosopher.coach" // rat)
|
||||
(fromDb "morningbrew.com/feed" // pol)
|
||||
|
||||
# RATIONALITY/PHILOSOPHY/ETC
|
||||
(mkSubstack "samkriss" // humor // infrequent)
|
||||
(fromDb "unintendedconsequenc.es" // rat)
|
||||
(fromDb "applieddivinitystudies.com" // rat)
|
||||
(fromDb "slimemoldtimemold.com" // rat)
|
||||
(fromDb "richardcarrier.info" // rat)
|
||||
(fromDb "gwern.net" // rat)
|
||||
## Jason Crawford
|
||||
(fromDb "rootsofprogress.org" // rat)
|
||||
## Robin Hanson
|
||||
(fromDb "overcomingbias.com" // rat)
|
||||
## Scott Alexander
|
||||
(mkSubstack "astralcodexten" // rat // daily)
|
||||
## Paul Christiano
|
||||
(fromDb "sideways-view.com" // rat)
|
||||
## Sean Carroll
|
||||
(fromDb "preposterousuniverse.com" // rat)
|
||||
(mkSubstack "eliqian" // rat // weekly)
|
||||
(mkText "https://acoup.blog/feed" // rat // weekly)
|
||||
|
||||
## mostly dating topics. not advice, or humor, but looking through a social lens
|
||||
(fromDb "putanumonit.com" // rat)
|
||||
|
||||
# LOCAL
|
||||
(fromDb "capitolhillseattle.com" // pol)
|
||||
|
||||
# CODE
|
||||
# (mkText "https://github.com/Kaiteki-Fedi/Kaiteki/commits/master.atom" // tech // infrequent)
|
||||
];
|
||||
|
||||
images = [
|
||||
(fromDb "smbc-comics.com" // img // humor)
|
||||
(fromDb "xkcd.com" // img // humor)
|
||||
(fromDb "pbfcomics.com" // img // humor)
|
||||
# (mkImg "http://dilbert.com/feed" // humor // daily)
|
||||
(fromDb "poorlydrawnlines.com/feed" // img // humor)
|
||||
|
||||
# ART
|
||||
(fromDb "miniature-calendar.com" // img // art // daily)
|
||||
];
|
||||
in
|
||||
{
|
||||
sane.feeds = texts ++ images ++ podcasts;
|
||||
|
||||
assertions = builtins.map
|
||||
(p: {
|
||||
assertion = p.format or "unknown" == "podcast";
|
||||
message = ''${p.url} is not a podcast: ${p.format or "unknown"}'';
|
||||
})
|
||||
podcasts;
|
||||
}
|
@@ -28,6 +28,11 @@
|
||||
# powertop will default to putting USB devices -- including HID -- to sleep after TWO SECONDS
|
||||
powerManagement.powertop.enable = false;
|
||||
|
||||
services.logind.extraConfig = ''
|
||||
# don’t shutdown when power button is short-pressed
|
||||
HandlePowerKey=ignore
|
||||
'';
|
||||
|
||||
# services.snapper.configs = {
|
||||
# root = {
|
||||
# subvolume = "/";
|
9
hosts/common/home/default.nix
Normal file
9
hosts/common/home/default.nix
Normal file
@@ -0,0 +1,9 @@
|
||||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
./keyring.nix
|
||||
./mime.nix
|
||||
./ssh.nix
|
||||
./xdg-dirs.nix
|
||||
];
|
||||
}
|
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 ];
|
||||
};
|
||||
}
|
43
hosts/common/home/mime.nix
Normal file
43
hosts/common/home/mime.nix
Normal file
@@ -0,0 +1,43 @@
|
||||
{ config, sane-lib, ...}:
|
||||
|
||||
let
|
||||
www = config.sane.programs.web-browser.config.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/webm" = 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;
|
||||
};
|
||||
}
|
26
hosts/common/home/ssh.nix
Normal file
26
hosts/common/home/ssh.nix
Normal file
@@ -0,0 +1,26 @@
|
||||
{ config, lib, sane-lib, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
host = config.networking.hostName;
|
||||
user-pubkey-full = config.sane.ssh.pubkeys."colin@${host}" or {};
|
||||
user-pubkey = user-pubkey-full.asUserKey or null;
|
||||
host-keys = filter (k: k.user == "root") (attrValues config.sane.ssh.pubkeys);
|
||||
known-hosts-text = concatStringsSep
|
||||
"\n"
|
||||
(map (k: k.asHostKey) host-keys)
|
||||
;
|
||||
in
|
||||
{
|
||||
# ssh key is stored in private storage
|
||||
sane.user.persist.private = [ ".ssh/id_ed25519" ];
|
||||
sane.user.fs.".ssh/id_ed25519.pub" =
|
||||
mkIf (user-pubkey != null) (sane-lib.fs.wantedText user-pubkey);
|
||||
sane.user.fs.".ssh/known_hosts" = sane-lib.fs.wantedText known-hosts-text;
|
||||
|
||||
users.users.colin.openssh.authorizedKeys.keys =
|
||||
let
|
||||
user-keys = filter (k: k.user == "colin") (attrValues config.sane.ssh.pubkeys);
|
||||
in
|
||||
map (k: k.asUserKey) user-keys;
|
||||
}
|
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";
|
||||
}
|
@@ -1,4 +0,0 @@
|
||||
{ ... }:
|
||||
{
|
||||
services.i2p.enable = true;
|
||||
}
|
80
hosts/common/ids.nix
Normal file
80
hosts/common/ids.nix
Normal file
@@ -0,0 +1,80 @@
|
||||
# TODO: migrate to nixpkgs `config.ids.uids`
|
||||
# - note that nixpkgs' `config.ids.uids` is strictly a database: it doesn't set anything by default
|
||||
# whereas our impl sets the gid/uid of the user/group specified if they exist.
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
# legacy servo users, some are inconvenient to migrate
|
||||
sane.ids.dhcpcd.gid = 991;
|
||||
sane.ids.dhcpcd.uid = 992;
|
||||
sane.ids.gitea.gid = 993;
|
||||
sane.ids.git.uid = 994;
|
||||
sane.ids.jellyfin.gid = 994;
|
||||
sane.ids.pleroma.gid = 995;
|
||||
sane.ids.jellyfin.uid = 996;
|
||||
sane.ids.acme.gid = 996;
|
||||
sane.ids.pleroma.uid = 997;
|
||||
sane.ids.acme.uid = 998;
|
||||
sane.ids.matrix-appservice-irc.uid = 993;
|
||||
sane.ids.matrix-appservice-irc.gid = 992;
|
||||
|
||||
# greetd (used by sway)
|
||||
sane.ids.greeter.uid = 999;
|
||||
sane.ids.greeter.gid = 999;
|
||||
|
||||
# new servo users
|
||||
sane.ids.freshrss.uid = 2401;
|
||||
sane.ids.freshrss.gid = 2401;
|
||||
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.calibre-web.uid = 2406;
|
||||
sane.ids.calibre-web.gid = 2406;
|
||||
sane.ids.komga.uid = 2407;
|
||||
sane.ids.komga.gid = 2407;
|
||||
sane.ids.lemmy.uid = 2408;
|
||||
sane.ids.lemmy.gid = 2408;
|
||||
sane.ids.pict-rs.uid = 2409;
|
||||
sane.ids.pict-rs.gid = 2409;
|
||||
|
||||
sane.ids.colin.uid = 1000;
|
||||
sane.ids.guest.uid = 1100;
|
||||
|
||||
# found on all hosts
|
||||
sane.ids.sshd.uid = 2001; # 997
|
||||
sane.ids.sshd.gid = 2001; # 997
|
||||
sane.ids.polkituser.gid = 2002; # 998
|
||||
sane.ids.systemd-coredump.gid = 2003; # 996 # 2023/02/12-2023/02/28: upstream temporarily specified this as 151
|
||||
sane.ids.nscd.uid = 2004;
|
||||
sane.ids.nscd.gid = 2004;
|
||||
sane.ids.systemd-oom.uid = 2005;
|
||||
sane.ids.systemd-oom.gid = 2005;
|
||||
sane.ids.wireshark.gid = 2006;
|
||||
|
||||
# found on graphical hosts
|
||||
sane.ids.nm-iodine.uid = 2101; # desko/moby/lappy
|
||||
|
||||
# found on desko host
|
||||
# from services.usbmuxd
|
||||
sane.ids.usbmux.uid = 2204;
|
||||
sane.ids.usbmux.gid = 2204;
|
||||
|
||||
|
||||
# originally found on moby host
|
||||
# gnome core-shell
|
||||
sane.ids.avahi.uid = 2304;
|
||||
sane.ids.avahi.gid = 2304;
|
||||
sane.ids.colord.uid = 2305;
|
||||
sane.ids.colord.gid = 2305;
|
||||
sane.ids.geoclue.uid = 2306;
|
||||
sane.ids.geoclue.gid = 2306;
|
||||
# gnome core-os-services
|
||||
sane.ids.rtkit.uid = 2307;
|
||||
sane.ids.rtkit.gid = 2307;
|
||||
# phosh
|
||||
sane.ids.feedbackd.gid = 2308;
|
||||
}
|
@@ -1,16 +1,6 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
# 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".
|
||||
# wpa_supplicant reliably picks weak APs to connect to.
|
||||
# see: <https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/474>
|
||||
@@ -31,19 +21,7 @@
|
||||
General.RoamThreshold5G = "-52"; # default -76
|
||||
};
|
||||
|
||||
# TODO: don't need to depend on binsh if we were to use a nix-style shebang
|
||||
system.activationScripts.linkIwdKeys = let
|
||||
unwrapped = ../../scripts/install-iwd;
|
||||
install-iwd = pkgs.writeShellApplication {
|
||||
name = "install-iwd";
|
||||
runtimeInputs = with pkgs; [ coreutils gnused ];
|
||||
text = ''${unwrapped} "$@"'';
|
||||
};
|
||||
in (lib.stringAfter
|
||||
[ "setupSecrets" "binsh" ]
|
||||
''
|
||||
mkdir -p /var/lib/iwd
|
||||
${install-iwd}/bin/install-iwd /run/secrets/iwd /var/lib/iwd
|
||||
''
|
||||
);
|
||||
networking.firewall.allowedUDPPorts = [
|
||||
1900 # to received UPnP advertisements. required by sane-ip-check-upnp
|
||||
];
|
||||
}
|
||||
|
18
hosts/common/persist.nix
Normal file
18
hosts/common/persist.nix
Normal file
@@ -0,0 +1,18 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
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.
|
||||
"/var/lib/systemd/backlight" # backlight brightness
|
||||
"/var/lib/systemd/coredump"
|
||||
];
|
||||
}
|
6
hosts/common/programs/aerc.nix
Normal file
6
hosts/common/programs/aerc.nix
Normal file
@@ -0,0 +1,6 @@
|
||||
# Terminal UI mail client
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
sane.programs.aerc.secrets.".config/aerc/accounts.conf" = ../../../secrets/common/aerc_accounts.conf.bin;
|
||||
}
|
425
hosts/common/programs/default.nix
Normal file
425
hosts/common/programs/default.nix
Normal file
@@ -0,0 +1,425 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (builtins) attrNames concatLists;
|
||||
inherit (lib) mapAttrs mapAttrsToList mkDefault mkIf mkMerge optional;
|
||||
|
||||
flattenedPkgs = pkgs // (with pkgs; {
|
||||
# XXX can't `inherit` a nested attr, so we move them to the toplevel
|
||||
"cacert.unbundled" = pkgs.cacert.unbundled;
|
||||
"gnome.cheese" = gnome.cheese;
|
||||
"gnome.dconf-editor" = gnome.dconf-editor;
|
||||
"gnome.file-roller" = gnome.file-roller;
|
||||
"gnome.gnome-disk-utility" = gnome.gnome-disk-utility;
|
||||
"gnome.gnome-maps" = gnome.gnome-maps;
|
||||
"gnome.nautilus" = gnome.nautilus;
|
||||
"gnome.gnome-system-monitor" = gnome.gnome-system-monitor;
|
||||
"gnome.gnome-terminal" = gnome.gnome-terminal;
|
||||
"gnome.gnome-weather" = gnome.gnome-weather;
|
||||
"gnome.totem" = gnome.totem;
|
||||
"libsForQt5.plasmatube" = libsForQt5.plasmatube;
|
||||
});
|
||||
|
||||
sysadminPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
btrfs-progs
|
||||
"cacert.unbundled" # some services require unbundled /etc/ssl/certs
|
||||
cryptsetup
|
||||
dig
|
||||
efibootmgr
|
||||
fatresize
|
||||
fd
|
||||
file
|
||||
gawk
|
||||
git
|
||||
gptfdisk
|
||||
hdparm
|
||||
htop
|
||||
iftop
|
||||
inetutils # for telnet
|
||||
iotop
|
||||
iptables
|
||||
jq
|
||||
killall
|
||||
lsof
|
||||
miniupnpc
|
||||
nano
|
||||
netcat
|
||||
nethogs
|
||||
nmap
|
||||
openssl
|
||||
parted
|
||||
pciutils
|
||||
powertop
|
||||
pstree
|
||||
ripgrep
|
||||
screen
|
||||
smartmontools
|
||||
socat
|
||||
strace
|
||||
subversion
|
||||
tcpdump
|
||||
tree
|
||||
usbutils
|
||||
wget
|
||||
wirelesstools # iwlist
|
||||
;
|
||||
};
|
||||
sysadminExtraPkgs = {
|
||||
# application-specific packages
|
||||
inherit (pkgs)
|
||||
backblaze-b2
|
||||
duplicity
|
||||
sqlite # to debug sqlite3 databases
|
||||
;
|
||||
};
|
||||
|
||||
iphonePkgs = {
|
||||
inherit (pkgs)
|
||||
ifuse
|
||||
ipfs
|
||||
libimobiledevice
|
||||
;
|
||||
};
|
||||
|
||||
tuiPkgs = {
|
||||
inherit (pkgs)
|
||||
aerc # email client
|
||||
offlineimap # email mailox sync
|
||||
visidata # TUI spreadsheet viewer/editor
|
||||
w3m
|
||||
;
|
||||
};
|
||||
|
||||
# TODO: split these into smaller groups.
|
||||
# - transcoders (ffmpeg, imagemagick) only wanted on desko/lappy ("powerutils"?)
|
||||
consolePkgs = {
|
||||
inherit (pkgs)
|
||||
cdrtools
|
||||
dmidecode
|
||||
efivar
|
||||
flashrom
|
||||
fwupd
|
||||
gh # MS GitHub cli
|
||||
git # needed as a user package, for config.
|
||||
gnupg
|
||||
gocryptfs
|
||||
gopass # TODO: shouldn't be needed here
|
||||
gopass-jsonapi
|
||||
imagemagick
|
||||
kitty # TODO: move to GUI, but `ssh servo` from kitty sets `TERM=xterm-kitty` in the remove and breaks things
|
||||
libsecret # for managing user keyrings
|
||||
lm_sensors # for sensors-detect
|
||||
lshw
|
||||
ffmpeg
|
||||
# memtester
|
||||
neovim
|
||||
# nettools
|
||||
# networkmanager
|
||||
nixpkgs-review
|
||||
# nixos-generators
|
||||
nmon
|
||||
# node2nix
|
||||
# oathToolkit # for oathtool
|
||||
# ponymix
|
||||
pulsemixer
|
||||
python3
|
||||
ripgrep # needed as a user package, for config.
|
||||
rsync
|
||||
# python3Packages.eyeD3 # music tagging
|
||||
sane-scripts
|
||||
sequoia
|
||||
snapper
|
||||
sops
|
||||
sox
|
||||
speedtest-cli
|
||||
# ssh-to-age
|
||||
sudo
|
||||
# tageditor # music tagging
|
||||
unar
|
||||
wireguard-tools
|
||||
xdg-utils # for xdg-open
|
||||
# yarn
|
||||
# youtube-dl
|
||||
yt-dlp
|
||||
zsh
|
||||
;
|
||||
};
|
||||
|
||||
guiPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
# celluloid # mpv frontend
|
||||
clinfo
|
||||
emote
|
||||
evince # works on phosh
|
||||
|
||||
# { pkg = fluffychat-moby; persist.plaintext = [ ".local/share/chat.fluffy.fluffychat" ]; } # TODO: ship normal fluffychat on non-moby?
|
||||
|
||||
# foliate # e-book reader
|
||||
|
||||
# XXX by default fractal stores its state in ~/.local/share/<UUID>.
|
||||
# after logging in, manually change ~/.local/share/keyrings/... to point it to some predictable subdir.
|
||||
# then reboot (so that libsecret daemon re-loads the keyring...?)
|
||||
# { pkg = fractal-latest; persist.private = [ ".local/share/fractal" ]; }
|
||||
# { pkg = fractal-next; persist.private = [ ".local/share/fractal" ]; }
|
||||
|
||||
# "gnome.cheese"
|
||||
"gnome.dconf-editor"
|
||||
# gnome-feeds # RSS reader (with claimed mobile support)
|
||||
"gnome.file-roller"
|
||||
# "gnome.gnome-maps" # works on phosh
|
||||
"gnome.nautilus"
|
||||
# gnome-podcasts
|
||||
"gnome.gnome-system-monitor"
|
||||
# "gnome.gnome-terminal" # works on phosh
|
||||
# "gnome.gnome-weather"
|
||||
gpodder
|
||||
gthumb
|
||||
jellyfin-media-player
|
||||
# lollypop
|
||||
# mpv
|
||||
networkmanagerapplet
|
||||
# newsflash
|
||||
nheko
|
||||
pavucontrol
|
||||
# picard # music tagging
|
||||
playerctl
|
||||
# "libsForQt5.plasmatube" # Youtube player
|
||||
soundconverter
|
||||
sublime-music
|
||||
# tdesktop # broken on phosh
|
||||
# tokodon
|
||||
vlc
|
||||
# pleroma client (Electron). input is broken on phosh. TODO(2023/02/02): fix electron19 input (insecure)
|
||||
# whalebird
|
||||
xterm # broken on phosh
|
||||
;
|
||||
};
|
||||
desktopGuiPkgs = {
|
||||
inherit (flattenedPkgs)
|
||||
audacity
|
||||
brave # for the integrated wallet -- as a backup
|
||||
chromium
|
||||
dino
|
||||
electrum
|
||||
element-desktop
|
||||
font-manager
|
||||
gajim # XMPP client
|
||||
gimp # broken on phosh
|
||||
"gnome.gnome-disk-utility"
|
||||
# "gnome.totem" # video player, supposedly supports UPnP
|
||||
handbrake
|
||||
hase
|
||||
inkscape
|
||||
kdenlive
|
||||
kid3 # audio tagging
|
||||
krita
|
||||
libreoffice-fresh
|
||||
mumble
|
||||
obsidian
|
||||
slic3r
|
||||
steam
|
||||
wireshark # could maybe ship the cli as sysadmin pkg
|
||||
;
|
||||
};
|
||||
x86GuiPkgs = {
|
||||
inherit (pkgs)
|
||||
discord
|
||||
|
||||
# kaiteki # Pleroma client
|
||||
# gnome.zenity # for kaiteki (it will use qarma, kdialog, or zenity)
|
||||
# gpt2tc # XXX: unreliable mirror
|
||||
|
||||
# logseq # Personal Knowledge Management
|
||||
losslesscut-bin
|
||||
makemkv
|
||||
monero-gui
|
||||
signal-desktop
|
||||
spotify
|
||||
tor-browser-bundle-bin
|
||||
zecwallet-lite
|
||||
;
|
||||
};
|
||||
|
||||
# packages not part of any package set; not enabled by default
|
||||
otherPkgs = {
|
||||
inherit (pkgs)
|
||||
lemmy-server
|
||||
mx-sanebot
|
||||
stepmania
|
||||
;
|
||||
};
|
||||
|
||||
# define -- but don't enable -- the packages in some attrset.
|
||||
declarePkgs = pkgsAsAttrs: mapAttrs (_n: p: {
|
||||
# no need to actually define the package here: it's defaulted
|
||||
# package = mkDefault p;
|
||||
}) pkgsAsAttrs;
|
||||
in
|
||||
{
|
||||
|
||||
imports = [
|
||||
./aerc.nix
|
||||
./git.nix
|
||||
./gnome-feeds.nix
|
||||
./gpodder.nix
|
||||
./kitty
|
||||
./libreoffice.nix
|
||||
./mpv.nix
|
||||
./neovim.nix
|
||||
./newsflash.nix
|
||||
./offlineimap.nix
|
||||
./ripgrep.nix
|
||||
./splatmoji.nix
|
||||
./sublime-music.nix
|
||||
./vlc.nix
|
||||
./web-browser.nix
|
||||
./wireshark.nix
|
||||
./zeal.nix
|
||||
./zsh
|
||||
];
|
||||
|
||||
config = {
|
||||
sane.programs = mkMerge [
|
||||
(declarePkgs consolePkgs)
|
||||
(declarePkgs desktopGuiPkgs)
|
||||
(declarePkgs guiPkgs)
|
||||
(declarePkgs iphonePkgs)
|
||||
(declarePkgs sysadminPkgs)
|
||||
(declarePkgs sysadminExtraPkgs)
|
||||
(declarePkgs tuiPkgs)
|
||||
(declarePkgs x86GuiPkgs)
|
||||
(declarePkgs otherPkgs)
|
||||
{
|
||||
# link the various package sets into their own meta packages
|
||||
consoleUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames consolePkgs;
|
||||
};
|
||||
desktopGuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames desktopGuiPkgs;
|
||||
};
|
||||
guiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = (attrNames guiPkgs)
|
||||
++ [ "web-browser" ]
|
||||
++ [ "tuiApps" ]
|
||||
++ optional (pkgs.system == "x86_64-linux") "x86GuiApps";
|
||||
};
|
||||
iphoneUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames iphonePkgs;
|
||||
};
|
||||
sysadminUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames sysadminPkgs;
|
||||
};
|
||||
sysadminExtraUtils = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames sysadminExtraPkgs;
|
||||
};
|
||||
tuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames tuiPkgs;
|
||||
};
|
||||
x86GuiApps = {
|
||||
package = null;
|
||||
suggestedPrograms = attrNames x86GuiPkgs;
|
||||
};
|
||||
}
|
||||
{
|
||||
# nontrivial package definitions
|
||||
|
||||
dino.persist.private = [ ".local/share/dino" ];
|
||||
|
||||
# creds, but also 200 MB of node modules, etc
|
||||
discord.persist.private = [ ".config/discord" ];
|
||||
|
||||
# creds/session keys, etc
|
||||
element-desktop.persist.private = [ ".config/Element" ];
|
||||
|
||||
# `emote` will show a first-run dialog based on what's in this directory.
|
||||
# mostly, it just keeps a LRU of previously-used emotes to optimize display order.
|
||||
# TODO: package [smile](https://github.com/mijorus/smile) for probably a better mobile experience.
|
||||
emote.persist.plaintext = [ ".local/share/Emote" ];
|
||||
|
||||
# MS GitHub stores auth token in .config
|
||||
# TODO: we can populate gh's stuff statically; it even lets us use the same oauth across machines
|
||||
gh.persist.private = [ ".config/gh" ];
|
||||
|
||||
ghostscript = {}; # used by imagemagick
|
||||
|
||||
imagemagick = {
|
||||
package = pkgs.imagemagick.override {
|
||||
ghostscriptSupport = true;
|
||||
};
|
||||
suggestedPrograms = [ "ghostscript" ];
|
||||
};
|
||||
|
||||
# jellyfin stores things in a bunch of directories: this one persists auth info.
|
||||
# it *might* be possible to populate this externally (it's Qt stuff), but likely to
|
||||
# be fragile and take an hour+ to figure out.
|
||||
jellyfin-media-player.persist.plaintext = [ ".local/share/Jellyfin Media Player" ];
|
||||
|
||||
# actual monero blockchain (not wallet/etc; safe to delete, just slow to regenerate)
|
||||
# XXX: is it really safe to persist this? it doesn't have info that could de-anonymize if captured?
|
||||
monero-gui.persist.plaintext = [ ".bitmonero" ];
|
||||
|
||||
mumble.persist.private = [ ".local/share/Mumble" ];
|
||||
|
||||
# not strictly necessary, but allows caching articles; offline use, etc.
|
||||
nheko.persist.private = [
|
||||
".config/nheko" # config file (including client token)
|
||||
".cache/nheko" # media cache
|
||||
".local/share/nheko" # per-account state database
|
||||
];
|
||||
|
||||
# settings (electron app)
|
||||
obsidian.persist.plaintext = [ ".config/obsidian" ];
|
||||
|
||||
# creds, media
|
||||
signal-desktop.persist.private = [ ".config/Signal" ];
|
||||
|
||||
# printer/filament settings
|
||||
slic3r.persist.plaintext = [ ".Slic3r" ];
|
||||
|
||||
# creds, widevine .so download. TODO: could easily manage these statically.
|
||||
spotify.persist.plaintext = [ ".config/spotify" ];
|
||||
|
||||
steam.persist.plaintext = [
|
||||
".steam"
|
||||
".local/share/Steam"
|
||||
];
|
||||
|
||||
tdesktop.persist.private = [ ".local/share/TelegramDesktop" ];
|
||||
|
||||
tokodon.persist.private = [ ".cache/KDE/tokodon" ];
|
||||
|
||||
# hardenedMalloc solves a crash at startup
|
||||
# TODO 2023/02/02: is this safe to remove yet?
|
||||
tor-browser-bundle-bin.package = pkgs.tor-browser-bundle-bin.override {
|
||||
useHardenedMalloc = false;
|
||||
};
|
||||
|
||||
whalebird.persist.private = [ ".config/Whalebird" ];
|
||||
|
||||
yarn.persist.plaintext = [ ".cache/yarn" ];
|
||||
|
||||
# zcash coins. safe to delete, just slow to regenerate (10-60 minutes)
|
||||
zecwallet-lite.persist.private = [ ".zcash" ];
|
||||
}
|
||||
];
|
||||
|
||||
# XXX: this might not be necessary. try removing this and cacert.unbundled (servo)?
|
||||
environment.etc."ssl/certs".source = "${pkgs.cacert.unbundled}/etc/ssl/certs/*";
|
||||
|
||||
# steam requires system-level config for e.g. firewall or controller support
|
||||
programs.steam = mkIf config.sane.programs.steam.enabled {
|
||||
enable = true;
|
||||
# not sure if needed: stole this whole snippet from the wiki
|
||||
remotePlay.openFirewall = true; # Open ports in the firewall for Steam Remote Play
|
||||
dedicatedServer.openFirewall = true; # Open ports in the firewall for Source Dedicated Server
|
||||
};
|
||||
};
|
||||
}
|
26
hosts/common/programs/git.nix
Normal file
26
hosts/common/programs/git.nix
Normal file
@@ -0,0 +1,26 @@
|
||||
{ lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
mkCfg = lib.generators.toINI { };
|
||||
in
|
||||
{
|
||||
sane.programs.git.fs.".config/git/config".symlink.text = mkCfg {
|
||||
# top-level options documented:
|
||||
# - <https://git-scm.com/docs/git-config#_variables>
|
||||
|
||||
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
|
||||
|
||||
# render dates as YYYY-MM-DD HH:MM:SS +TZ
|
||||
log.date = "iso";
|
||||
};
|
||||
}
|
40
hosts/common/programs/gnome-feeds.nix
Normal file
40
hosts/common/programs/gnome-feeds.nix
Normal file
@@ -0,0 +1,40 @@
|
||||
# gnome feeds RSS viewer
|
||||
{ config, lib, sane-lib, ... }:
|
||||
|
||||
let
|
||||
feeds = sane-lib.feeds;
|
||||
all-feeds = config.sane.feeds;
|
||||
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
|
||||
in {
|
||||
sane.programs.gnome-feeds.fs.".config/org.gabmus.gfeeds.json".symlink.text = builtins.toJSON {
|
||||
# feed format is a map from URL to a dict,
|
||||
# with dict["tags"] a list of string tags.
|
||||
feeds = sane-lib.mapToAttrs (feed: {
|
||||
name = feed.url;
|
||||
value.tags = [ feed.cat feed.freq ];
|
||||
}) wanted-feeds;
|
||||
dark_reader = false;
|
||||
new_first = true;
|
||||
# windowsize = {
|
||||
# width = 350;
|
||||
# height = 650;
|
||||
# };
|
||||
max_article_age_days = 90;
|
||||
enable_js = false;
|
||||
max_refresh_threads = 3;
|
||||
# saved_items = {};
|
||||
# read_items = [];
|
||||
show_read_items = true;
|
||||
full_article_title = true;
|
||||
# views: "webview", "reader", "rsscont"
|
||||
default_view = "rsscont";
|
||||
open_links_externally = true;
|
||||
full_feed_name = false;
|
||||
refresh_on_startup = true;
|
||||
tags = lib.unique (
|
||||
(builtins.catAttrs "cat" wanted-feeds) ++ (builtins.catAttrs "freq" wanted-feeds)
|
||||
);
|
||||
open_youtube_externally = false;
|
||||
media_player = "vlc"; # default: mpv
|
||||
};
|
||||
}
|
17
hosts/common/programs/gpodder.nix
Normal file
17
hosts/common/programs/gpodder.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
# gnome feeds RSS viewer
|
||||
{ config, pkgs, sane-lib, ... }:
|
||||
|
||||
let
|
||||
feeds = sane-lib.feeds;
|
||||
all-feeds = config.sane.feeds;
|
||||
wanted-feeds = feeds.filterByFormat ["podcast"] all-feeds;
|
||||
in {
|
||||
sane.programs.gpodder = {
|
||||
package = pkgs.gpodder-configured;
|
||||
fs.".config/gpodderFeeds.opml".symlink.text = feeds.feedsToOpml wanted-feeds;
|
||||
|
||||
# XXX: we preserve the whole thing because if we only preserve gPodder/Downloads
|
||||
# then startup is SLOW during feed import, and we might end up with zombie eps in the dl dir.
|
||||
persist.plaintext = [ "gPodder" ];
|
||||
};
|
||||
}
|
47
hosts/common/programs/kitty/PaperColor_dark.conf
Normal file
47
hosts/common/programs/kitty/PaperColor_dark.conf
Normal file
@@ -0,0 +1,47 @@
|
||||
# vim:ft=kitty
|
||||
|
||||
## name: PaperColor Dark
|
||||
## author: Nikyle Nguyen
|
||||
## license: MIT
|
||||
## blurb: Dark color scheme inspired by Google's Material Design
|
||||
|
||||
# special
|
||||
foreground #d0d0d0
|
||||
background #1c1c1c
|
||||
cursor #d0d0d0
|
||||
cursor_text_color background
|
||||
|
||||
# black
|
||||
color0 #1c1c1c
|
||||
color8 #585858
|
||||
|
||||
# red
|
||||
color1 #af005f
|
||||
color9 #5faf5f
|
||||
|
||||
# green
|
||||
# "color2" is the green color used by ls to indicate executability
|
||||
# both as text color
|
||||
# or as bg color when the text is blue (color4)
|
||||
color2 #246a28
|
||||
color10 #2df200
|
||||
|
||||
# yellow
|
||||
color3 #d7af5f
|
||||
color11 #af87d7
|
||||
|
||||
# blue
|
||||
color4 #78c6ef
|
||||
color12 #ffaf00
|
||||
|
||||
# magenta
|
||||
color5 #808080
|
||||
color13 #ff5faf
|
||||
|
||||
# cyan
|
||||
color6 #d7875f
|
||||
color14 #00afaf
|
||||
|
||||
# white
|
||||
color7 #d0d0d0
|
||||
color15 #5f8787
|
70
hosts/common/programs/kitty/default.nix
Normal file
70
hosts/common/programs/kitty/default.nix
Normal file
@@ -0,0 +1,70 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
sane.programs.kitty.fs.".config/kitty/kitty.conf".symlink.text = ''
|
||||
# docs: https://sw.kovidgoyal.net/kitty/conf/
|
||||
# disable terminal bell (when e.g. you backspace too many times)
|
||||
enable_audio_bell no
|
||||
|
||||
map ctrl+n new_os_window_with_cwd
|
||||
include ${./PaperColor_dark.conf}
|
||||
'';
|
||||
|
||||
# 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/programs/libreoffice.nix
Normal file
14
hosts/common/programs/libreoffice.nix
Normal file
@@ -0,0 +1,14 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
# libreoffice: disable first-run stuff
|
||||
sane.programs.libreoffice-fresh.fs.".config/libreoffice/4/user/registrymodifications.xcu".symlink.text = ''
|
||||
<?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>
|
||||
}
|
13
hosts/common/programs/mpv.nix
Normal file
13
hosts/common/programs/mpv.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
sane.programs.mpv = {
|
||||
persist.plaintext = [ ".config/mpv/watch_later" ];
|
||||
# format is <key>=%<length>%<value>
|
||||
fs.".config/mpv/mpv.conf".symlink.text = ''
|
||||
save-position-on-quit=%3%yes
|
||||
keep-open=%3%yes
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
129
hosts/common/programs/neovim.nix
Normal file
129
hosts/common/programs/neovim.nix
Normal file
@@ -0,0 +1,129 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (builtins) map;
|
||||
inherit (lib) concatMapStrings mkIf optionalString;
|
||||
# this structure roughly mirrors home-manager's `programs.neovim.plugins` option
|
||||
plugins = with pkgs.vimPlugins; [
|
||||
# docs: surround-nvim: https://github.com/ur4ltz/surround.nvim/
|
||||
# docs: vim-surround: https://github.com/tpope/vim-surround
|
||||
{ plugin = vim-surround; }
|
||||
# docs: fzf-vim (fuzzy finder): https://github.com/junegunn/fzf.vim
|
||||
{ plugin = fzf-vim; }
|
||||
({
|
||||
# docs: tex-conceal-vim: https://github.com/KeitaNakamura/tex-conceal.vim/
|
||||
plugin = tex-conceal-vim;
|
||||
type = "viml";
|
||||
config = ''
|
||||
" present prettier fractions
|
||||
let g:tex_conceal_frac=1
|
||||
'';
|
||||
})
|
||||
({
|
||||
plugin = vim-SyntaxRange;
|
||||
type = "viml";
|
||||
config = ''
|
||||
" enable markdown-style codeblock highlighting for tex code
|
||||
autocmd BufEnter * call SyntaxRange#Include('```tex', '```', 'tex', 'NonText')
|
||||
" autocmd Syntax tex set conceallevel=2
|
||||
'';
|
||||
})
|
||||
({
|
||||
# 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.programs.neovim.persist.private = [ ".cache/vim-swap" ];
|
||||
|
||||
programs.neovim = mkIf config.sane.programs.neovim.enabled {
|
||||
# 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
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
15
hosts/common/programs/newsflash.nix
Normal file
15
hosts/common/programs/newsflash.nix
Normal file
@@ -0,0 +1,15 @@
|
||||
# news-flash RSS viewer
|
||||
{ config, sane-lib, ... }:
|
||||
|
||||
let
|
||||
feeds = sane-lib.feeds;
|
||||
all-feeds = config.sane.feeds;
|
||||
wanted-feeds = feeds.filterByFormat ["text" "image"] all-feeds;
|
||||
in {
|
||||
sane.programs.newsflash = {
|
||||
persist.plaintext = [ ".local/share/news-flash" ];
|
||||
fs.".config/newsflashFeeds.opml".symlink.text =
|
||||
feeds.feedsToOpml wanted-feeds
|
||||
;
|
||||
};
|
||||
}
|
12
hosts/common/programs/offlineimap.nix
Normal file
12
hosts/common/programs/offlineimap.nix
Normal file
@@ -0,0 +1,12 @@
|
||||
# mail archiving/synchronization tool.
|
||||
#
|
||||
# manually download all emails for an account with
|
||||
# - `offlineimap -a <accountname>`
|
||||
#
|
||||
# view account names inside the secrets file, listed below.
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
sane.programs.offlineimap.secrets.".config/offlineimap/config" = ../../../secrets/common/offlineimaprc.bin;
|
||||
}
|
||||
|
9
hosts/common/programs/ripgrep.nix
Normal file
9
hosts/common/programs/ripgrep.nix
Normal file
@@ -0,0 +1,9 @@
|
||||
{ ... }:
|
||||
{
|
||||
# .ignore file is read by ripgrep (rg), silver searcher (ag), maybe others.
|
||||
# ignore translation files by default when searching, as they tend to have
|
||||
# a LOT of duplicate text.
|
||||
sane.programs.ripgrep.fs.".ignore".symlink.text = ''
|
||||
po/
|
||||
'';
|
||||
}
|
@@ -4,8 +4,10 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
home-manager.users.colin = {
|
||||
xdg.configFile."splatmoji/splatmoji.config".text = ''
|
||||
sane.programs.splatmoji = {
|
||||
persist.plaintext = [ ".local/state/splatmoji" ];
|
||||
fs.".config/splatmoji/splatmoji.config".symlink.text = ''
|
||||
# XXX doesn't seem to understand ~ as shorthand for `$HOME`
|
||||
history_file=/home/colin/.local/state/splatmoji/history
|
||||
history_length=5
|
||||
# TODO: wayland equiv
|
14
hosts/common/programs/sublime-music.nix
Normal file
14
hosts/common/programs/sublime-music.nix
Normal file
@@ -0,0 +1,14 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
sane.programs.sublime-music = {
|
||||
package = pkgs.sublime-music-mobile;
|
||||
# sublime music persists any downloaded albums here.
|
||||
# it doesn't obey a conventional ~/Music/{Artist}/{Album}/{Track} notation, so no symlinking
|
||||
# config (e.g. server connection details) is persisted in ~/.config/sublime-music/config.json
|
||||
# possible to pass config as a CLI arg (sublime-music -c config.json)
|
||||
persist.plaintext = [ ".local/share/sublime-music" ];
|
||||
|
||||
secrets.".config/sublime-music/config.json" = ../../../secrets/common/sublime_music_config.json.bin;
|
||||
};
|
||||
}
|
24
hosts/common/programs/vlc.nix
Normal file
24
hosts/common/programs/vlc.nix
Normal file
@@ -0,0 +1,24 @@
|
||||
{ config, lib, sane-lib, ... }:
|
||||
|
||||
let
|
||||
feeds = sane-lib.feeds;
|
||||
all-feeds = config.sane.feeds;
|
||||
wanted-feeds = feeds.filterByFormat ["podcast"] all-feeds;
|
||||
podcast-urls = lib.concatStringsSep "|" (
|
||||
builtins.map (feed: feed.url) wanted-feeds
|
||||
);
|
||||
in
|
||||
{
|
||||
sane.programs.vlc = {
|
||||
# vlc remembers play position in ~/.config/vlc/vlc-qt-interface.conf
|
||||
persist.plaintext = [ ".config/vlc" ];
|
||||
fs.".config/vlc/vlcrc".symlink.text = ''
|
||||
[podcast]
|
||||
podcast-urls=${podcast-urls}
|
||||
[core]
|
||||
metadata-network-access=0
|
||||
[qt]
|
||||
qt-privacy-ask=0
|
||||
'';
|
||||
};
|
||||
}
|
246
hosts/common/programs/web-browser.nix
Normal file
246
hosts/common/programs/web-browser.nix
Normal file
@@ -0,0 +1,246 @@
|
||||
# common settings to toggle (at runtime, in about:config):
|
||||
# > security.ssl.require_safe_negotiation
|
||||
|
||||
# librewolf is a forked firefox which patches firefox to allow more things
|
||||
# (like default search engines) to be configurable at runtime.
|
||||
# many of the settings below won't have effect without those patches.
|
||||
# see: https://gitlab.com/librewolf-community/settings/-/blob/master/distribution/policies.json
|
||||
|
||||
{ config, lib, pkgs, ...}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.sane.programs.web-browser.config;
|
||||
# allow easy switching between firefox and librewolf with `defaultSettings`, below
|
||||
librewolfSettings = {
|
||||
browser = pkgs.librewolf-unwrapped;
|
||||
# browser = pkgs.librewolf-unwrapped.overrideAttrs (drv: {
|
||||
# # this allows side-loading unsigned addons
|
||||
# MOZ_REQUIRE_SIGNING = false;
|
||||
# });
|
||||
libName = "librewolf";
|
||||
dotDir = ".librewolf";
|
||||
cacheDir = ".cache/librewolf"; # TODO: is it?
|
||||
desktop = "librewolf.desktop";
|
||||
};
|
||||
firefoxSettings = {
|
||||
browser = pkgs.firefox-esr-unwrapped;
|
||||
libName = "firefox";
|
||||
dotDir = ".mozilla/firefox";
|
||||
cacheDir = ".cache/mozilla";
|
||||
desktop = "firefox.desktop";
|
||||
};
|
||||
# defaultSettings = firefoxSettings;
|
||||
defaultSettings = librewolfSettings;
|
||||
|
||||
addon = name: extid: hash: pkgs.fetchFirefoxAddon {
|
||||
inherit name hash;
|
||||
url = "https://addons.mozilla.org/firefox/downloads/latest/${name}/latest.xpi";
|
||||
# extid can be found by unar'ing the above xpi, and copying browser_specific_settings.gecko.id field
|
||||
fixedExtid = extid;
|
||||
};
|
||||
localAddon = pkg: pkgs.fetchFirefoxAddon {
|
||||
inherit (pkg) name;
|
||||
src = "${pkg}/share/mozilla/extensions/\\{ec8030f7-c20a-464f-9b0e-13a3a9e97384\\}/${pkg.extid}.xpi";
|
||||
fixedExtid = pkg.extid;
|
||||
};
|
||||
|
||||
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 = optional cfg.addons.browserpass-extension.enable pkgs.browserpass;
|
||||
# extraNativeMessagingHosts = [ pkgs.gopass-native-messaging-host ];
|
||||
|
||||
nixExtensions = concatMap (ext: optional ext.enable ext.package) (attrValues cfg.addons);
|
||||
|
||||
extraPolicies = {
|
||||
FirefoxHome = {
|
||||
Search = true;
|
||||
Pocket = false;
|
||||
Snippets = false;
|
||||
TopSites = false;
|
||||
Highlights = false;
|
||||
};
|
||||
NoDefaultBookmarks = true;
|
||||
OfferToSaveLogins = false;
|
||||
OfferToSaveLoginsDefault = false;
|
||||
PasswordManagerEnabled = false;
|
||||
SearchEngines = {
|
||||
Default = "DuckDuckGo";
|
||||
};
|
||||
UserMessaging = {
|
||||
ExtensionRecommendations = false;
|
||||
SkipOnboarding = true;
|
||||
};
|
||||
|
||||
# these were taken from Librewolf
|
||||
AppUpdateURL = "https://localhost";
|
||||
DisableAppUpdate = true;
|
||||
OverrideFirstRunPage = "";
|
||||
OverridePostUpdatePage = "";
|
||||
DisableSystemAddonUpdate = true;
|
||||
DisableFirefoxStudies = true;
|
||||
DisableTelemetry = true;
|
||||
DisableFeedbackCommands = true;
|
||||
DisablePocket = true;
|
||||
DisableSetDesktopBackground = false;
|
||||
|
||||
# remove many default search providers
|
||||
# XXX this seems to prevent the `nixExtensions` from taking effect
|
||||
# Extensions.Uninstall = [
|
||||
# "google@search.mozilla.org"
|
||||
# "bing@search.mozilla.org"
|
||||
# "amazondotcom@search.mozilla.org"
|
||||
# "ebay@search.mozilla.org"
|
||||
# "twitter@search.mozilla.org"
|
||||
# ];
|
||||
# XXX doesn't seem to have any effect...
|
||||
# docs: https://github.com/mozilla/policy-templates#homepage
|
||||
# Homepage = {
|
||||
# HomepageURL = "https://uninsane.org/";
|
||||
# StartPage = "homepage";
|
||||
# };
|
||||
# NewTabPage = true;
|
||||
};
|
||||
# extraPrefs = ...
|
||||
};
|
||||
|
||||
addonOpts = types.submodule {
|
||||
options = {
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
};
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configOpts = {
|
||||
options = {
|
||||
browser = mkOption {
|
||||
default = defaultSettings;
|
||||
type = types.anything;
|
||||
};
|
||||
persistData = mkOption {
|
||||
description = "optional store name to which persist browsing data (like history)";
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
persistCache = mkOption {
|
||||
description = "optional store name to which persist browser cache";
|
||||
type = types.nullOr types.str;
|
||||
default = "cryptClearOnBoot";
|
||||
};
|
||||
addons = mkOption {
|
||||
type = types.attrsOf addonOpts;
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
config = mkMerge [
|
||||
({
|
||||
sane.programs.web-browser.configOption = mkOption {
|
||||
type = types.submodule configOpts;
|
||||
default = {};
|
||||
};
|
||||
sane.programs.web-browser.config.addons = {
|
||||
# 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-extension = {
|
||||
# package = addon "browserpass-ce" "browserpass@maximbaz.com" "sha256-sXgUBbRvMnRpeIW1MTkmTcoqtW/8RDXAkxAq1evFkpc=";
|
||||
package = localAddon pkgs.browserpass-extension;
|
||||
enable = lib.mkDefault true;
|
||||
};
|
||||
|
||||
# TODO: build bypass-paywalls from source? it's mysteriously disappeared from the Mozilla store.
|
||||
# bypass-paywalls-clean.package = addon "bypass-paywalls-clean" "{d133e097-46d9-4ecc-9903-fa6a722a6e0e}" "sha256-oUwdqdAwV3DezaTtOMx7A/s4lzIws+t2f08mwk+324k=";
|
||||
# bypass-paywalls-clean.enable = lib.mkDefault true;
|
||||
|
||||
ether-metamask = {
|
||||
package = addon "ether-metamask" "webextension@metamask.io" "sha256-G+MwJDOcsaxYSUXjahHJmkWnjLeQ0Wven8DU/lGeMzA=";
|
||||
enable = lib.mkDefault true;
|
||||
};
|
||||
i2p-in-private-browsing = {
|
||||
package = addon "i2p-in-private-browsing" "i2ppb@eyedeekay.github.io" "sha256-dJcJ3jxeAeAkRvhODeIVrCflvX+S4E0wT/PyYzQBQWs=";
|
||||
enable = lib.mkDefault config.services.i2p.enable;
|
||||
};
|
||||
sidebery = {
|
||||
package = addon "sidebery" "{3c078156-979c-498b-8990-85f7987dd929}" "sha256-YONfK/rIjlsrTgRHIt3km07Q7KnpIW89Z9r92ZSCc6w=";
|
||||
enable = lib.mkDefault true;
|
||||
};
|
||||
sponsorblock = {
|
||||
package = addon "sponsorblock" "sponsorBlocker@ajay.app" "sha256-hRsvLaAsVm3dALsTrJqHTNgRFAQcU7XSaGhr5G6+mFs=";
|
||||
enable = lib.mkDefault true;
|
||||
};
|
||||
ublacklist = {
|
||||
package = addon "ublacklist" "@ublacklist" "sha256-RqY5iHzbL2qizth7aguyOKWPyINXmrwOlf/OsfqAS48=";
|
||||
enable = lib.mkDefault true;
|
||||
};
|
||||
ublock-origin = {
|
||||
package = addon "ublock-origin" "uBlock0@raymondhill.net" "sha256-eHlQrU/b9X/6sTbHBpGAd+0VsLT7IrVCnd0AQ948lyA=";
|
||||
enable = lib.mkDefault true;
|
||||
};
|
||||
};
|
||||
})
|
||||
({
|
||||
sane.programs.web-browser = {
|
||||
inherit package;
|
||||
|
||||
# uBlock filter list configuration.
|
||||
# specifically, enable the GDPR cookie prompt blocker.
|
||||
# data.toOverwrite.filterLists is additive (i.e. it supplements the default filters)
|
||||
# this configuration method is documented here:
|
||||
# - <https://github.com/gorhill/uBlock/issues/2986#issuecomment-364035002>
|
||||
# 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/assets/assets.json>
|
||||
fs."${cfg.browser.dotDir}/managed-storage/uBlock0@raymondhill.net.json".symlink.text = ''
|
||||
{
|
||||
"name": "uBlock0@raymondhill.net",
|
||||
"description": "ignored",
|
||||
"type": "storage",
|
||||
"data": {
|
||||
"toOverwrite": "{\"filterLists\": [\"fanboy-cookiemonster\"]}"
|
||||
}
|
||||
}
|
||||
'';
|
||||
fs."${cfg.browser.dotDir}/${cfg.browser.libName}.overrides.cfg".symlink.text = ''
|
||||
// if we can't query the revocation status of a SSL cert because the issuer is offline,
|
||||
// treat it as unrevoked.
|
||||
// see: <https://librewolf.net/docs/faq/#im-getting-sec_error_ocsp_server_error-what-can-i-do>
|
||||
defaultPref("security.OCSP.require", false);
|
||||
'';
|
||||
fs."${cfg.browser.dotDir}/default".dir = {};
|
||||
# instruct Firefox to put the profile in a predictable directory (so we can do things like persist just it).
|
||||
# XXX: the directory *must* exist, even if empty; Firefox will not create the directory itself.
|
||||
fs."${cfg.browser.dotDir}/profiles.ini".symlink.text = ''
|
||||
[Profile0]
|
||||
Name=default
|
||||
IsRelative=1
|
||||
Path=default
|
||||
Default=1
|
||||
|
||||
[General]
|
||||
StartWithLastProfile=1
|
||||
'';
|
||||
};
|
||||
})
|
||||
(mkIf config.sane.programs.web-browser.enabled {
|
||||
# TODO: move the persistence into the sane.programs API (above)
|
||||
# flush the cache to disk to avoid it taking up too much tmp
|
||||
sane.user.persist.byPath."${cfg.browser.cacheDir}" = lib.mkIf (cfg.persistCache != null) {
|
||||
store = cfg.persistCache;
|
||||
};
|
||||
|
||||
sane.user.persist.byPath."${cfg.browser.dotDir}/default" = lib.mkIf (cfg.persistData != null) {
|
||||
store = cfg.persistData;
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
5
hosts/common/programs/wireshark.nix
Normal file
5
hosts/common/programs/wireshark.nix
Normal file
@@ -0,0 +1,5 @@
|
||||
{ config, ... }:
|
||||
{
|
||||
sane.programs.wireshark = {};
|
||||
programs.wireshark.enable = config.sane.programs.wireshark.enabled;
|
||||
}
|
55
hosts/common/programs/zeal.nix
Normal file
55
hosts/common/programs/zeal.nix
Normal file
@@ -0,0 +1,55 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
inherit (builtins) map;
|
||||
inherit (lib) mkIf mkOption optionalString types;
|
||||
cfg = config.sane.programs.docsets.config;
|
||||
configOpts = types.submodule {
|
||||
options = {
|
||||
rustPkgs = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
};
|
||||
in {
|
||||
sane.programs.zeal = {
|
||||
package = pkgs.zeal-qt5;
|
||||
persist.plaintext = [
|
||||
".cache/Zeal"
|
||||
".local/share/Zeal"
|
||||
];
|
||||
fs.".local/share/Zeal/Zeal/docsets/system".symlink.target = "/run/current-system/sw/share/docset";
|
||||
suggestedPrograms = [ "docsets" ];
|
||||
};
|
||||
|
||||
sane.programs.docsets = {
|
||||
configOption = mkOption {
|
||||
type = configOpts;
|
||||
default = {};
|
||||
};
|
||||
package = pkgs.symlinkJoin {
|
||||
name = "docsets";
|
||||
# build each package with rust docs
|
||||
paths = map (name:
|
||||
let
|
||||
orig = pkgs."${name}";
|
||||
withDocs = orig.overrideAttrs (upstream: {
|
||||
nativeBuildInputs = upstream.nativeBuildInputs or [] ++ [
|
||||
pkgs.cargoDocsetHook
|
||||
];
|
||||
});
|
||||
in
|
||||
"${toString withDocs}/share/docset"
|
||||
) cfg.rustPkgs;
|
||||
# link only the docs (not any binaries)
|
||||
postBuild = optionalString (cfg.rustPkgs != []) ''
|
||||
mkdir -p $out/share/docset
|
||||
mv $out/*.docset $out/share/docset
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
environment.pathsToLink = mkIf config.sane.programs.zeal.enabled [
|
||||
"/share/docset"
|
||||
];
|
||||
}
|
166
hosts/common/programs/zsh/default.nix
Normal file
166
hosts/common/programs/zsh/default.nix
Normal file
@@ -0,0 +1,166 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkIf mkMerge mkOption types;
|
||||
cfg = config.sane.zsh;
|
||||
# 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
|
||||
{
|
||||
options = {
|
||||
sane.zsh = {
|
||||
showDeadlines = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "show upcoming deadlines (frommy PKM) upon shell init";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkMerge [
|
||||
({
|
||||
sane.programs.zsh = {
|
||||
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.
|
||||
fs.".config/zsh/.zshrc".symlink.text = "# ";
|
||||
|
||||
# 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.
|
||||
fs.".config/zsh/.zpreztorc".symlink.text = ''
|
||||
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'
|
||||
'';
|
||||
};
|
||||
})
|
||||
(mkIf config.sane.programs.zsh.enabled {
|
||||
# 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 *|nixos-rebuild.* switch)'
|
||||
|
||||
# extra aliases
|
||||
# TODO: move to `shellAliases` config?
|
||||
function nd() {
|
||||
mkdir -p "$1";
|
||||
pushd "$1";
|
||||
}
|
||||
''
|
||||
+ lib.optionalString cfg.showDeadlines ''
|
||||
${pkgs.sane-scripts}/bin/sane-deadlines
|
||||
''
|
||||
+ ''
|
||||
# auto-cd into any of these dirs by typing them and pressing 'enter':
|
||||
hash -d 3rd="/home/colin/dev/3rd"
|
||||
hash -d dev="/home/colin/dev"
|
||||
hash -d knowledge="/home/colin/knowledge"
|
||||
hash -d nixos="/home/colin/nixos"
|
||||
hash -d nixpkgs="/home/colin/dev/3rd/nixpkgs"
|
||||
hash -d ref="/home/colin/ref"
|
||||
hash -d secrets="/home/colin/knowledge/secrets"
|
||||
hash -d tmp="/home/colin/tmp"
|
||||
hash -d uninsane="/home/colin/dev/uninsane"
|
||||
hash -d Videos="/home/colin/Videos"
|
||||
'';
|
||||
|
||||
syntaxHighlighting.enable = true;
|
||||
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
|
||||
})
|
||||
];
|
||||
}
|
@@ -1,38 +1,49 @@
|
||||
{ config, ... }:
|
||||
# SOPS configuration:
|
||||
# docs: https://github.com/Mic92/sops-nix
|
||||
#
|
||||
# for each new user you want to edit sops files:
|
||||
# create a private age key from ssh key:
|
||||
# $ mkdir -p ~/.config/sops/age; ssh-to-age -private-key -i ~/.ssh/id_ed25519 > ~/.config/sops/age/keys.txt; chmod 600 ~/.config/sops/age/keys.txt
|
||||
# if the private key was password protected, then first decrypt it:
|
||||
# $ cp ~/.ssh/id_ed25519 /tmp/id_ed25519
|
||||
# $ ssh-keygen -p -N "" -f /tmp/id_ed25519
|
||||
#
|
||||
# for each user you want to decrypt secrets:
|
||||
# $ cat ~/.ssh/id_ed25519.pub | ssh-to-age
|
||||
# add the result to .sops.yaml
|
||||
# since we specify ssh pubkeys in the nix config, you can just grep for `ssh-ed25519` here and use those instead
|
||||
#
|
||||
# for each host you want to decrypt secrets:
|
||||
# $ cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age
|
||||
# add the result to .sops.yaml
|
||||
# $ sops updatekeys secrets/example.yaml
|
||||
#
|
||||
# to create a new secret:
|
||||
# $ sops secrets/example.yaml
|
||||
# control access below (sops.secret.<x>.owner = ...)
|
||||
#
|
||||
# to read a secret:
|
||||
# $ cat /run/secrets/example_key
|
||||
|
||||
{ config, lib, sane-lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib.strings) hasSuffix removeSuffix;
|
||||
secretsForHost = host: sane-lib.joinAttrsets (
|
||||
map
|
||||
(path: lib.optionalAttrs (hasSuffix ".bin" path) (sane-lib.nameValueToAttrs {
|
||||
name = removeSuffix ".bin" path;
|
||||
value = {
|
||||
sopsFile = ../../secrets/${host}/${path};
|
||||
format = "binary";
|
||||
};
|
||||
}))
|
||||
(sane-lib.enumerateFilePaths ../../secrets/${host})
|
||||
);
|
||||
in
|
||||
{
|
||||
# SOPS configuration:
|
||||
# docs: https://github.com/Mic92/sops-nix
|
||||
#
|
||||
# for each new user you want to edit sops files:
|
||||
# create a private age key from ssh key:
|
||||
# $ mkdir -p ~/.config/sops/age; ssh-to-age -private-key -i ~/.ssh/id_ed25519 > ~/.config/sops/age/keys.txt; chmod 600 ~/.config/sops/age/keys.txt
|
||||
# if the private key was password protected, then first decrypt it:
|
||||
# $ cp ~/.ssh/id_ed25519 /tmp/id_ed25519
|
||||
# $ ssh-keygen -p -N "" -f /tmp/id_ed25519
|
||||
#
|
||||
# for each user you want to decrypt secrets:
|
||||
# $ cat ~/.ssh/id_ed25519.pub | ssh-to-age
|
||||
# add the result to .sops.yaml
|
||||
# since we specify ssh pubkeys in the nix config, you can just grep for `ssh-ed25519` here and use those instead
|
||||
#
|
||||
# for each host you want to decrypt secrets:
|
||||
# $ cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age
|
||||
# add the result to .sops.yaml
|
||||
# $ sops updatekeys secrets/example.yaml
|
||||
#
|
||||
# to create a new secret:
|
||||
# $ sops secrets/example.yaml
|
||||
# control access below (sops.secret.<x>.owner = ...)
|
||||
#
|
||||
# to read a secret:
|
||||
# $ cat /run/secrets/example_key
|
||||
|
||||
# sops.age.sshKeyPaths = [ "/home/colin/.ssh/id_ed25519_dec" ];
|
||||
# This will add secrets.yaml to the nix store
|
||||
# You can avoid this by adding a string to the full path instead, i.e.
|
||||
# sops.defaultSopsFile = "/root/.sops/secrets/example.yaml";
|
||||
sops.defaultSopsFile = ../../secrets/universal.yaml;
|
||||
sops.gnupg.sshKeyPaths = []; # disable RSA key import
|
||||
# This is using an age key that is expected to already be in the filesystem
|
||||
# sops.age.keyFile = "/home/colin/.ssh/age.pub";
|
||||
@@ -45,80 +56,15 @@
|
||||
# };
|
||||
# sops.secrets."myservice/my_subdir/my_secret" = {};
|
||||
|
||||
## universal secrets
|
||||
# TODO: glob these?
|
||||
|
||||
sops.secrets."jackett_apikey" = {
|
||||
sopsFile = ../../secrets/universal.yaml;
|
||||
owner = config.users.users.colin.name;
|
||||
};
|
||||
sops.secrets."router_passwd" = {
|
||||
sopsFile = ../../secrets/universal.yaml;
|
||||
};
|
||||
sops.secrets."wg_ovpnd_us_privkey" = {
|
||||
sopsFile = ../../secrets/universal.yaml;
|
||||
};
|
||||
sops.secrets."wg_ovpnd_us-atl_privkey" = {
|
||||
sopsFile = ../../secrets/universal.yaml;
|
||||
};
|
||||
sops.secrets."wg_ovpnd_us-mi_privkey" = {
|
||||
sopsFile = ../../secrets/universal.yaml;
|
||||
};
|
||||
sops.secrets."wg_ovpnd_ukr_privkey" = {
|
||||
sopsFile = ../../secrets/universal.yaml;
|
||||
};
|
||||
|
||||
sops.secrets."snippets" = {
|
||||
sopsFile = ../../secrets/universal/snippets.bin;
|
||||
format = "binary";
|
||||
owner = config.users.users.colin.name;
|
||||
};
|
||||
|
||||
sops.secrets."bt/car" = {
|
||||
sopsFile = ../../secrets/universal/bt/car.bin;
|
||||
format = "binary";
|
||||
};
|
||||
sops.secrets."bt/earbuds" = {
|
||||
sopsFile = ../../secrets/universal/bt/earbuds.bin;
|
||||
format = "binary";
|
||||
};
|
||||
sops.secrets."bt/portable-speaker" = {
|
||||
sopsFile = ../../secrets/universal/bt/portable-speaker.bin;
|
||||
format = "binary";
|
||||
};
|
||||
|
||||
sops.secrets."iwd/community-university.psk" = {
|
||||
sopsFile = ../../secrets/universal/net/community-university.psk.bin;
|
||||
format = "binary";
|
||||
};
|
||||
sops.secrets."iwd/friend-libertarian-dod.psk" = {
|
||||
sopsFile = ../../secrets/universal/net/friend-libertarian-dod.psk.bin;
|
||||
format = "binary";
|
||||
};
|
||||
sops.secrets."iwd/friend-rationalist-empathist.psk" = {
|
||||
sopsFile = ../../secrets/universal/net/friend-rationalist-empathist.psk.bin;
|
||||
format = "binary";
|
||||
};
|
||||
sops.secrets."iwd/home-bedroom.psk" = {
|
||||
sopsFile = ../../secrets/universal/net/home-bedroom.psk.bin;
|
||||
format = "binary";
|
||||
};
|
||||
sops.secrets."iwd/home-shared-24G.psk" = {
|
||||
sopsFile = ../../secrets/universal/net/home-shared-24G.psk.bin;
|
||||
format = "binary";
|
||||
};
|
||||
sops.secrets."iwd/home-shared.psk" = {
|
||||
sopsFile = ../../secrets/universal/net/home-shared.psk.bin;
|
||||
format = "binary";
|
||||
};
|
||||
sops.secrets."iwd/iphone" = {
|
||||
sopsFile = ../../secrets/universal/net/iphone.psk.bin;
|
||||
format = "binary";
|
||||
};
|
||||
sops.secrets."iwd/parents" = {
|
||||
sopsFile = ../../secrets/universal/net/parents.psk.bin;
|
||||
format = "binary";
|
||||
};
|
||||
sops.secrets = lib.mkMerge [
|
||||
(secretsForHost "common")
|
||||
(secretsForHost config.networking.hostName)
|
||||
{
|
||||
"jackett_apikey".owner = config.users.users.colin.name;
|
||||
"mx-sanebot-env".owner = config.users.users.colin.name;
|
||||
"snippets".owner = config.users.users.colin.name;
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,10 +1,33 @@
|
||||
{ config, lib, ... }:
|
||||
{ config, lib, sane-data, sane-lib, ... }:
|
||||
|
||||
let
|
||||
inherit (builtins) head map mapAttrs tail;
|
||||
inherit (lib) concatStringsSep mkMerge reverseList;
|
||||
in
|
||||
{
|
||||
environment.etc."ssh/host_keys".source = "/nix/persist/etc/ssh/host_keys";
|
||||
|
||||
services.openssh.hostKeys = [
|
||||
{ type = "rsa"; bits = 4096; path = "/etc/ssh/host_keys/ssh_host_rsa_key"; }
|
||||
{ type = "ed25519"; path = "/etc/ssh/host_keys/ssh_host_ed25519_key"; }
|
||||
];
|
||||
sane.ssh.pubkeys =
|
||||
let
|
||||
# path is a DNS-style path like [ "org" "uninsane" "root" ]
|
||||
keyNameForPath = path:
|
||||
let
|
||||
rev = reverseList path;
|
||||
name = head rev;
|
||||
host = concatStringsSep "." (tail rev);
|
||||
in
|
||||
"${name}@${host}";
|
||||
|
||||
# [{ path :: [String], value :: String }] for the keys we want to install
|
||||
globalKeys = sane-lib.flattenAttrs sane-data.keys;
|
||||
domainKeys = sane-lib.flattenAttrs (
|
||||
mapAttrs (host: cfg: {
|
||||
colin = cfg.ssh.user_pubkey;
|
||||
root = cfg.ssh.host_pubkey;
|
||||
}) config.sane.hosts.by-name
|
||||
);
|
||||
in mkMerge (map
|
||||
({ path, value }: {
|
||||
"${keyNameForPath path}" = lib.mkIf (value != null) value;
|
||||
})
|
||||
(globalKeys ++ domainKeys)
|
||||
);
|
||||
}
|
||||
|
@@ -1,17 +1,14 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
{ config, pkgs, lib, sane-lib, ... }:
|
||||
|
||||
# installer docs: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/installation-device.nix
|
||||
with lib;
|
||||
let
|
||||
cfg = config.sane.users;
|
||||
# see nixpkgs/nixos/modules/services/networking/dhcpcd.nix
|
||||
hasDHCP = config.networking.dhcpcd.enable &&
|
||||
(config.networking.useDHCP || any (i: i.useDHCP == true) (attrValues config.networking.interfaces));
|
||||
|
||||
cfg = config.sane.guest;
|
||||
fs = sane-lib.fs;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
sane.users.guest.enable = mkOption {
|
||||
sane.guest.enable = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
};
|
||||
@@ -28,8 +25,7 @@ in
|
||||
isNormalUser = true;
|
||||
home = "/home/colin";
|
||||
createHome = true;
|
||||
homeMode = "700";
|
||||
uid = config.sane.allocations.colin-uid;
|
||||
homeMode = "0700";
|
||||
# i don't get exactly what this is, but nixos defaults to this non-deterministically
|
||||
# in /var/lib/nixos/auto-subuid-map and i don't want that.
|
||||
subUidRanges = [
|
||||
@@ -37,13 +33,14 @@ in
|
||||
];
|
||||
group = "users";
|
||||
extraGroups = [
|
||||
"wheel"
|
||||
"nixbuild"
|
||||
"networkmanager"
|
||||
# phosh/mobile. XXX colin: unsure if necessary
|
||||
"video"
|
||||
"dialout" # required for modem access (moby)
|
||||
"feedbackd"
|
||||
"dialout" # required for modem access
|
||||
"input" # for /dev/input/<xyz>: sxmo
|
||||
"networkmanager"
|
||||
"nixbuild"
|
||||
"video" # phosh/mobile. XXX colin: unsure if necessary
|
||||
"wheel"
|
||||
"wireshark"
|
||||
];
|
||||
|
||||
# initial password is empty, in case anything goes wrong.
|
||||
@@ -52,53 +49,71 @@ in
|
||||
passwordFile = lib.mkIf (config.sops.secrets ? "colin-passwd") config.sops.secrets.colin-passwd.path;
|
||||
|
||||
shell = pkgs.zsh;
|
||||
openssh.authorizedKeys.keys = builtins.attrValues (import ../../modules/pubkeys.nix).users;
|
||||
|
||||
# mount encrypted stuff at login
|
||||
# some other nix pam users:
|
||||
# - <https://github.com/g00pix/nixconf/blob/32c04f6fa843fed97639dd3f09e157668d3eea1f/profiles/sshfs.nix>
|
||||
# - <https://github.com/lourkeur/distro/blob/11173454c6bb50f7ccab28cc2c757dca21446d1d/nixos/profiles/users/louis-full.nix>
|
||||
# - <https://github.com/dnr/sample-nix-code/blob/03494480c1fae550c033aa54fd96aeb3827761c5/nixos/laptop.nix>
|
||||
pamMount = {
|
||||
# mount encrypted stuff at login
|
||||
# requires that login password == fs encryption password
|
||||
fstype = "fuse";
|
||||
path = "gocryptfs#/nix/persist/home/colin/private";
|
||||
# path = "${pkgs.gocryptfs}/bin/gocryptfs#/nix/persist/home/colin/private";
|
||||
# fstype = "fuse.gocryptfs";
|
||||
# path = "/nix/persist/home/colin/private";
|
||||
mountpoint = "/home/colin/private";
|
||||
# without allow_other, *root* isn't allowed to list anything in ~/private.
|
||||
# which is weird (root can just `su colin`), but probably doesn't *hurt* anything -- right?
|
||||
options="nodev,nosuid,quiet"; # allow_other
|
||||
pamMount = let
|
||||
priv = config.fileSystems."/home/colin/private";
|
||||
in {
|
||||
fstype = priv.fsType;
|
||||
path = priv.device;
|
||||
mountpoint = priv.mountPoint;
|
||||
options = builtins.concatStringsSep "," priv.options;
|
||||
};
|
||||
};
|
||||
|
||||
# required for PAM to find gocryptfs
|
||||
security.pam.mount.additionalSearchPaths = [ pkgs.gocryptfs ];
|
||||
security.pam.mount.enable = true;
|
||||
# security.pam.mount.debugLevel = 1;
|
||||
# security.pam.enableSSHAgentAuth = true; # ??
|
||||
# needed for `allow_other` in e.g. gocryptfs mounts
|
||||
# or i guess going through mount.fuse sets suid so that's not necessary?
|
||||
# programs.fuse.userAllowOther = true;
|
||||
|
||||
sane.impermanence.home-dirs = [
|
||||
# cache is probably too big to fit on the tmpfs
|
||||
# { directory = ".cache"; encryptedClearOnBoot = true; }
|
||||
{ directory = ".cache/mozilla"; encryptedClearOnBoot = true; }
|
||||
".cargo"
|
||||
".rustup"
|
||||
# TODO: move this to ~/private!
|
||||
".local/share/keyrings"
|
||||
sane.users.colin.default = true;
|
||||
# ensure ~ perms are known to sane.fs module.
|
||||
# TODO: this is generic enough to be lifted up into sane.fs itself.
|
||||
sane.fs."/home/colin".dir.acl = {
|
||||
user = "colin";
|
||||
group = config.users.users.colin.group;
|
||||
mode = config.users.users.colin.homeMode;
|
||||
};
|
||||
|
||||
sane.user.persist.plaintext = [
|
||||
"archive"
|
||||
"dev"
|
||||
# TODO: records should be private
|
||||
"records"
|
||||
"ref"
|
||||
"tmp"
|
||||
"use"
|
||||
"Music"
|
||||
"Pictures"
|
||||
"Videos"
|
||||
|
||||
".cache/nix"
|
||||
".cache/nix-index"
|
||||
|
||||
# ".cargo"
|
||||
# ".rustup"
|
||||
];
|
||||
|
||||
sane.impermanence.dirs = mkIf cfg.guest.enable [
|
||||
{ user = "guest"; group = "users"; directory = "/home/guest"; }
|
||||
# convenience
|
||||
sane.user.fs."knowledge" = fs.wantedSymlinkTo "private/knowledge";
|
||||
sane.user.fs."nixos" = fs.wantedSymlinkTo "dev/nixos";
|
||||
sane.user.fs."Books/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Books";
|
||||
sane.user.fs."Videos/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Videos";
|
||||
sane.user.fs."Videos/servo-incomplete" = fs.wantedSymlinkTo "/mnt/servo-media/incomplete";
|
||||
sane.user.fs."Music/servo" = fs.wantedSymlinkTo "/mnt/servo-media/Music";
|
||||
sane.user.fs."Pictures/servo-macros" = fs.wantedSymlinkTo "/mnt/servo-media/Pictures/macros";
|
||||
|
||||
# used by password managers, e.g. unix `pass`
|
||||
sane.user.fs.".password-store" = fs.wantedSymlinkTo "knowledge/secrets/accounts";
|
||||
|
||||
sane.persist.sys.plaintext = mkIf cfg.enable [
|
||||
# intentionally allow other users to write to the guest folder
|
||||
{ directory = "/home/guest"; user = "guest"; group = "users"; mode = "0775"; }
|
||||
];
|
||||
users.users.guest = mkIf cfg.guest.enable {
|
||||
users.users.guest = mkIf cfg.enable {
|
||||
isNormalUser = true;
|
||||
home = "/home/guest";
|
||||
uid = config.sane.allocations.guest-uid;
|
||||
subUidRanges = [
|
||||
{ startUid=200000; count=1; }
|
||||
];
|
||||
@@ -110,13 +125,6 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
users.users.dhcpcd = mkIf hasDHCP {
|
||||
uid = config.sane.allocations.dhcpcd-uid;
|
||||
};
|
||||
users.groups.dhcpcd = mkIf hasDHCP {
|
||||
gid = config.sane.allocations.dhcpcd-gid;
|
||||
};
|
||||
|
||||
security.sudo = {
|
||||
enable = true;
|
||||
wheelNeedsPassword = false;
|
||||
@@ -124,34 +132,8 @@ in
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
permitRootLogin = "no";
|
||||
passwordAuthentication = false;
|
||||
settings.PermitRootLogin = "no";
|
||||
settings.PasswordAuthentication = false;
|
||||
};
|
||||
|
||||
# affix some UIDs which were historically auto-generated
|
||||
users.users.sshd.uid = config.sane.allocations.sshd-uid;
|
||||
users.groups.polkituser.gid = config.sane.allocations.polkituser-gid;
|
||||
users.groups.sshd.gid = config.sane.allocations.sshd-gid;
|
||||
users.groups.systemd-coredump.gid = config.sane.allocations.systemd-coredump-gid;
|
||||
users.users.nscd.uid = config.sane.allocations.nscd-uid;
|
||||
users.groups.nscd.gid = config.sane.allocations.nscd-gid;
|
||||
users.users.systemd-oom.uid = config.sane.allocations.systemd-oom-uid;
|
||||
users.groups.systemd-oom.gid = config.sane.allocations.systemd-oom-gid;
|
||||
|
||||
# guarantee determinism in uid/gid generation for users:
|
||||
assertions = let
|
||||
uidAssertions = builtins.attrValues (builtins.mapAttrs (name: user: {
|
||||
assertion = user.uid != null;
|
||||
message = "non-deterministic uid detected for: ${name}";
|
||||
}) config.users.users);
|
||||
gidAssertions = builtins.attrValues (builtins.mapAttrs (name: group: {
|
||||
assertion = group.gid != null;
|
||||
message = "non-deterministic gid detected for: ${name}";
|
||||
}) config.users.groups);
|
||||
autoSubAssertions = builtins.attrValues (builtins.mapAttrs (name: user: {
|
||||
assertion = !user.autoSubUidGidRange;
|
||||
message = "non-deterministic subUids/Guids detected for: ${name}";
|
||||
}) config.users.users);
|
||||
in uidAssertions ++ gidAssertions ++ autoSubAssertions;
|
||||
};
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@ let
|
||||
def-ovpn = name: { endpoint, publicKey, address }: {
|
||||
networking.wg-quick.interfaces."ovpnd-${name}" = {
|
||||
inherit address;
|
||||
privateKeyFile = config.sops.secrets."wg_ovpnd_${name}_privkey".path;
|
||||
privateKeyFile = config.sops.secrets."wg/ovpnd_${name}_privkey".path;
|
||||
dns = [
|
||||
"46.227.67.134"
|
||||
"192.165.9.158"
|
||||
|
@@ -1,10 +1,18 @@
|
||||
# trampoline from flake.nix into the specific host definition, while doing a tiny bit of common setup
|
||||
|
||||
hostName: { ... }: {
|
||||
# args from flake-level `import`
|
||||
{ hostName, localSystem }:
|
||||
|
||||
# module args
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./${hostName}
|
||||
./by-name/${hostName}
|
||||
./common
|
||||
./modules
|
||||
];
|
||||
|
||||
networking.hostName = hostName;
|
||||
nixpkgs.buildPlatform = lib.mkIf (localSystem != null) localSystem;
|
||||
}
|
||||
|
@@ -1,143 +0,0 @@
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
# use the last commit on the 5.18 branch (5.18.14)
|
||||
# manjaro's changes between kernel patch versions tend to be minimal if any.
|
||||
manjaroBase = "https://gitlab.manjaro.org/manjaro-arm/packages/core/linux/-/raw/25bd828cd47b1c6e09fcbcf394a649b89d2876dd";
|
||||
manjaroPatch = name: sha256: {
|
||||
inherit name;
|
||||
patch = pkgs.fetchpatch {
|
||||
inherit name;
|
||||
url = "${manjaroBase}/${name}?inline=false";
|
||||
inherit sha256;
|
||||
};
|
||||
};
|
||||
|
||||
# the idea for patching off Manjaro's kernel comes from jakewaksbaum:
|
||||
# - https://git.sr.ht/~jakewaksbaum/pi/tree/af20aae5653545d6e67a459b59ee3e1ca8a680b0/item/kernel/default.nix
|
||||
# - he later abandoned this, i think because he's using the Pinephone Pro which received mainline support.
|
||||
manjaroPatches = [
|
||||
(manjaroPatch
|
||||
"1001-arm64-dts-allwinner-add-hdmi-sound-to-pine-devices.patch"
|
||||
"sha256-DApd791A+AxB28Ven/MVAyuyVphdo8KQDx8O7oxVPnc="
|
||||
)
|
||||
# these patches below are critical to enable wifi (RTL8723CS)
|
||||
# - the alternative is a wholly forked kernel by megi/megous:
|
||||
# - https://xnux.eu/howtos/build-pinephone-kernel.html#toc-how-to-build-megi-s-pinehpone-kernel
|
||||
# - i don't know if these patches are based on megi's or original
|
||||
(manjaroPatch
|
||||
"2001-Bluetooth-Add-new-quirk-for-broken-local-ext-features.patch"
|
||||
"sha256-CExhJuUWivegxPdnzKINEsKrMFx/m/1kOZFmlZ2SEOc="
|
||||
)
|
||||
(manjaroPatch
|
||||
"2002-Bluetooth-btrtl-add-support-for-the-RTL8723CS.patch"
|
||||
"sha256-dDdvOphTcP/Aog93HyH+L9m55laTgtjndPSE4/rnzUA="
|
||||
)
|
||||
(manjaroPatch
|
||||
"2004-arm64-dts-allwinner-enable-bluetooth-pinetab-pinepho.patch"
|
||||
"sha256-o43P3WzXyHK1PF+Kdter4asuyGAEKO6wf5ixcco2kCQ="
|
||||
)
|
||||
# XXX: this one has a Makefile, which hardcodes /sbin/depmod:
|
||||
# - drivers/staging/rtl8723cs/Makefile
|
||||
# - not sure if this is problematic?
|
||||
(manjaroPatch
|
||||
"2005-staging-add-rtl8723cs-driver.patch"
|
||||
"sha256-6ywm3dQQ5JYl60CLKarxlSUukwi4QzqctCj3tVgzFbo="
|
||||
)
|
||||
];
|
||||
|
||||
# pinephone uses the linux dtb at arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
# - this includes sun50i-a64.dtsi
|
||||
# - and sun50i-a64-cpu-opp.dtsi
|
||||
# - no need to touch the allwinner-h6 stuff: that's the SBC pine product
|
||||
# - i think it's safe to ignore sun9i stuff, but i don't know what it is
|
||||
kernelConfig = with lib.kernel; {
|
||||
# NB: nix adds the CONFIG_ prefix to each of these.
|
||||
# if you add the prefix yourself nix will IGNORE YOUR CONFIG.
|
||||
RTL8723CS = module;
|
||||
BT_HCIUART_3WIRE = yes;
|
||||
BT_HCIUART_RTL = yes;
|
||||
RTL8XXXU_UNTESTED = yes;
|
||||
BT_BNEP_MC_FILTER = yes;
|
||||
BT_BNEP_PROTO_FILTER = yes;
|
||||
BT_HS = yes;
|
||||
BT_LE = yes;
|
||||
# relevant configs inherited from nixos defaults (or above additions):
|
||||
# CONFIG_BT=m
|
||||
# CONFIG_BT_BREDR=y
|
||||
# CONFIG_BT_RFCOMM=m
|
||||
# CONFIG_BT_RFCOMM_TTY=y
|
||||
# CONFIG_BT_BNEP=m
|
||||
# CONFIG_BT_HIDP=m
|
||||
# CONFIG_BT_RTL=m
|
||||
# CONFIG_BT_HCIBTUSB=m
|
||||
# CONFIG_BT_HCIBTUSB_BCM=y
|
||||
# CONFIG_BT_HCIBTUSB_RTL=y
|
||||
# CONFIG_BT_HCIUART=m
|
||||
# CONFIG_BT_HCIUART_SERDEV=y
|
||||
# CONFIG_BT_HCIUART_H4=y
|
||||
# CONFIG_BT_HCIUART_LL=y
|
||||
# CONFIG_RTL_CARDS=m
|
||||
# CONFIG_RTLWIFI=m
|
||||
# CONFIG_RTLWIFI_PCI=m
|
||||
# CONFIG_RTLWIFI_USB=m
|
||||
# CONFIG_RTLWIFI_DEBUG=y
|
||||
# CONFIG_RTL8723_COMMON=m
|
||||
# CONFIG_RTLBTCOEXIST=m
|
||||
# CONFIG_RTL8XXXU=m
|
||||
# CONFIG_RTLLIB=m
|
||||
# consider adding (from mobile-nixos):
|
||||
# maybe: CONFIG_BT_HCIUART_3WIRE=y
|
||||
# maybe: CONFIG_BT_HCIUART_RTL=y
|
||||
# maybe: CONFIG_RTL8XXXU_UNTESTED=y
|
||||
# consider adding (from manjaro):
|
||||
# CONFIG_BT_6LOWPAN=m (not listed as option in nixos kernel)
|
||||
# these are referenced in the rtl8723 source, but not known to config (and not in mobile-nixos config
|
||||
# maybe: CONFIG_RTL_ODM_WLAN_DRIVER
|
||||
# maybe: CONFIG_RTL_TRIBAND_SUPPORT
|
||||
# maybe: CONFIG_SDIO_HCI
|
||||
# maybe: CONFIG_USB_HCI
|
||||
};
|
||||
|
||||
# create a kernelPatch which overrides nixos' defconfig with extra options
|
||||
patchDefconfig = config: {
|
||||
# defconfig options. this method comes from here:
|
||||
# - https://discourse.nixos.org/t/the-correct-way-to-override-the-latest-kernel-config/533/9
|
||||
name = "sane-moby-defconfig";
|
||||
patch = null;
|
||||
extraStructuredConfig = config;
|
||||
};
|
||||
in
|
||||
{
|
||||
# use Megi's kernel:
|
||||
# even with the Manjaro patches, stock 5.18 has a few issues on Pinephone:
|
||||
# - no battery charging
|
||||
# - phone rotation sensor is off by 90 degrees
|
||||
# - ambient light sensor causes screen brightness to be shakey
|
||||
# - phosh greeter may not appear after wake from sleep
|
||||
boot.kernelPackages = pkgs.cross.linuxPackagesFor pkgs.cross.linux-megous;
|
||||
|
||||
boot.kernelPatches = [
|
||||
(patchDefconfig (kernelConfig //
|
||||
(with lib.kernel; {
|
||||
# disabling the sun5i_eink driver avoids this compilation error:
|
||||
# CC [M] drivers/video/fbdev/sun5i-eink-neon.o
|
||||
# aarch64-unknown-linux-gnu-gcc: error: unrecognized command line option '-mfloat-abi=softfp'
|
||||
# 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
|
||||
FB_SUN5I_EINK = no;
|
||||
})
|
||||
))
|
||||
];
|
||||
|
||||
# alternatively, use nixos' kernel and add the stuff we want:
|
||||
# # cross-compilation optimization:
|
||||
# boot.kernelPackages =
|
||||
# let p = (import nixpkgs { localSystem = "x86_64-linux"; });
|
||||
# in p.pkgsCross.aarch64-multiplatform.linuxPackages_5_18;
|
||||
# # non-cross:
|
||||
# # boot.kernelPackages = pkgs.linuxPackages_5_18;
|
||||
|
||||
# boot.kernelPatches = manjaroPatches ++ [
|
||||
# (patchDefconfig kernelConfig)
|
||||
# ];
|
||||
}
|
16
hosts/modules/default.nix
Normal file
16
hosts/modules/default.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./derived-secrets.nix
|
||||
./gui
|
||||
./hardware
|
||||
./hostnames.nix
|
||||
./hosts.nix
|
||||
./nixcache.nix
|
||||
./roles
|
||||
./services
|
||||
./wg-home.nix
|
||||
./yggdrasil.nix
|
||||
];
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user