Compare commits
695 Commits
snowfall
...
3e232c3474
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e232c3474 | ||
|
|
e6c9e21c62 | ||
| de8ec35cbb | |||
| 3e6e975ce5 | |||
| 897ca32919 | |||
| 8d2b16825a | |||
| 33f0a085ef | |||
|
|
798f233ff2 | ||
|
|
f968cc0e8d | ||
|
|
cd6188775f | ||
|
|
e13c19e698 | ||
|
|
56c2ef7b96 | ||
|
|
829b369ebe | ||
|
|
9891b3abff | ||
|
|
8fc34adfc6 | ||
|
|
56c3bfdd91 | ||
|
|
21a9b476e2 | ||
|
|
2314dd3225 | ||
|
|
9cd0677ba0 | ||
|
|
2699bc0f0d | ||
|
|
996571a544 | ||
|
|
4f4b7865eb | ||
|
|
c5e97ac853 | ||
|
|
778e9ce02b | ||
|
|
39b898bcf2 | ||
|
|
9737b3af9f | ||
|
|
3862a6b651 | ||
|
|
2500f5ffa0 | ||
|
|
8d3574e183 | ||
|
|
631d7336f6 | ||
|
|
01f6eeff7c | ||
| 2fbfd9c2d3 | |||
| 89196706c7 | |||
|
|
1616c6766e | ||
|
|
c13ce86810 | ||
|
|
cce8f2ea03 | ||
|
|
75c64f2499 | ||
|
|
9daf43e3f3 | ||
|
|
f369128cb7 | ||
|
|
6210605ac2 | ||
|
|
f1493146ab | ||
|
|
86acd96e07 | ||
|
|
e5b7c403a3 | ||
|
|
805699d9d0 | ||
|
|
bcc7214c43 | ||
|
|
52bc808a0a | ||
|
|
0beecf9cce | ||
|
|
eac037caf8 | ||
|
|
56c4e1fcad | ||
|
|
8d299980fb | ||
| a2ee0e2a55 | |||
|
|
401e5f7bd8 | ||
|
|
2398b810dc | ||
| 79b0fdf4c4 | |||
|
|
46d35ab70e | ||
|
|
0dc60c261b | ||
|
|
23f5f6c3b3 | ||
|
|
d17d096a97 | ||
| 5f79421d9e | |||
| 5eaf1cce2a | |||
| 85b35eaedc | |||
|
|
3c4856ddca | ||
| ff92934cc4 | |||
| c304fefb54 | |||
|
|
9b1c9a6371 | ||
|
|
b0ecedaf2a | ||
|
|
8d7a112365 | ||
| 5994b99288 | |||
|
|
9e755ab926 | ||
| e277a56233 | |||
| 41361e5bc1 | |||
|
|
85b69d69ff | ||
| 9a962363e8 | |||
|
|
d856b57f13 | ||
|
|
7e85953133 | ||
|
|
3655680e7c | ||
|
|
1fc2a7a89f | ||
|
|
ddd99ef396 | ||
|
|
ff9aea7a58 | ||
|
|
4c5118c181 | ||
|
|
2e0d6aebb5 | ||
|
|
974b696ef8 | ||
| afccded50c | |||
|
|
0d835df1aa | ||
|
|
d7958927b5 | ||
| a5162e9e76 | |||
| ed19748358 | |||
|
|
2efe3fa067 | ||
|
|
c7a3aa6897 | ||
|
|
f7ecb901db | ||
|
|
66ee83167f | ||
|
|
1740116e6b | ||
|
|
80204acfb6 | ||
|
|
c50aa6d68e | ||
|
|
99a6b40776 | ||
|
|
d855e75e48 | ||
|
|
ae9075e795 | ||
|
|
3b3ec68a3c | ||
|
|
e771770ae2 | ||
|
|
17a1307343 | ||
|
|
fe77b68446 | ||
|
|
6ebc1bb103 | ||
|
|
869a320ede | ||
|
|
fd437ec528 | ||
|
|
9a63c609fa | ||
|
|
b46628a747 | ||
|
|
48d864bb64 | ||
|
|
92b6e7a822 | ||
|
|
89275509f3 | ||
|
|
28c6306182 | ||
|
|
535fdc2f86 | ||
|
|
09d9b010b7 | ||
|
|
ec76404122 | ||
| 5c94bd7fcb | |||
| 07e8fc704f | |||
|
|
27e0a448b8 | ||
| 50773eda54 | |||
| c8f8fce410 | |||
| 2184135c7c | |||
| 60df52b090 | |||
| 5e6edd00bb | |||
| 319923c57c | |||
| eb2ebdca84 | |||
|
|
d9c801530d | ||
| f5b0b16c22 | |||
| a95bc4db39 | |||
| b5b5bf43e2 | |||
| 49e60a0d27 | |||
| 3d21a345c3 | |||
| a740e1c33a | |||
|
|
bc16420869 | ||
|
|
1731647367 | ||
|
|
9ad06425c8 | ||
| 525cc60739 | |||
|
|
3595428e02 | ||
| 4ed90347f8 | |||
| b92dda099b | |||
|
|
f61dbc7190 | ||
| a48fc8fffe | |||
|
|
4d107533ea | ||
|
|
2c3cc8ed18 | ||
|
|
334d69894e | ||
|
|
31a9957877 | ||
|
|
dc25f02010 | ||
|
|
ef8e52b93f | ||
|
|
bf48d8fcf0 | ||
|
|
a68c91264f | ||
|
|
75d7097e23 | ||
|
|
b738f38267 | ||
|
|
32b0e67a7a | ||
|
|
f352ef1c05 | ||
|
|
1ea8c8b6a9 | ||
|
|
eac9c4b67d | ||
|
|
ce4047b62f | ||
|
|
aff6fa9ec6 | ||
|
|
a9c1d71495 | ||
|
|
4d4808490b | ||
|
|
1f99318fcd | ||
|
|
87fb1c96e5 | ||
|
|
aa7fc9c228 | ||
|
|
f856076452 | ||
|
|
d9d7760e58 | ||
|
|
bd8d1e6485 | ||
|
|
8fa82bce90 | ||
|
|
187b478c5d | ||
|
|
25ef179d3a | ||
|
|
57d1a8d864 | ||
|
|
c83cfcf06b | ||
|
|
59268d1da3 | ||
|
|
bca4a13614 | ||
|
|
044bac7464 | ||
|
|
10fa5498ee | ||
|
|
1331e69b58 | ||
|
|
9c8733431d | ||
|
|
ad15679eb4 | ||
|
|
01ae622391 | ||
|
|
defbd725dd | ||
|
|
d2c1cbf987 | ||
|
|
14db694b90 | ||
|
|
10fc7820e1 | ||
|
|
176d0b7311 | ||
|
|
1fc2ce66cf | ||
|
|
f93d69a259 | ||
|
|
d7afac2fb9 | ||
|
|
3aa0407532 | ||
|
|
c29ff231f9 | ||
| c5481909a1 | |||
|
|
8b4489cf8f | ||
|
|
d1d68e154d | ||
|
|
3ff7bed41d | ||
|
|
19acd60ed7 | ||
|
|
6cfb31fdc9 | ||
|
|
e5dbeadbb6 | ||
|
|
302d7f5af5 | ||
|
|
148229f551 | ||
|
|
5a22ad0f88 | ||
|
|
5b96b59e60 | ||
|
|
bfd5e90613 | ||
|
|
fdaa34191c | ||
|
|
fde852b29b | ||
|
|
d4e0b93e4e | ||
|
|
1410f0fe25 | ||
|
|
5fed9a649f | ||
|
|
9b87aa9d3e | ||
|
|
e7a6fdb644 | ||
|
|
871f099dac | ||
|
|
a07f694806 | ||
|
|
45f40e45d8 | ||
|
|
7c7c1dc3f4 | ||
|
|
bd44913ccc | ||
|
|
a5b53e66e7 | ||
|
|
5d9613ee13 | ||
|
|
3dea6e0a9e | ||
|
|
9ab1c99914 | ||
|
|
62ff7b829a | ||
|
|
477b79bfb8 | ||
|
|
e2e2d814fe | ||
|
|
94c3d6d6ff | ||
|
|
a336b0cf60 | ||
|
|
a94e68514a | ||
|
|
fb68d25008 | ||
|
|
2b9908e760 | ||
|
|
7cc4e8c99e | ||
|
|
fbdbbdf328 | ||
|
|
d4799b6598 | ||
|
|
6a9ec8f933 | ||
|
|
fa236b7076 | ||
|
|
05bd3f1a60 | ||
|
|
a3ade57500 | ||
|
|
e40181ba04 | ||
|
|
cedd4051f7 | ||
|
|
5a992567b8 | ||
|
|
631bdd3c2c | ||
|
|
a968cb4b4f | ||
|
|
d76fdcbab6 | ||
|
|
e2dfca0245 | ||
|
|
59500f3e50 | ||
|
|
a74305a444 | ||
|
|
e39614a9c8 | ||
|
|
b5de056631 | ||
|
|
49680a9188 | ||
|
|
c3865f2742 | ||
|
|
341d522fd4 | ||
|
|
51f4b335b1 | ||
|
|
77dc15e0e1 | ||
|
|
a0c2753f37 | ||
|
|
7320b0ee87 | ||
|
|
10268e7677 | ||
|
|
f57617e268 | ||
|
|
b613f941a6 | ||
|
|
b3138d0fca | ||
|
|
9376005a21 | ||
|
|
549580395f | ||
|
|
3f5634317b | ||
|
|
26746873f3 | ||
|
|
a58a9da64e | ||
|
|
8e7a0343c2 | ||
|
|
d47b092a8c | ||
|
|
4de54dee30 | ||
|
|
455ea26cdc | ||
|
|
7306b08762 | ||
|
|
59b4729636 | ||
|
|
afe04b88b0 | ||
|
|
b1215da790 | ||
|
|
b1f2521260 | ||
|
|
57add82f95 | ||
|
|
49485c91a6 | ||
|
|
a7c25fe70d | ||
|
|
1dc075f405 | ||
|
|
2a17112d50 | ||
|
|
a59d5ce3b1 | ||
|
|
639ce36cb0 | ||
|
|
42e771ef1f | ||
|
|
37d472c7db | ||
|
|
382f059188 | ||
|
|
dfd8d9a1a8 | ||
|
|
fcddde0c06 | ||
|
|
ad16b47827 | ||
|
|
994fddba66 | ||
|
|
0483ea8a67 | ||
|
|
b6e5223d96 | ||
|
|
ed7656cf3e | ||
|
|
76b6255169 | ||
|
|
5f5972f10f | ||
|
|
82dffdf505 | ||
|
|
741ab5c7ec | ||
|
|
3d0d5c878c | ||
|
|
0bb71bbb4f | ||
|
|
741de00ef7 | ||
|
|
c7c5192c0c | ||
|
|
052f7a2838 | ||
|
|
ca17f0fe18 | ||
|
|
e76f74e63a | ||
|
|
88e81c9aaa | ||
|
|
8406714527 | ||
|
|
97e4060b52 | ||
|
|
59121cf43b | ||
|
|
e15d62d03a | ||
|
|
3268c28cc8 | ||
|
|
e4ac3b99cd | ||
|
|
dabd791fac | ||
|
|
98c627531c | ||
|
|
c8f41cf7d8 | ||
|
|
78f8d1a733 | ||
|
|
b05067a3e1 | ||
|
|
3b780d4d78 | ||
|
|
77c76e6483 | ||
|
|
cd03862e4b | ||
|
|
e6a69cc21f | ||
|
|
c6317cdd18 | ||
|
|
ca73743483 | ||
|
|
105ed3bcb8 | ||
|
|
4a6a68dad4 | ||
|
|
56154fe941 | ||
|
|
b7380317b9 | ||
|
|
579c83164e | ||
|
|
56fb195967 | ||
|
|
451f5aa726 | ||
|
|
5c359dca81 | ||
|
|
6b28a8df9c | ||
|
|
dfc2c8faa4 | ||
|
|
0f42ffeebd | ||
|
|
1d5b1cf5e0 | ||
|
|
8fc40f265b | ||
|
|
cdf388cf17 | ||
|
|
8088ea0933 | ||
|
|
9305483e09 | ||
|
|
687a3a6446 | ||
|
|
1e5ef59d56 | ||
|
|
a7389ac9b2 | ||
|
|
501329def1 | ||
|
|
3063d6b161 | ||
|
|
c4ea874ae7 | ||
|
|
68dbe98370 | ||
|
|
374bd4348f | ||
|
|
5ee4da5b08 | ||
|
|
bf31786735 | ||
|
|
b216fe5215 | ||
|
|
b36ae0914c | ||
|
|
edd6291176 | ||
|
|
b91afbc323 | ||
|
|
450dc1ad91 | ||
|
|
eed1d28bd8 | ||
|
|
ae8bcdf690 | ||
|
|
4ac6de479c | ||
|
|
14990b28e4 | ||
|
|
ede0bf5c10 | ||
|
|
ae95786d8e | ||
|
|
209e776640 | ||
|
|
82e062a7e8 | ||
|
|
67fb7d7323 | ||
|
|
462494277a | ||
|
|
8fbf8c54eb | ||
|
|
f549723a61 | ||
|
|
c8aebb9e4a | ||
|
|
afb60fc031 | ||
|
|
4604e24ee5 | ||
|
|
3233955690 | ||
|
|
c9f75a053c | ||
|
|
f7cb1cb217 | ||
|
|
d981fb20c2 | ||
|
|
8f08f24761 | ||
|
|
74e772582d | ||
|
|
15f186e3ce | ||
|
|
7d92e9b1cc | ||
|
|
53a2d01a83 | ||
|
|
abdeddf751 | ||
|
|
1280cf9939 | ||
|
|
76265f9b1b | ||
|
|
66fe87dd23 | ||
|
|
e8fcf96253 | ||
|
|
479ac18f20 | ||
|
|
ba446f408a | ||
|
|
05486efb75 | ||
|
|
e0b1e72431 | ||
|
|
63bd725d64 | ||
|
|
96ce0001c5 | ||
|
|
50345adeb5 | ||
|
|
e74ea5f13b | ||
|
|
367c3a16c5 | ||
|
|
4c784f5f33 | ||
|
|
fa0210e937 | ||
|
|
f803c37105 | ||
|
|
03b00c59b2 | ||
|
|
5c9a42fe71 | ||
|
|
3b95a97921 | ||
|
|
2d03954a9f | ||
|
|
3dc1055b54 | ||
|
|
fedba849a7 | ||
|
|
34539045e5 | ||
|
|
0012a019fc | ||
|
|
f09246dcba | ||
|
|
90daf80a88 | ||
|
|
3c85ea0515 | ||
|
|
06e26e3be2 | ||
|
|
d76eff6f68 | ||
|
|
ce39a330b1 | ||
|
|
41063a1ef7 | ||
|
|
35206c8ed5 | ||
|
|
201ba0b780 | ||
|
|
a273c701ab | ||
|
|
2e4b629805 | ||
|
|
3364ae8fda | ||
|
|
15e0b9563f | ||
|
|
64f34892b7 | ||
|
|
8d1a9312cb | ||
|
|
31202f8b0e | ||
|
|
82ecfba7db | ||
|
|
f86808d86e | ||
|
|
89c5d60be3 | ||
|
|
96c3a34449 | ||
|
|
a5eba8ec68 | ||
|
|
764ce12aea | ||
|
|
989e717e4e | ||
|
|
4b53a89030 | ||
|
|
70a54b208e | ||
|
|
0b4d63fd09 | ||
|
|
f54285bfe6 | ||
|
|
a94f5c20aa | ||
|
|
adf1cc7ca6 | ||
|
|
d32826dc36 | ||
|
|
3c1c5b6292 | ||
|
|
73a11e1ac8 | ||
|
|
88e29f74de | ||
|
|
59702e15cf | ||
|
|
6c8d306d38 | ||
| f172707b15 | |||
|
|
672221f471 | ||
|
|
73581fd8f0 | ||
|
|
421c1e155b | ||
|
|
be9be7a4c5 | ||
|
|
db988e9761 | ||
|
|
e1706274fd | ||
|
|
96eda0dae7 | ||
|
|
33c00f0d7c | ||
|
|
001f465153 | ||
|
|
61532d5149 | ||
|
|
e1ccf848cf | ||
|
|
091ecdc10f | ||
|
|
e9084fe9ca | ||
|
|
f1074d7b24 | ||
|
|
16151dffdb | ||
|
|
34181aa0c9 | ||
|
|
b62f49b362 | ||
|
|
e985d6e104 | ||
|
|
5aaae9ca99 | ||
|
|
875498d07b | ||
|
|
02daab7686 | ||
|
|
821d594292 | ||
|
|
b4c1cb2a9f | ||
|
|
daa85b2ab3 | ||
|
|
c9d5d469c8 | ||
|
|
bb788d1de3 | ||
|
|
f085f17fe8 | ||
|
|
37316dd1c8 | ||
|
|
297a49a8f6 | ||
|
|
eb12e2271d | ||
|
|
bf0290df38 | ||
|
|
4c839eb867 | ||
|
|
98aeb1646d | ||
|
|
c6357aa6a6 | ||
|
|
5de3cc2ba1 | ||
|
|
2e54f153ed | ||
|
|
9334a35d3b | ||
|
|
f91ce5ad84 | ||
|
|
af57fdfb9f | ||
|
|
81b8bd9ec5 | ||
|
|
8705f7336b | ||
|
|
71b8fc9d0f | ||
|
|
66fefbe907 | ||
|
|
9ff8fe8399 | ||
|
|
d49a2744d2 | ||
|
|
9cadcf2eed | ||
|
|
66ab57fce0 | ||
|
|
84b2315aa5 | ||
|
|
f5161b237a | ||
|
|
aee0a4b34b | ||
|
|
75d97dd9ff | ||
|
|
2c4cc7c6b7 | ||
|
|
585689db43 | ||
|
|
140b9b5e32 | ||
|
|
f3cac97463 | ||
|
|
53a64aaf52 | ||
|
|
babe314199 | ||
|
|
778a7c93b3 | ||
|
|
2e3d8e6e7d | ||
|
|
0eed44ef6d | ||
|
|
76f0e8f176 | ||
|
|
3cad7ae079 | ||
|
|
c482cf1106 | ||
|
|
ca69b2294f | ||
|
|
5e4d16297e | ||
|
|
c0dbceefb9 | ||
|
|
c75f1e9131 | ||
|
|
b615cfe2e9 | ||
|
|
e2433d7367 | ||
|
|
ca448410f0 | ||
|
|
f47678cd12 | ||
|
|
31aba7d0a5 | ||
|
|
3f3641bf3d | ||
|
|
2eb2e902b2 | ||
|
|
c71c3b8ed2 | ||
|
|
108bb31e8e | ||
|
|
34b6399d24 | ||
|
|
1c1dc71cd7 | ||
|
|
6dc81d0cbf | ||
|
|
2a77d233f9 | ||
|
|
0e93ea159f | ||
|
|
582561ae12 | ||
|
|
c2766e82af | ||
|
|
b42d9eff71 | ||
|
|
5ae2d51961 | ||
|
|
ed2ec3a875 | ||
|
|
66281a5fd2 | ||
|
|
6068832fe6 | ||
|
|
c9588fbb95 | ||
|
|
627636ab9a | ||
|
|
63173a6262 | ||
|
|
65bdf1124d | ||
|
|
b3f9b50be5 | ||
|
|
97560f1bc9 | ||
|
|
840f3c9120 | ||
|
|
2b5614a07b | ||
|
|
9582ca5392 | ||
|
|
1b125aecd0 | ||
|
|
35733e1044 | ||
|
|
b748aa86a0 | ||
|
|
57c5926dac | ||
|
|
b77f2a3c45 | ||
|
|
8177cfdfdd | ||
|
|
2a4b734b7f | ||
|
|
f90324ca49 | ||
|
|
9f1c57ddf2 | ||
|
|
ee486f52bb | ||
|
|
6b6cf3eee1 | ||
|
|
52fc211dbf | ||
|
|
d9e415870c | ||
|
|
d61dfda3d5 | ||
|
|
2cfbc6d854 | ||
|
|
bf8b3d226a | ||
|
|
843304def7 | ||
|
|
41105e3f5a | ||
|
|
1fecd14b02 | ||
|
|
76c0cd98d8 | ||
|
|
ef22231dd7 | ||
|
|
8677ca747a | ||
|
|
02b5dd32a2 | ||
|
|
ee48ca08bd | ||
|
|
e72d1b5d93 | ||
|
|
5d6e7e35d5 | ||
|
|
751b4f9f69 | ||
|
|
ec23a7fe14 | ||
|
|
117912045c | ||
|
|
5ebb66d7d4 | ||
|
|
7a7b9cc01b | ||
|
|
4a00394402 | ||
|
|
aa0d09d3c9 | ||
|
|
0a40f7712a | ||
|
|
02debc8387 | ||
|
|
e6d386d362 | ||
|
|
208aaf3f27 | ||
|
|
6c9d4ccc86 | ||
|
|
1f0def655c | ||
|
|
c5e8fff07d | ||
|
|
7295254fe9 | ||
|
|
efbbfde6f5 | ||
|
|
fc4096d5d9 | ||
|
|
f58006cf8a | ||
|
|
6567bb1348 | ||
|
|
b71ca02d25 | ||
| 44b17502a0 | |||
|
|
bf70c50b80 | ||
|
|
d50fbb5f73 | ||
|
|
30fb21e062 | ||
|
|
6b44792e06 | ||
|
|
c7ac858ec5 | ||
|
|
73cb9010e2 | ||
|
|
3c1b5d5072 | ||
|
|
a8873d9435 | ||
|
|
d2c60d8157 | ||
|
|
bb96cf2406 | ||
|
|
c4911b9d5f | ||
|
|
67b840c40f | ||
|
|
e7276cadf6 | ||
|
|
36ca3ed90e | ||
|
|
57a079a86f | ||
|
|
0691806032 | ||
|
|
a6167bf31c | ||
|
|
e79ae984a3 | ||
|
|
81471cc582 | ||
|
|
6e1f6c23fe | ||
|
|
93c698c2de | ||
|
|
92855d5d31 | ||
|
|
6c6d6325c9 | ||
|
|
83f8b3543c | ||
|
|
d6ae29f16f | ||
|
|
02085e7ff1 | ||
|
|
68f6ced410 | ||
|
|
3fda24b5ac | ||
|
|
baa831d002 | ||
|
|
9ebb187a85 | ||
|
|
c50bcd4120 | ||
|
|
72d314b1e2 | ||
|
|
d15762b199 | ||
|
|
f66c0726b0 | ||
|
|
b3090b49e2 | ||
|
|
3bbd0d4432 | ||
|
|
281bb7cb55 | ||
|
|
46ea1e681a | ||
|
|
c759baed06 | ||
|
|
d19191bb14 | ||
|
|
81e78a6809 | ||
|
|
5749de77a9 | ||
|
|
921f186665 | ||
|
|
b098c2ad36 | ||
|
|
2ea82a643d | ||
|
|
cfaf900db6 | ||
|
|
7b44863814 | ||
|
|
d3274d8a59 | ||
|
|
b367df3f4e | ||
|
|
ac84ea8a7a | ||
|
|
e0ee270075 | ||
|
|
76134f4533 | ||
|
|
36010a4230 | ||
|
|
c90bd0cd07 | ||
|
|
6c9a010c3c | ||
|
|
c680392513 | ||
|
|
a233606e8d | ||
|
|
bc18b0775b | ||
|
|
a96b8ddf86 | ||
|
|
d6e7be7db1 | ||
|
|
999fbbf022 | ||
|
|
f8adf906e3 | ||
|
|
c2bbac4020 | ||
|
|
5ad754f5e9 | ||
|
|
814451041a | ||
|
|
1f9af9618f | ||
|
|
2601629e47 | ||
|
|
09b3fcb825 | ||
|
|
34746e865b | ||
|
|
7e82df3df7 | ||
|
|
1faa099900 | ||
|
|
f1295e17d6 | ||
|
|
fd34e5719d | ||
|
|
87f0941d61 | ||
|
|
7ebe9a9c8d | ||
|
|
c2d0993d9d | ||
|
|
8b6c35ff3c | ||
|
|
b0c812ac7a | ||
|
|
83116ee596 | ||
|
|
929786cb12 | ||
|
|
0364333921 | ||
|
|
9d93ba8e07 | ||
|
|
aacb72b78d | ||
|
|
83f7f3261c | ||
|
|
022f67554b | ||
|
|
2c339a22f4 | ||
|
|
e4c6f9d7fe | ||
|
|
24c1580452 | ||
|
|
b937a85dcc | ||
|
|
db43ca4b10 | ||
|
|
8e3e1ef6cc | ||
|
|
26ecfe79eb | ||
|
|
5dd2876fb5 | ||
|
|
807e964f34 | ||
|
|
8a1714eeb6 | ||
|
|
2623efc997 | ||
|
|
c053da2e30 | ||
|
|
533d6a4170 | ||
|
|
5b3e01820b | ||
| 5cef58ade0 | |||
|
|
981b41f4c2 | ||
|
|
ae8039dba0 | ||
|
|
54f56c3f83 | ||
|
|
ce142bb64a | ||
|
|
fd3f61a0ac | ||
|
|
d0ac22c211 | ||
|
|
caa326d496 | ||
|
|
04ef2a4b8c | ||
|
|
7e35a27b2e | ||
|
|
48108e693a | ||
|
|
8e3d3e4281 | ||
|
|
c7c99b339b | ||
|
|
c8f5547727 | ||
|
|
6f5e592d8c | ||
|
|
5ae3f1a9ef | ||
|
|
1a3b091588 | ||
|
|
5b34456571 | ||
|
|
5918611469 | ||
|
|
f3aafffcaa | ||
|
|
3d213c8769 | ||
|
|
f05972d6ae | ||
|
|
b77dda0e6f | ||
|
|
3c1a956c81 | ||
|
|
5dc1a96f6d |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,10 +1,14 @@
|
|||||||
hosts/nas/*.conf
|
hosts/nas/*.conf
|
||||||
hosts/nas/*.users
|
hosts/nas/*.users
|
||||||
result
|
result*
|
||||||
*.raw
|
*.raw
|
||||||
.codegpt
|
.codegpt
|
||||||
.direnv
|
.direnv
|
||||||
shell.nix
|
shell.nix
|
||||||
.vscode
|
.vscode
|
||||||
**/*/*.py
|
**/*/*.py
|
||||||
.envrc
|
.envrc
|
||||||
|
.DS_Store
|
||||||
|
*.qcow2
|
||||||
|
keys
|
||||||
|
iso-*
|
||||||
138
.sops.yaml
138
.sops.yaml
@@ -1,90 +1,92 @@
|
|||||||
# See https://github.com/Mic92/dotfiles/blob/d6114726d859df36ccaa32891c4963ae5717ef7f/nixos/.sops.yaml
|
# See https://github.com/Mic92/dotfiles/blob/d6114726d859df36ccaa32891c4963ae5717ef7f/nixos/.sops.yaml
|
||||||
keys:
|
keys:
|
||||||
|
- &matt-pgp CBCB9B18A6B8930B0B6ABFD1CCB8CBEB30633684
|
||||||
- &matt age157jemphjzg6zmk373vpccuguyw6e75qnkqmz8pcnn2yue85p939swqqhy0
|
- &matt age157jemphjzg6zmk373vpccuguyw6e75qnkqmz8pcnn2yue85p939swqqhy0
|
||||||
- &matt_pi4 age13g9a4d4jrvckfddpgn8sm4kjtzajr67le56pfdg78ktr5pd09phq32j89u
|
|
||||||
- &matt_pi5 age1wpvfpv5n32lruk7c0da4uaeapsmhjxdvg8z4ljehn06l6g2y0e0sum404l
|
- &matt_pi5 age1wpvfpv5n32lruk7c0da4uaeapsmhjxdvg8z4ljehn06l6g2y0e0sum404l
|
||||||
- &desktop age1jv8ap5zwa49ftv0gg7wqf5ps0e68uuwxe2fekjsn0zkyql964unqyc58rf
|
- &desktop age1jv8ap5zwa49ftv0gg7wqf5ps0e68uuwxe2fekjsn0zkyql964unqyc58rf
|
||||||
- &admin age1pm3fehmmk0vmnrscz9vm96rakn46aaldr5ydpscmde3v9x0k3faswwdzxs
|
- &admin age1pm3fehmmk0vmnrscz9vm96rakn46aaldr5ydpscmde3v9x0k3faswwdzxs
|
||||||
- &jallen-nas age1mn2afyp9my7y7hcyzum0wdwt49zufnkt8swnyy8pj30cwzs4zvgsthj0lt
|
- &jallen-nas age1mn2afyp9my7y7hcyzum0wdwt49zufnkt8swnyy8pj30cwzs4zvgsthj0lt
|
||||||
- &pi4 age1ykkjw57t3z3deup3gtp7dujyaslskn74e0d9hsmqaha2pj3rvazqgndw5a
|
|
||||||
- &pi5 age1t2d5scrukk0guva5sr97a8tge5j8kd865adezrcru7p269pzwvpsamkgje
|
- &pi5 age1t2d5scrukk0guva5sr97a8tge5j8kd865adezrcru7p269pzwvpsamkgje
|
||||||
- &deck age1c8qw59ffcq9l77gfmtyc3djtvt3md0u6dwhrjcgsm98ntyf72ufqugj7cg
|
- &deck age1c8qw59ffcq9l77gfmtyc3djtvt3md0u6dwhrjcgsm98ntyf72ufqugj7cg
|
||||||
- &steamdeck age1er5qucsc2mugrzrr7n3xhzv7kemkrqrw4m84r544fkk7nkg5g5eswxkqj0
|
- &steamdeck age1er5qucsc2mugrzrr7n3xhzv7kemkrqrw4m84r544fkk7nkg5g5eswxkqj0
|
||||||
- &matt_macbook-pro age1xg6mvj3x6s3t8058c6rsk3q4kskvm6nsffwckxkkjzhyn7r6tczqgkj23p
|
- &matt_macbook-pro age12gu9hqhd56yl5x3t5yenkn9yg57du08h77vzjqsmnu5hdppne38qcur5a0
|
||||||
- &macbook-pro age1rdn39ywgzmc8wlsl5lrfe77e652wzjmjx58gx4k2ydghd35kdqvqscrf3h
|
- &macbook-pro age1t7378n8kmd3f32fkye2gw3jj6qswv3exjdx0dq8kl0xra3tmcdnsvddq3u
|
||||||
- &nuc age1wurzgc20e6ye79wsg85vvqk4aj3mmc0llxshcy9532ex8f4c6dqql76c78
|
- &nuc age102el4snus37dj807rwvsmlvwu2sg2d8rw3vfmtntgczfkz04l9nshetcq0
|
||||||
- &admin_nuc age1luyejgmqjj0esydlr2jxqkg48vexmx57gdz7cy5gq7rz8kf5cups2rnfa9
|
- &admin_nuc age1yn82e39pxt0d0pgny34ux4lkge4ff7wxvsye8ragvwngehemt4ps27phyw
|
||||||
|
- &matt_allyx age18z4ctyyj7eq0cmt23eelfzjuacq4fa6hsplyg779d3rdg7ac2q5q2njxqh
|
||||||
|
- &allyx age164xpf9cepfjqvcn7v5ahcaq9zmm5u3yl9t04d098e3e2zkfjcyws02rx42
|
||||||
creation_rules:
|
creation_rules:
|
||||||
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- pgp:
|
||||||
- *matt
|
- *matt-pgp
|
||||||
- *matt_pi4
|
age:
|
||||||
- *matt_pi5
|
- *matt
|
||||||
- *desktop
|
- *matt_pi5
|
||||||
- *admin
|
- *desktop
|
||||||
- *jallen-nas
|
- *admin
|
||||||
- *pi4
|
- *jallen-nas
|
||||||
- *pi5
|
- *pi5
|
||||||
- *deck
|
- *deck
|
||||||
- *steamdeck
|
- *steamdeck
|
||||||
- *matt_macbook-pro
|
- *matt_macbook-pro
|
||||||
- *macbook-pro
|
- *macbook-pro
|
||||||
- *admin_nuc
|
- *admin_nuc
|
||||||
- *nuc
|
- *nuc
|
||||||
|
- *matt_allyx
|
||||||
|
- *allyx
|
||||||
- path_regex: nas-secrets/[^/]+\.(yaml|json|env|ini)$
|
- path_regex: nas-secrets/[^/]+\.(yaml|json|env|ini)$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- pgp:
|
||||||
- *matt
|
- *matt-pgp
|
||||||
- *desktop
|
age:
|
||||||
- *admin
|
- *matt
|
||||||
- *jallen-nas
|
- *desktop
|
||||||
|
- *admin
|
||||||
|
- *jallen-nas
|
||||||
- path_regex: desktop-secrets/[^/]+\.(yaml|json|env|ini)$
|
- path_regex: desktop-secrets/[^/]+\.(yaml|json|env|ini)$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- pgp:
|
||||||
- *matt
|
- *matt-pgp
|
||||||
- *desktop
|
age:
|
||||||
- *admin
|
- *matt
|
||||||
- *jallen-nas
|
- *desktop
|
||||||
- path_regex: steamdeck-secrets/[^/]+\.(yaml|json|env|ini)$
|
- *admin
|
||||||
|
- *jallen-nas
|
||||||
|
- path_regex: allyx-secrets/[^/]+\.(yaml|json|env|ini)$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- pgp:
|
||||||
- *matt
|
- *matt-pgp
|
||||||
- *desktop
|
age:
|
||||||
- *deck
|
- *matt
|
||||||
- *steamdeck
|
- *desktop
|
||||||
- *admin
|
- *deck
|
||||||
- *jallen-nas
|
- *steamdeck
|
||||||
- path_regex: pi4-secrets/[^/]+\.(yaml|json|env|ini)$
|
- *admin
|
||||||
key_groups:
|
- *jallen-nas
|
||||||
- age:
|
- *matt_allyx
|
||||||
- *matt
|
- *allyx
|
||||||
- *matt_pi4
|
|
||||||
- *matt_pi5
|
|
||||||
- *desktop
|
|
||||||
- *pi4
|
|
||||||
- *pi5
|
|
||||||
- *admin
|
|
||||||
- *jallen-nas
|
|
||||||
- path_regex: pi5-secrets/[^/]+\.(yaml|json|env|ini)$
|
- path_regex: pi5-secrets/[^/]+\.(yaml|json|env|ini)$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- pgp:
|
||||||
- *matt
|
- *matt-pgp
|
||||||
- *matt_pi4
|
age:
|
||||||
- *matt_pi5
|
- *matt
|
||||||
- *desktop
|
- *matt_pi5
|
||||||
- *pi4
|
- *desktop
|
||||||
- *pi5
|
- *pi5
|
||||||
- *admin
|
- *admin
|
||||||
- *jallen-nas
|
- *jallen-nas
|
||||||
- path_regex: mac-secrets/[^/]+\.(yaml|json|env|ini)$
|
- path_regex: mac-secrets/[^/]+\.(yaml|json|env|ini)$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- pgp:
|
||||||
- *matt
|
- *matt-pgp
|
||||||
- *matt_pi5
|
age:
|
||||||
- *desktop
|
- *matt
|
||||||
- *pi5
|
- *matt_pi5
|
||||||
- *admin
|
- *desktop
|
||||||
- *jallen-nas
|
- *pi5
|
||||||
- *matt_macbook-pro
|
- *admin
|
||||||
- *macbook-pro
|
- *jallen-nas
|
||||||
|
- *matt_macbook-pro
|
||||||
|
- *macbook-pro
|
||||||
|
|||||||
167
README.md
167
README.md
@@ -1,50 +1,129 @@
|
|||||||
# nixOS Config
|
# NixOS Configuration Repository
|
||||||
|
|
||||||
### Common Files
|
This repository contains my personal NixOS configurations for multiple systems, managed using [Snowfall Lib](https://github.com/snowfallorg/lib) and the Nix Flakes system.
|
||||||
* [flake.nix](./flake.nix)
|
|
||||||
* [impermenance.nix](./share/impermanence/default.nix)
|
## Overview
|
||||||
* [share](./share)
|
|
||||||
* [overlays](./overlays)
|
This repository provides a centralized, declarative configuration for all my systems, including:
|
||||||
|
|
||||||
|
- Desktop PC (AMD)
|
||||||
|
- NAS server
|
||||||
|
- Steam Deck
|
||||||
|
- Intel NUC
|
||||||
|
- Raspberry Pi 4
|
||||||
|
- Raspberry Pi 5
|
||||||
|
- MacBook Pro (NixOS on Apple Silicon)
|
||||||
|
- MacBook Pro (Darwin/macOS)
|
||||||
|
|
||||||
|
## Repository Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── checks/ # Pre-commit hooks and other checks
|
||||||
|
├── flake.nix # Main flake configuration
|
||||||
|
├── homes/ # Home-manager configurations for users
|
||||||
|
│ ├── aarch64-darwin/ # macOS home configurations
|
||||||
|
│ ├── aarch64-linux/ # ARM Linux home configurations
|
||||||
|
│ └── x86_64-linux/ # x86 Linux home configurations
|
||||||
|
├── modules/ # Reusable configuration modules
|
||||||
|
│ ├── home/ # Home-manager modules
|
||||||
|
│ └── nixos/ # NixOS system modules
|
||||||
|
├── overlays/ # Nixpkgs overlays
|
||||||
|
├── packages/ # Custom package definitions
|
||||||
|
├── secrets/ # Encrypted secrets (managed with sops-nix)
|
||||||
|
└── systems/ # System-specific configurations
|
||||||
|
├── aarch64-darwin/ # macOS system configurations
|
||||||
|
├── aarch64-linux/ # ARM Linux system configurations
|
||||||
|
└── x86_64-linux/ # x86 Linux system configurations
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
- **Modular Design**: Reusable modules for various system components
|
||||||
|
- **Multi-System Support**: Configurations for different hardware platforms
|
||||||
|
- **Home Manager Integration**: User environment management
|
||||||
|
- **Secret Management**: Encrypted secrets with sops-nix
|
||||||
|
- **Disk Management**: Declarative disk partitioning with disko
|
||||||
|
- **State Management**: Persistent state management with impermanence
|
||||||
|
- **Desktop Environments**: Support for GNOME, Hyprland, and COSMIC
|
||||||
|
- **Hardware-Specific Optimizations**: Tailored configurations for different hardware
|
||||||
|
|
||||||
|
## Key Technologies
|
||||||
|
|
||||||
|
- [Nix](https://nixos.org/) and [NixOS](https://nixos.org/)
|
||||||
|
- [Nix Flakes](https://nixos.wiki/wiki/Flakes)
|
||||||
|
- [Snowfall Lib](https://github.com/snowfallorg/lib)
|
||||||
|
- [Home Manager](https://github.com/nix-community/home-manager)
|
||||||
|
- [sops-nix](https://github.com/Mic92/sops-nix)
|
||||||
|
- [disko](https://github.com/nix-community/disko)
|
||||||
|
- [impermanence](https://github.com/nix-community/impermanence)
|
||||||
|
- [lanzaboote](https://github.com/nix-community/lanzaboote) (Secure Boot)
|
||||||
|
|
||||||
|
## Notable System Configurations
|
||||||
|
|
||||||
### Desktop
|
### Desktop
|
||||||
* [boot.nix](./hosts/desktop/boot.nix)
|
|
||||||
* [configuration.nix](./hosts/desktop/configuration.nix)
|
A powerful AMD-based desktop with gaming capabilities, featuring:
|
||||||
* [hardware-configuration.nix](./hosts/desktop/hardware-configuration.nix)
|
- AMD CPU and GPU optimizations
|
||||||
* [filesystems.nix](./hosts/desktop/filesystems.nix)
|
- Multiple desktop environment options (GNOME, Hyprland, COSMIC)
|
||||||
* [home.nix](./hosts/desktop/home.nix)
|
- Gaming setup with Steam and related tools
|
||||||
* [sops.nix](./hosts/desktop/sops.nix)
|
|
||||||
* [specialisations.hyprland](./hosts/desktop/hyprland)
|
|
||||||
* [specialisations.gnome](./hosts/desktop/gnome)
|
|
||||||
* [specialisations.cosmic](./hosts/desktop/cosmic)
|
|
||||||
|
|
||||||
### NAS
|
### NAS
|
||||||
* [boot.nix](./hosts/nas/boot.nix)
|
|
||||||
* [configuration.nix](./hosts/nas/configuration.nix)
|
|
||||||
* [hardware-configuration.nix](./hosts/nas/hardware-configuration.nix)
|
|
||||||
* [impermenance.nix](./hosts/nas/impermenance.nix)
|
|
||||||
* [apps.nix](./hosts/desktop/apps.nix)
|
|
||||||
* [home.nix](./hosts/desktop/home.nix)
|
|
||||||
* [networking.nix](./hosts/desktop/networking.nix)
|
|
||||||
* [services.nix](./hosts/desktop/services.nix)
|
|
||||||
* [sops.nix](./hosts/desktop/sops.nix)
|
|
||||||
* [ups.nix](./hosts/desktop/ups.nix)
|
|
||||||
* [samba](./modules/samba)
|
|
||||||
* nas-apps
|
|
||||||
* [arrs](./hosts/nas/apps/arrs/default.nix)
|
|
||||||
* [free-games-claimer](./modules/apps/free-games-claimer)
|
|
||||||
* [jackett](./modules/apps/jackett)
|
|
||||||
* [jellyfin](./hosts/nas/apps/jellyfin/default.nix)
|
|
||||||
* [jellyseerr](./hosts/nas/apps/jellyseerr/default.nix)
|
|
||||||
* [jackett](./modules/apps/manyfold)
|
|
||||||
* [mariadb](./modules/apps/mariadb)
|
|
||||||
* [mealie](./modules/apps/mealie)
|
|
||||||
* [nextcloud+onlyoffice](./hosts/nas/apps/nextcloud/default.nix)
|
|
||||||
* [ollama](./hosts/nas/apps/ollama/default.nix)
|
|
||||||
* [paperless](./hosts/nas/apps/paperless/default.nix)
|
|
||||||
* [tdarr](./modules/apps/tdarr)
|
|
||||||
* [traefik](./hosts/nas/apps/traefik/default.nix)
|
|
||||||
* [wireguard](./modules/apps/your-spotify)
|
|
||||||
|
|
||||||
### Raspberry Pi 4
|
A home server with various self-hosted services:
|
||||||
* [configuration.nix](./hosts/pi4/configuration.nix)
|
- Media management (Jellyfin, Jellyseerr)
|
||||||
* [hardware-configuration.nix](./hosts/pi4/hardware-configuration.nix)
|
- Download automation (Sonarr, Radarr, etc.)
|
||||||
|
- Document management (Paperless)
|
||||||
|
- File sharing (Samba, Nextcloud)
|
||||||
|
- AI services (Ollama)
|
||||||
|
|
||||||
|
### Raspberry Pi
|
||||||
|
|
||||||
|
Configurations for both Pi 4 and Pi 5:
|
||||||
|
- Hardware-specific optimizations
|
||||||
|
- Disk partitioning suitable for ARM devices
|
||||||
|
- Bluetooth and wireless support
|
||||||
|
|
||||||
|
### Steam Deck
|
||||||
|
|
||||||
|
Custom NixOS configuration for the Steam Deck:
|
||||||
|
- Integration with Jovian for Steam Deck compatibility
|
||||||
|
- Gaming optimizations
|
||||||
|
- Steam ROM Manager
|
||||||
|
|
||||||
|
### MacBook Pro
|
||||||
|
|
||||||
|
Configurations for both:
|
||||||
|
- NixOS on Apple Silicon
|
||||||
|
- nix-darwin for macOS
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Building a System Configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build and activate a system configuration
|
||||||
|
sudo nixos-rebuild switch --flake .#hostname
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building a Home Configuration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build and activate a home configuration
|
||||||
|
home-manager switch --flake .#username@hostname
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Comprehensive documentation is available in the [docs](./docs) directory:
|
||||||
|
|
||||||
|
- [Getting Started](./docs/getting-started.md) - Instructions for setting up new systems
|
||||||
|
- [Architecture](./docs/architecture.md) - Overview of the repository structure
|
||||||
|
- [System Configurations](./docs/systems/README.md) - Details about each system
|
||||||
|
- [Home Assistant](./docs/home-assistant/README.md) - Home Assistant setup and automations
|
||||||
|
- [Custom Modules](./docs/modules/README.md) - Details about reusable configuration modules
|
||||||
|
- [Troubleshooting](./docs/troubleshooting.md) - Common issues and solutions
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License - see the LICENSE file for details.
|
||||||
|
|||||||
62
checks/disksnstuff.sh
Executable file
62
checks/disksnstuff.sh
Executable file
@@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
disk=/dev/mapper/nuc-nixos-cryptroot
|
||||||
|
|
||||||
|
# sudo mkfs.vfat "$disk"1
|
||||||
|
# sudo bcachefs format --label ssd.ssd1 --compression=zstd --discard "$disk"
|
||||||
|
|
||||||
|
sudo mount -t tmpfs -o mode=755 none /mnt
|
||||||
|
sudo mkdir -p /mnt/{boot,home,root,etc,nix,var/log,tmp,persist}
|
||||||
|
sudo mount /dev/disk/by-partlabel/disk-main-nuc-nixos-EFI /mnt/boot
|
||||||
|
# sudo mkdir -p /mnt/boot/firmware
|
||||||
|
# sudo mount "$disk"2 /mnt/boot/firmware
|
||||||
|
# sudo mount "$disk"2 -o compress=zstd,subvol=home /mnt/home
|
||||||
|
# sudo mount "$disk"2 -o compress=zstd,noatime,subvol=root /mnt/root
|
||||||
|
# sudo mount "$disk"2 -o compress=zstd,noatime,subvol=etc /mnt/etc
|
||||||
|
# sudo mount "$disk"2 -o compress=zstd,noatime,subvol=nix /mnt/nix
|
||||||
|
# sudo mount "$disk"2 -o compress=zstd,noatime,subvol=log /mnt/var/log
|
||||||
|
|
||||||
|
# bcachefs unlock -k session /dev/disk/by-partlabel/disk-main-nuc-nixos-bcachefs-root
|
||||||
|
sudo cryptsetup open /dev/disk/by-partlabel/disk-main-nuc-nixos-cryptroot nuc-nixos-cryptroot
|
||||||
|
# sudo bcachefs unlock -k session "$disk"2
|
||||||
|
# sudo mount "$disk" /mnt/tmp
|
||||||
|
# cd /mnt/tmp
|
||||||
|
# ls -alh
|
||||||
|
|
||||||
|
# sudo bcachefs subvolume create nix
|
||||||
|
# sudo bcachefs subvolume create etc
|
||||||
|
# sudo bcachefs subvolume create log
|
||||||
|
# sudo bcachefs subvolume create root
|
||||||
|
# sudo bcachefs subvolume create persist
|
||||||
|
# sudo bcachefs subvolume create home
|
||||||
|
|
||||||
|
# ls -alh
|
||||||
|
# cd /etc/nixos
|
||||||
|
# sudo umount /mnt/tmp
|
||||||
|
|
||||||
|
sudo mount -o noatime,X-mount.subdir=nix "$disk" /mnt/nix
|
||||||
|
sudo mount -o noatime,X-mount.subdir=etc "$disk" /mnt/etc
|
||||||
|
sudo mount -o noatime,X-mount.subdir=log "$disk" /mnt/var/log
|
||||||
|
sudo mount -o noatime,X-mount.subdir=root "$disk" /mnt/root
|
||||||
|
sudo mount -o noatime,X-mount.subdir=persist "$disk" /mnt/persist
|
||||||
|
sudo mount -o X-mount.subdir=home "$disk" /mnt/home
|
||||||
|
|
||||||
|
# tree /mnt
|
||||||
|
|
||||||
|
# sudo nixos-install --flake /etc/nixos#nuc-nixos
|
||||||
|
|
||||||
|
# sudo umount /mnt/boot
|
||||||
|
# sudo umount /mnt/var/log
|
||||||
|
# sudo umount /mnt/persist
|
||||||
|
# sudo umount /mnt/home
|
||||||
|
# sudo umount /mnt/root
|
||||||
|
# sudo umount /mnt/etc
|
||||||
|
# sudo umount /mnt/nix
|
||||||
|
# sudo umount /mnt
|
||||||
|
|
||||||
|
# wpa_passphrase "Joey's Jungle 5G" "kR8v&3Qd" > 5g.conf
|
||||||
|
# wpa_supplicant -i wlp6s0 -c 5g.conf -B
|
||||||
|
# dhcpcd
|
||||||
|
|
||||||
|
# keyctl link @u @s
|
||||||
|
# clevis decrypt < "/etc/clevis/nas_pool.jwe" | bcachefs unlock /dev/disk/by-label/nas_pool
|
||||||
@@ -1,19 +1,22 @@
|
|||||||
{
|
{
|
||||||
inputs,
|
inputs,
|
||||||
pkgs,
|
pkgs,
|
||||||
|
lib,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
inherit (inputs) git-hooks-nix;
|
inherit (inputs) pre-commit-hooks-nix;
|
||||||
in
|
in
|
||||||
git-hooks-nix.lib.${pkgs.system}.run {
|
pre-commit-hooks-nix.lib.${pkgs.stdenv.hostPlatform.system}.run {
|
||||||
src = ../..;
|
src = ../..;
|
||||||
hooks = {
|
hooks = {
|
||||||
pre-commit-hook-ensure-sops.enable = true;
|
pre-commit-hook-ensure-sops.enable = true;
|
||||||
treefmt = {
|
treefmt = {
|
||||||
enable = true;
|
enable = lib.mkForce true;
|
||||||
settings.fail-on-change = false;
|
settings.fail-on-change = lib.mkForce false;
|
||||||
packageOverrides.treefmt = inputs.treefmt-nix.lib.mkWrapper pkgs ../../treefmt.nix;
|
packageOverrides.treefmt = inputs.treefmt-nix.lib.mkWrapper pkgs (
|
||||||
|
lib.snowfall.fs.get-file "treefmt.nix"
|
||||||
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
12
docs/README.md
Normal file
12
docs/README.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Documentation
|
||||||
|
|
||||||
|
This directory contains comprehensive documentation for the NixOS configuration.
|
||||||
|
|
||||||
|
## Contents
|
||||||
|
|
||||||
|
- [Getting Started](./getting-started.md) - Instructions for setting up new systems
|
||||||
|
- [System Configurations](./systems/README.md) - Detailed information about each system
|
||||||
|
- [Home Assistant](./home-assistant/README.md) - Documentation for the Home Assistant setup
|
||||||
|
- [Custom Modules](./modules/README.md) - Information about reusable modules
|
||||||
|
- [Architecture](./architecture.md) - Overview of the repository architecture
|
||||||
|
- [Troubleshooting](./troubleshooting.md) - Common issues and solutions
|
||||||
104
docs/architecture.md
Normal file
104
docs/architecture.md
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# Repository Architecture
|
||||||
|
|
||||||
|
This document provides an overview of the repository architecture, explaining how the various components fit together.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This NixOS configuration repository is built using [Nix Flakes](https://nixos.wiki/wiki/Flakes) and [Snowfall Lib](https://github.com/snowfallorg/lib) to provide a modular, maintainable configuration for multiple systems.
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── checks/ # Pre-commit hooks and other checks
|
||||||
|
├── flake.nix # Main flake configuration
|
||||||
|
├── homes/ # Home-manager configurations for users
|
||||||
|
│ ├── aarch64-darwin/ # macOS home configurations
|
||||||
|
│ ├── aarch64-linux/ # ARM Linux home configurations
|
||||||
|
│ └── x86_64-linux/ # x86 Linux home configurations
|
||||||
|
├── modules/ # Reusable configuration modules
|
||||||
|
│ ├── home/ # Home-manager modules
|
||||||
|
│ └── nixos/ # NixOS system modules
|
||||||
|
│ ├── boot/ # Boot configuration modules
|
||||||
|
│ ├── desktop/ # Desktop environment modules
|
||||||
|
│ ├── hardware/ # Hardware-specific modules
|
||||||
|
│ ├── homeassistant/ # Home Assistant modules
|
||||||
|
│ ├── network/ # Network configuration modules
|
||||||
|
│ ├── services/ # Service configuration modules
|
||||||
|
│ └── ... # Other module categories
|
||||||
|
├── overlays/ # Nixpkgs overlays
|
||||||
|
├── packages/ # Custom package definitions
|
||||||
|
├── secrets/ # Encrypted secrets (managed with sops-nix)
|
||||||
|
└── systems/ # System-specific configurations
|
||||||
|
├── aarch64-darwin/ # macOS system configurations
|
||||||
|
├── aarch64-linux/ # ARM Linux system configurations
|
||||||
|
└── x86_64-linux/ # x86 Linux system configurations
|
||||||
|
├── jallen-nas/ # NAS server configuration
|
||||||
|
├── matt-nixos/ # Desktop configuration
|
||||||
|
├── nuc-nixos/ # NUC configuration
|
||||||
|
└── ... # Other system configurations
|
||||||
|
```
|
||||||
|
|
||||||
|
## Flake Structure
|
||||||
|
|
||||||
|
The `flake.nix` file defines the inputs (external dependencies) and outputs (configurations) of this repository:
|
||||||
|
|
||||||
|
### Inputs
|
||||||
|
|
||||||
|
- **nixpkgs-unstable**: The unstable channel of Nixpkgs
|
||||||
|
- **nixpkgs-stable**: The stable channel of Nixpkgs (25.11)
|
||||||
|
- **home-manager**: User environment management
|
||||||
|
- **snowfall-lib**: Library for structuring flake repositories
|
||||||
|
- **impermanence**: Persistent state management
|
||||||
|
- **lanzaboote**: Secure boot implementation
|
||||||
|
- **nixos-hardware**: Hardware-specific configurations
|
||||||
|
- **sops-nix**: Secret management
|
||||||
|
- **disko**: Disk partitioning and formatting
|
||||||
|
- **And more specialized inputs**
|
||||||
|
|
||||||
|
### Outputs
|
||||||
|
|
||||||
|
The outputs are generated using Snowfall Lib's `mkFlake` function, which automatically discovers and assembles:
|
||||||
|
|
||||||
|
- **NixOS system configurations**: For each system in the `systems/` directory
|
||||||
|
- **Home Manager configurations**: For each configuration in the `homes/` directory
|
||||||
|
- **Packages**: From the `packages/` directory
|
||||||
|
- **Modules**: From the `modules/` directory
|
||||||
|
- **Overlays**: From the `overlays/` directory
|
||||||
|
|
||||||
|
## Module System
|
||||||
|
|
||||||
|
The module system uses a modular approach where:
|
||||||
|
|
||||||
|
1. **Common modules** are defined in `modules/nixos/` and `modules/home/`
|
||||||
|
2. **System-specific modules** are defined in `systems/<architecture>/<hostname>/`
|
||||||
|
|
||||||
|
Each module follows the NixOS module pattern, with:
|
||||||
|
- `default.nix`: Main module implementation
|
||||||
|
- `options.nix`: Option declarations
|
||||||
|
|
||||||
|
## Integration with Snowfall Lib
|
||||||
|
|
||||||
|
Snowfall Lib provides:
|
||||||
|
1. **Automatic discovery** of modules, overlays, and packages
|
||||||
|
2. **Consistent structure** across the repository
|
||||||
|
3. **Common utilities** for working with flakes
|
||||||
|
|
||||||
|
## Secrets Management
|
||||||
|
|
||||||
|
Secrets are managed using [sops-nix](https://github.com/Mic92/sops-nix), with:
|
||||||
|
- Encrypted secret files in the `secrets/` directory
|
||||||
|
- `.sops.yaml` configuration file in the root
|
||||||
|
- Key management integrated into the configuration
|
||||||
|
|
||||||
|
## Deployment Process
|
||||||
|
|
||||||
|
Systems are built and deployed using:
|
||||||
|
```bash
|
||||||
|
nixos-rebuild switch --flake .#hostname
|
||||||
|
```
|
||||||
|
|
||||||
|
This command:
|
||||||
|
1. Evaluates the flake for the specified hostname
|
||||||
|
2. Builds the resulting configuration
|
||||||
|
3. Activates it on the current system
|
||||||
172
docs/getting-started.md
Normal file
172
docs/getting-started.md
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
# Getting Started
|
||||||
|
|
||||||
|
This guide will help you get started with this NixOS configuration repository.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Basic knowledge of NixOS and the Nix language
|
||||||
|
- Git installed on your system
|
||||||
|
- Physical access to the machine you want to configure
|
||||||
|
|
||||||
|
## Initial Setup
|
||||||
|
|
||||||
|
### 1. Cloning the Repository
|
||||||
|
|
||||||
|
Clone this repository to your local machine:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone ssh://nix-apps@localhost:2222/mjallen/nix-config.git
|
||||||
|
cd nix-config
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Setting Up a New System
|
||||||
|
|
||||||
|
#### Option 1: Using an Existing Configuration
|
||||||
|
|
||||||
|
If you're setting up a new machine that should be identical to an existing configuration:
|
||||||
|
|
||||||
|
1. Boot from a NixOS installation media
|
||||||
|
2. Mount your target partitions to `/mnt`
|
||||||
|
3. Clone this repository:
|
||||||
|
```bash
|
||||||
|
nixos-enter
|
||||||
|
cd /mnt
|
||||||
|
mkdir -p /mnt/etc/nixos
|
||||||
|
git clone ssh://nix-apps@localhost:2222/mjallen/nix-config.git /mnt/etc/nixos
|
||||||
|
```
|
||||||
|
4. Install NixOS with the desired system profile:
|
||||||
|
```bash
|
||||||
|
nixos-install --flake /mnt/etc/nixos#hostname
|
||||||
|
```
|
||||||
|
Replace `hostname` with the target system name (e.g., `matt-nixos`, `jallen-nas`, etc.)
|
||||||
|
|
||||||
|
#### Option 2: Creating a New System Configuration
|
||||||
|
|
||||||
|
If you're adding a completely new system:
|
||||||
|
|
||||||
|
1. Create a new directory for your system configuration:
|
||||||
|
```bash
|
||||||
|
mkdir -p systems/$(uname -m)-linux/new-hostname
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Create the basic configuration files:
|
||||||
|
```bash
|
||||||
|
cat > systems/$(uname -m)-linux/new-hostname/default.nix << EOF
|
||||||
|
{ lib, pkgs, ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./hardware-configuration.nix
|
||||||
|
# Add other needed module imports here
|
||||||
|
];
|
||||||
|
|
||||||
|
networking.hostName = "new-hostname";
|
||||||
|
|
||||||
|
# Add your system-specific configuration here
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Generate the hardware configuration:
|
||||||
|
```bash
|
||||||
|
nixos-generate-config --no-filesystems --dir systems/$(uname -m)-linux/new-hostname/
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Add your new system to the flake by adding it to the `hosts` section in `flake.nix`
|
||||||
|
|
||||||
|
5. Build and install the configuration:
|
||||||
|
```bash
|
||||||
|
sudo nixos-rebuild switch --flake .#new-hostname
|
||||||
|
```
|
||||||
|
|
||||||
|
## Secret Management
|
||||||
|
|
||||||
|
### Setting Up Sops-Nix
|
||||||
|
|
||||||
|
1. Create a GPG key if you don't already have one:
|
||||||
|
```bash
|
||||||
|
gpg --full-generate-key
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Add your key to `.sops.yaml`:
|
||||||
|
```bash
|
||||||
|
# Get your key fingerprint
|
||||||
|
gpg --list-secret-keys --keyid-format=long
|
||||||
|
|
||||||
|
# Edit the .sops.yaml file to add your key
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Create a new encrypted secret:
|
||||||
|
```bash
|
||||||
|
sops secrets/newsecret.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Tasks
|
||||||
|
|
||||||
|
### Updating the Repository
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git pull
|
||||||
|
sudo nixos-rebuild switch --flake .#hostname
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding a New Package
|
||||||
|
|
||||||
|
1. For standard packages, add them to your system or home configuration:
|
||||||
|
```nix
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
new-package
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
2. For custom packages, add them to the `packages` directory:
|
||||||
|
```bash
|
||||||
|
mkdir -p packages/new-package
|
||||||
|
# Create the necessary Nix files
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding a New Module
|
||||||
|
|
||||||
|
1. Create a new module directory:
|
||||||
|
```bash
|
||||||
|
mkdir -p modules/nixos/new-module
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Create the module files:
|
||||||
|
```bash
|
||||||
|
# Create options.nix
|
||||||
|
cat > modules/nixos/new-module/options.nix << EOF
|
||||||
|
{ lib, namespace, ... }:
|
||||||
|
with lib;
|
||||||
|
{
|
||||||
|
options.${namespace}.new-module = {
|
||||||
|
enable = mkEnableOption "Enable new module";
|
||||||
|
# Add other options here
|
||||||
|
};
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create default.nix
|
||||||
|
cat > modules/nixos/new-module/default.nix << EOF
|
||||||
|
{ config, lib, namespace, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.${namespace}.new-module;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [ ./options.nix ];
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
# Add your configuration here
|
||||||
|
};
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Import your module in your system configuration:
|
||||||
|
```nix
|
||||||
|
imports = [
|
||||||
|
# ...
|
||||||
|
../../../modules/nixos/new-module
|
||||||
|
];
|
||||||
|
|
||||||
|
${namespace}.new-module.enable = true;
|
||||||
|
```
|
||||||
188
docs/home-assistant/README.md
Normal file
188
docs/home-assistant/README.md
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
# Home Assistant Configuration
|
||||||
|
|
||||||
|
This document provides comprehensive information about the Home Assistant setup in this NixOS configuration.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Home Assistant is configured as a NixOS service with custom components, integrations, and automations. The configuration uses a modular approach with separate files for different aspects of the setup.
|
||||||
|
|
||||||
|
## Module Structure
|
||||||
|
|
||||||
|
The Home Assistant configuration is organized in the following structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
modules/nixos/homeassistant/
|
||||||
|
├── automations/ # Automation configurations
|
||||||
|
│ ├── lightswitch/ # Light switch automations
|
||||||
|
│ └── motion-light/ # Motion-activated light automations
|
||||||
|
├── default.nix # Main module configuration
|
||||||
|
├── options.nix # Module options definition
|
||||||
|
└── services/ # Related service configurations
|
||||||
|
├── govee2mqtt/ # Govee integration via MQTT
|
||||||
|
├── homeassistant/ # Core Home Assistant service
|
||||||
|
├── music-assistant/ # Music Assistant integration
|
||||||
|
├── thread/ # Thread border router
|
||||||
|
└── zigbee2mqtt/ # Zigbee to MQTT bridge
|
||||||
|
```
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
The Home Assistant module is enabled in the system configuration by setting:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
mjallen.services.home-assistant.enable = true;
|
||||||
|
```
|
||||||
|
|
||||||
|
This activates Home Assistant and related services such as MQTT, Zigbee2MQTT, and the Matter server.
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
The module provides several configuration options:
|
||||||
|
|
||||||
|
| Option | Type | Default | Description |
|
||||||
|
|--------|------|---------|-------------|
|
||||||
|
| `enable` | boolean | `false` | Enable Home Assistant and related services |
|
||||||
|
| `mosquittoPort` | integer | `1883` | Port for the MQTT broker |
|
||||||
|
| `zigbee2mqttPort` | integer | `8080` | Port for the Zigbee2MQTT web interface |
|
||||||
|
| `zigbeeDevicePath` | string | `/dev/ttyUSB0` | Path to the Zigbee USB device |
|
||||||
|
|
||||||
|
## Core Services
|
||||||
|
|
||||||
|
### Home Assistant
|
||||||
|
|
||||||
|
The main Home Assistant service is configured in `services/homeassistant/default.nix` with:
|
||||||
|
|
||||||
|
- PostgreSQL database backend
|
||||||
|
- Custom components
|
||||||
|
- Custom Lovelace modules
|
||||||
|
- HTTPS access with authentication
|
||||||
|
- Integration with other services
|
||||||
|
|
||||||
|
### MQTT
|
||||||
|
|
||||||
|
MQTT is used as a messaging protocol for various smart home devices. The Mosquitto MQTT broker is automatically configured when Home Assistant is enabled.
|
||||||
|
|
||||||
|
### Zigbee2MQTT
|
||||||
|
|
||||||
|
Zigbee2MQTT allows integration with Zigbee devices. It's configured with:
|
||||||
|
|
||||||
|
- Automatic discovery for Home Assistant
|
||||||
|
- OTA updates for Zigbee devices
|
||||||
|
- Web interface for management
|
||||||
|
|
||||||
|
### Thread Border Router
|
||||||
|
|
||||||
|
The Thread Border Router provides integration with Thread-based devices like Matter devices.
|
||||||
|
|
||||||
|
## Custom Components
|
||||||
|
|
||||||
|
The following custom components are included:
|
||||||
|
|
||||||
|
- `ha-anycubic` - Anycubic 3D printer integration
|
||||||
|
- `ha-bambulab` - Bambu Lab 3D printer integration
|
||||||
|
- `ha-bedjet` - BedJet climate control integration
|
||||||
|
- `ha-gehome` - GE Home appliance integration
|
||||||
|
- `ha-icloud3` - Enhanced iCloud device tracking
|
||||||
|
- `ha-local-llm` - Local LLM integration
|
||||||
|
- `ha-mail-and-packages` - Mail and package delivery tracking
|
||||||
|
- `ha-nanokvm` - NanoKVM integration
|
||||||
|
- `ha-openhasp` - openHASP integration for DIY displays
|
||||||
|
- `ha-overseerr` - Overseerr media request integration
|
||||||
|
- `ha-petlibro` - PetLibro pet feeder integration
|
||||||
|
- `ha-wyzeapi` - Wyze device integration
|
||||||
|
|
||||||
|
## Automations
|
||||||
|
|
||||||
|
### Light Switch Automations
|
||||||
|
|
||||||
|
The light switch automations handle physical switch inputs for controlling smart lights.
|
||||||
|
|
||||||
|
### Motion Light Automations
|
||||||
|
|
||||||
|
Motion light automations turn lights on when motion is detected and off after a period of inactivity.
|
||||||
|
|
||||||
|
### Custom Automations
|
||||||
|
|
||||||
|
Additional automations are placed in the `/etc/hass` directory and are included in the Home Assistant configuration. These include:
|
||||||
|
|
||||||
|
- `fountain_automation.yaml` - Toggles the water dispensing mode on the Dockstream Smart RFID Fountain every 15 minutes between constant and intermittent flow.
|
||||||
|
|
||||||
|
## Smart Home Devices
|
||||||
|
|
||||||
|
The configuration includes support for various smart home devices:
|
||||||
|
|
||||||
|
### Lighting
|
||||||
|
|
||||||
|
- Various smart lights throughout the home
|
||||||
|
|
||||||
|
### Climate
|
||||||
|
|
||||||
|
- Smart thermostat
|
||||||
|
- Humidifier control
|
||||||
|
|
||||||
|
### Pet Care
|
||||||
|
|
||||||
|
- Dockstream Smart RFID Fountain with scheduling
|
||||||
|
- Smart pet feeders for pets named Joey and Luci
|
||||||
|
- Litter-Robot 4 smart litter box
|
||||||
|
|
||||||
|
### Media
|
||||||
|
|
||||||
|
- Google Cast devices
|
||||||
|
- Smart TVs
|
||||||
|
- Media players
|
||||||
|
|
||||||
|
### Sensors
|
||||||
|
|
||||||
|
- Temperature, humidity, and motion sensors
|
||||||
|
- Door and window sensors
|
||||||
|
- Presence detection
|
||||||
|
|
||||||
|
## Integration with Other Services
|
||||||
|
|
||||||
|
Home Assistant is integrated with:
|
||||||
|
|
||||||
|
- **Music Assistant** - For enhanced music streaming capabilities
|
||||||
|
- **Govee Integration** - For Govee smart devices
|
||||||
|
- **Matter** - For Matter-compatible devices
|
||||||
|
|
||||||
|
## Adding New Automations
|
||||||
|
|
||||||
|
To add a new automation:
|
||||||
|
|
||||||
|
1. Create a YAML file with the automation definition
|
||||||
|
2. Place it in `/etc/hass`
|
||||||
|
3. The automation will be automatically included in Home Assistant
|
||||||
|
|
||||||
|
Example automation format:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
alias: "Automation Name"
|
||||||
|
description: "Description of what the automation does"
|
||||||
|
trigger:
|
||||||
|
- platform: state
|
||||||
|
entity_id: binary_sensor.motion_sensor
|
||||||
|
to: "on"
|
||||||
|
condition: []
|
||||||
|
action:
|
||||||
|
- service: light.turn_on
|
||||||
|
target:
|
||||||
|
entity_id: light.living_room
|
||||||
|
mode: single
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
1. **Zigbee Device Pairing Issues**
|
||||||
|
- Make sure the Zigbee coordinator is properly connected
|
||||||
|
- Check the Zigbee2MQTT logs for errors
|
||||||
|
|
||||||
|
2. **Service Unavailable**
|
||||||
|
- Check if all related services are running
|
||||||
|
- Verify firewall rules allow access to the services
|
||||||
|
|
||||||
|
3. **Database Issues**
|
||||||
|
- Check PostgreSQL service status
|
||||||
|
- Verify database connection settings
|
||||||
148
docs/home-assistant/automations.md
Normal file
148
docs/home-assistant/automations.md
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
# Home Assistant Automations
|
||||||
|
|
||||||
|
This document details the automations configured in the Home Assistant setup.
|
||||||
|
|
||||||
|
## Automation Types
|
||||||
|
|
||||||
|
Automations in this configuration are managed in several ways:
|
||||||
|
|
||||||
|
1. **Module-Based Automations**: Defined in Nix modules within the `modules/nixos/homeassistant/automations/` directory
|
||||||
|
2. **YAML Automations**: Defined in YAML files and included via the `automation manual` directive
|
||||||
|
3. **UI-Created Automations**: Created through the Home Assistant UI and stored in `automations.yaml`
|
||||||
|
|
||||||
|
## Module-Based Automations
|
||||||
|
|
||||||
|
### Light Switch Automations
|
||||||
|
|
||||||
|
**Location**: `modules/nixos/homeassistant/automations/lightswitch/`
|
||||||
|
|
||||||
|
These automations link physical light switches to smart lights:
|
||||||
|
|
||||||
|
- **Bedroom Light Switch**: Controls the bedroom lights
|
||||||
|
- **Living Room Light Switch**: Controls the living room lights
|
||||||
|
- **Bedroom Closet Lights**: Controls the closet lights
|
||||||
|
|
||||||
|
### Motion-Activated Light Automations
|
||||||
|
|
||||||
|
**Location**: `modules/nixos/homeassistant/automations/motion-light/`
|
||||||
|
|
||||||
|
These automations turn lights on when motion is detected and off after a period of inactivity.
|
||||||
|
|
||||||
|
## YAML Automations
|
||||||
|
|
||||||
|
### Fountain Cycling Automation
|
||||||
|
|
||||||
|
**Location**: `/etc/nixos/fountain_automation.yaml`
|
||||||
|
|
||||||
|
This automation toggles the water dispensing mode on the Dockstream Smart RFID Fountain every 15 minutes:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
alias: "Fountain Cycle Mode"
|
||||||
|
description: "Toggles fountain water mode every 15 minutes between constant and intermittent flow"
|
||||||
|
trigger:
|
||||||
|
- platform: time_pattern
|
||||||
|
minutes: "/15" # Every 15 minutes
|
||||||
|
condition: []
|
||||||
|
action:
|
||||||
|
- service: select.select_next
|
||||||
|
target:
|
||||||
|
entity_id: select.dockstream_smart_rfid_fountain_water_dispensing_mode
|
||||||
|
mode: single
|
||||||
|
id: fountain_cycle_mode
|
||||||
|
```
|
||||||
|
|
||||||
|
This automation:
|
||||||
|
1. Triggers every 15 minutes
|
||||||
|
2. Uses the `select.select_next` service to toggle between the two available options:
|
||||||
|
- "Flowing Water (Constant)"
|
||||||
|
- "Intermittent Water (Scheduled)"
|
||||||
|
|
||||||
|
The fountain is also configured with:
|
||||||
|
- Water Interval: 10 minutes
|
||||||
|
- Water Dispensing Duration: 15 minutes
|
||||||
|
|
||||||
|
## Creating New Automations
|
||||||
|
|
||||||
|
### Method 1: Module-Based Automation
|
||||||
|
|
||||||
|
For reusable, complex automations that should be managed in code:
|
||||||
|
|
||||||
|
1. Create a new directory in `modules/nixos/homeassistant/automations/`
|
||||||
|
2. Create a `default.nix` file with the automation logic
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```nix
|
||||||
|
{ config, lib, ... }:
|
||||||
|
{
|
||||||
|
config = {
|
||||||
|
services.home-assistant.config."automation manual" = [
|
||||||
|
{
|
||||||
|
alias = "Example Automation";
|
||||||
|
description = "Example automation created via Nix module";
|
||||||
|
trigger = [
|
||||||
|
{
|
||||||
|
platform = "state";
|
||||||
|
entity_id = "binary_sensor.example_sensor";
|
||||||
|
to = "on";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
action = [
|
||||||
|
{
|
||||||
|
service = "light.turn_on";
|
||||||
|
target.entity_id = "light.example_light";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
mode = "single";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Method 2: YAML Automation
|
||||||
|
|
||||||
|
For simpler automations:
|
||||||
|
|
||||||
|
1. Create a YAML file with the automation definition
|
||||||
|
2. Place it in `/etc/hass/`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```yaml
|
||||||
|
alias: "Example Automation"
|
||||||
|
description: "Example automation in YAML"
|
||||||
|
trigger:
|
||||||
|
- platform: state
|
||||||
|
entity_id: binary_sensor.example_sensor
|
||||||
|
to: "on"
|
||||||
|
action:
|
||||||
|
- service: light.turn_on
|
||||||
|
target:
|
||||||
|
entity_id: light.example_light
|
||||||
|
mode: single
|
||||||
|
```
|
||||||
|
|
||||||
|
### Method 3: UI Creation
|
||||||
|
|
||||||
|
For quick prototyping or simple automations:
|
||||||
|
|
||||||
|
1. Go to Home Assistant UI > Settings > Automations & Scenes
|
||||||
|
2. Click "+ Add Automation"
|
||||||
|
3. Configure using the UI editor
|
||||||
|
|
||||||
|
## Testing Automations
|
||||||
|
|
||||||
|
To test an automation:
|
||||||
|
|
||||||
|
1. In the Home Assistant UI, go to Developer Tools > Services
|
||||||
|
2. Select `automation.trigger` as the service
|
||||||
|
3. Enter the entity_id of your automation in the service data field
|
||||||
|
4. Click "Call Service" to trigger the automation manually
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
If an automation isn't working as expected:
|
||||||
|
|
||||||
|
1. Check the Home Assistant logs for errors
|
||||||
|
2. Verify entity names and service calls are correct
|
||||||
|
3. Test individual triggers and actions separately
|
||||||
|
4. Use the "Debug" section in the automation editor to trace execution
|
||||||
96
docs/home-assistant/fountain-automation.md
Normal file
96
docs/home-assistant/fountain-automation.md
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
# Pet Fountain Automation
|
||||||
|
|
||||||
|
This document details the automation for the Dockstream Smart RFID Fountain device.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The Dockstream Smart RFID Fountain is a smart pet fountain controlled through Home Assistant. A custom automation has been created to toggle the water dispensing mode between constant flow and intermittent flow every 15 minutes. This cycling helps keep the water fresh while reducing energy consumption.
|
||||||
|
|
||||||
|
## Fountain Configuration
|
||||||
|
|
||||||
|
The Dockstream Smart RFID Fountain has the following settings in Home Assistant:
|
||||||
|
|
||||||
|
| Setting | Entity ID | Value | Description |
|
||||||
|
|---------|-----------|-------|-------------|
|
||||||
|
| Water Dispensing Mode | `select.dockstream_smart_rfid_fountain_water_dispensing_mode` | Toggles between modes | Controls how water flows |
|
||||||
|
| Water Interval | `number.dockstream_smart_rfid_fountain_water_interval` | 10 minutes | Time between water dispensing in intermittent mode |
|
||||||
|
| Water Dispensing Duration | `number.dockstream_smart_rfid_fountain_water_dispensing_duration` | 15 minutes | How long water flows in intermittent mode |
|
||||||
|
| Cleaning Cycle | `number.dockstream_smart_rfid_fountain_cleaning_cycle` | 14 days | Reminder interval for cleaning |
|
||||||
|
|
||||||
|
## Available Modes
|
||||||
|
|
||||||
|
The fountain supports two water dispensing modes:
|
||||||
|
|
||||||
|
1. **Flowing Water (Constant)** - Water flows continuously
|
||||||
|
2. **Intermittent Water (Scheduled)** - Water flows according to the interval and duration settings
|
||||||
|
|
||||||
|
## Automation Details
|
||||||
|
|
||||||
|
The fountain cycling automation is defined in `/etc/nixos/fountain_automation.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
alias: "Fountain Cycle Mode"
|
||||||
|
description: "Toggles fountain water mode every 15 minutes between constant and intermittent flow"
|
||||||
|
trigger:
|
||||||
|
- platform: time_pattern
|
||||||
|
minutes: "/15" # Every 15 minutes
|
||||||
|
condition: []
|
||||||
|
action:
|
||||||
|
- service: select.select_next
|
||||||
|
target:
|
||||||
|
entity_id: select.dockstream_smart_rfid_fountain_water_dispensing_mode
|
||||||
|
mode: single
|
||||||
|
id: fountain_cycle_mode
|
||||||
|
```
|
||||||
|
|
||||||
|
### How It Works
|
||||||
|
|
||||||
|
1. **Trigger**: The automation runs every 15 minutes based on the time pattern trigger
|
||||||
|
2. **Action**: It uses the `select.select_next` service to toggle to the next available option
|
||||||
|
3. **Mode**: Set to "single" to prevent multiple executions if triggers overlap
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
The automation is included in Home Assistant via the `automation manual` directive in the Home Assistant configuration:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
"automation manual" = "!include_dir_merge_list /etc/hass";
|
||||||
|
```
|
||||||
|
|
||||||
|
The YAML file needs to be placed in the `/etc/hass` directory to be loaded.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
To manually test the automation:
|
||||||
|
|
||||||
|
1. In Home Assistant UI, go to Developer Tools > Services
|
||||||
|
2. Select `automation.trigger` as the service
|
||||||
|
3. Enter the following service data:
|
||||||
|
```yaml
|
||||||
|
entity_id: automation.fountain_cycle_mode
|
||||||
|
```
|
||||||
|
4. Click "Call Service" to trigger the automation
|
||||||
|
|
||||||
|
## Customizing
|
||||||
|
|
||||||
|
To adjust the cycling interval:
|
||||||
|
|
||||||
|
1. Edit the YAML file at `/etc/nixos/fountain_automation.yaml`
|
||||||
|
2. Change the `minutes` value in the trigger section (e.g., from `"/15"` to `"/30"` for every 30 minutes)
|
||||||
|
3. Save the file
|
||||||
|
4. Restart Home Assistant or reload automations
|
||||||
|
|
||||||
|
To adjust fountain settings:
|
||||||
|
|
||||||
|
1. In Home Assistant UI, go to Settings > Devices & Services
|
||||||
|
2. Find the Dockstream Smart RFID Fountain device
|
||||||
|
3. Adjust the water interval or dispensing duration settings
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
If the automation is not working as expected:
|
||||||
|
|
||||||
|
1. Check that the entity ID is correct and the fountain is online
|
||||||
|
2. Verify that Home Assistant is including the automation file correctly
|
||||||
|
3. Look for errors in the Home Assistant logs related to the automation or the fountain
|
||||||
|
4. Try manually controlling the fountain to ensure it responds to commands
|
||||||
116
docs/modules/README.md
Normal file
116
docs/modules/README.md
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
# Custom Modules
|
||||||
|
|
||||||
|
This directory contains documentation for the custom modules used in this NixOS configuration.
|
||||||
|
|
||||||
|
## Module Types
|
||||||
|
|
||||||
|
The repository uses two main types of modules:
|
||||||
|
|
||||||
|
1. **NixOS Modules** - System-level configurations in `modules/nixos/`
|
||||||
|
2. **Home Manager Modules** - User-level configurations in `modules/home/`
|
||||||
|
|
||||||
|
## NixOS Modules
|
||||||
|
|
||||||
|
These modules configure the system-level aspects of NixOS:
|
||||||
|
|
||||||
|
- [Boot Modules](./boot.md) - Boot loader and kernel configurations
|
||||||
|
- [Desktop Modules](./desktop.md) - Desktop environment configurations
|
||||||
|
- [Development Modules](./development.md) - Development tools and environments
|
||||||
|
- [Hardware Modules](./hardware.md) - Hardware-specific configurations
|
||||||
|
- [Home Assistant Modules](./homeassistant.md) - Home automation configuration
|
||||||
|
- [Networking Modules](./network.md) - Network configuration and services
|
||||||
|
- [Security Modules](./security.md) - Security-related configurations
|
||||||
|
- [Services Modules](./services.md) - Various service configurations
|
||||||
|
- [System Modules](./system.md) - General system configurations
|
||||||
|
- [Virtualization Modules](./virtualization.md) - Virtualization and containerization
|
||||||
|
|
||||||
|
## Home Manager Modules
|
||||||
|
|
||||||
|
These modules configure user environments:
|
||||||
|
|
||||||
|
- [Applications](./home/applications.md) - User applications
|
||||||
|
- [Desktop](./home/desktop.md) - User desktop environments
|
||||||
|
- [Development](./home/development.md) - User development environments
|
||||||
|
- [Media](./home/media.md) - Media applications
|
||||||
|
- [Shell](./home/shell.md) - Shell configurations
|
||||||
|
|
||||||
|
## Module Structure
|
||||||
|
|
||||||
|
Each module follows a standard structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
modules/nixos/example-module/
|
||||||
|
├── default.nix # Main implementation
|
||||||
|
├── options.nix # Option declarations
|
||||||
|
└── submodule/ # Optional submodules
|
||||||
|
└── default.nix # Submodule implementation
|
||||||
|
```
|
||||||
|
|
||||||
|
### default.nix
|
||||||
|
|
||||||
|
The `default.nix` file contains the main implementation of the module:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.${namespace}.example-module;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [ ./options.nix ];
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
# Module implementation when enabled
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### options.nix
|
||||||
|
|
||||||
|
The `options.nix` file declares the module's configuration options:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ lib, namespace, ... }:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}) mkOpt;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.${namespace}.example-module = {
|
||||||
|
enable = mkEnableOption "enable example module";
|
||||||
|
# Other option declarations
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using Modules
|
||||||
|
|
||||||
|
To use a module in your system configuration:
|
||||||
|
|
||||||
|
1. Enable the module in your system configuration:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
|
mjallen.example-module = {
|
||||||
|
enable = true;
|
||||||
|
# Other options
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Creating New Modules
|
||||||
|
|
||||||
|
To create a new module:
|
||||||
|
|
||||||
|
1. Create a new directory in `modules/nixos/` or `modules/home/`
|
||||||
|
2. Create `default.nix` and `options.nix` files
|
||||||
|
3. Implement your module functionality
|
||||||
|
4. Import the module in your system configuration
|
||||||
|
|
||||||
|
See the [Getting Started](../getting-started.md) guide for more details on creating modules.
|
||||||
190
docs/modules/homeassistant.md
Normal file
190
docs/modules/homeassistant.md
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
# Home Assistant Module
|
||||||
|
|
||||||
|
This document details the Home Assistant module configuration.
|
||||||
|
|
||||||
|
## Module Structure
|
||||||
|
|
||||||
|
The Home Assistant module is organized in the following structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
modules/nixos/homeassistant/
|
||||||
|
├── automations/ # Automation configurations
|
||||||
|
│ ├── lightswitch/ # Light switch automations
|
||||||
|
│ └── motion-light/ # Motion-activated light automations
|
||||||
|
├── default.nix # Main module configuration
|
||||||
|
├── options.nix # Module options definition
|
||||||
|
└── services/ # Related service configurations
|
||||||
|
├── govee2mqtt/ # Govee integration via MQTT
|
||||||
|
├── homeassistant/ # Core Home Assistant service
|
||||||
|
├── music-assistant/ # Music Assistant integration
|
||||||
|
├── thread/ # Thread border router
|
||||||
|
└── zigbee2mqtt/ # Zigbee to MQTT bridge
|
||||||
|
```
|
||||||
|
|
||||||
|
## Module Options
|
||||||
|
|
||||||
|
The module is configured through options defined in `options.nix`:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
options.${namespace}.services.home-assistant = {
|
||||||
|
enable = mkEnableOption "enable home-assistant";
|
||||||
|
mosquittoPort = mkOpt types.int 1883 "Port for MQTT";
|
||||||
|
zigbee2mqttPort = mkOpt types.int 8080 "Port for zigbee2mqtt web interface";
|
||||||
|
zigbeeDevicePath = mkOpt types.str "/dev/ttyUSB0" "Path to zigbee usb device";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Main Configuration
|
||||||
|
|
||||||
|
The main module configuration in `default.nix` includes:
|
||||||
|
|
||||||
|
1. **Activation Scripts** - For setting up custom components
|
||||||
|
2. **Service Configurations** - For Matter, PostgreSQL, etc.
|
||||||
|
3. **Firewall Rules** - For allowing required ports
|
||||||
|
|
||||||
|
```nix
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
# Activation script for custom components
|
||||||
|
system.activationScripts.installCustomComponents = ''
|
||||||
|
chown -R hass:hass ${config.services.home-assistant.configDir}
|
||||||
|
chmod -R 750 ${config.services.home-assistant.configDir}
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Service configurations
|
||||||
|
services = {
|
||||||
|
matter-server.enable = true;
|
||||||
|
postgresql = {
|
||||||
|
enable = false;
|
||||||
|
ensureDatabases = [ "hass" ];
|
||||||
|
ensureUsers = [
|
||||||
|
{
|
||||||
|
name = "hass";
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Firewall rules
|
||||||
|
networking.firewall.allowedTCPPorts = [
|
||||||
|
cfg.mosquittoPort
|
||||||
|
cfg.zigbee2mqttPort
|
||||||
|
8095 # music-assistant
|
||||||
|
8097 # home-assistant
|
||||||
|
5580 # matter-server
|
||||||
|
];
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Home Assistant Service
|
||||||
|
|
||||||
|
The core Home Assistant service configuration in `services/homeassistant/default.nix` includes:
|
||||||
|
|
||||||
|
1. **Package Selection** - Using the standard Home Assistant package
|
||||||
|
2. **Component Configuration** - Enabling required components
|
||||||
|
3. **Custom Components** - Adding custom components from packages
|
||||||
|
4. **Lovelace Modules** - Adding custom UI components
|
||||||
|
5. **Integration Configuration** - Setting up integrations with other systems
|
||||||
|
|
||||||
|
```nix
|
||||||
|
services.home-assistant = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.home-assistant;
|
||||||
|
openFirewall = true;
|
||||||
|
configDir = "/var/lib/homeassistant";
|
||||||
|
configWritable = true;
|
||||||
|
|
||||||
|
# Components
|
||||||
|
extraComponents = [
|
||||||
|
"mqtt"
|
||||||
|
"zha"
|
||||||
|
"homekit"
|
||||||
|
# ... many more components
|
||||||
|
];
|
||||||
|
|
||||||
|
# Custom components
|
||||||
|
customComponents = [
|
||||||
|
# ... custom components
|
||||||
|
];
|
||||||
|
|
||||||
|
# Lovelace modules
|
||||||
|
customLovelaceModules = [
|
||||||
|
# ... custom UI modules
|
||||||
|
];
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
config = {
|
||||||
|
# ... Home Assistant configuration
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Related Services
|
||||||
|
|
||||||
|
### Zigbee2MQTT
|
||||||
|
|
||||||
|
The Zigbee2MQTT service in `services/zigbee2mqtt/default.nix` connects Zigbee devices to MQTT:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
services.zigbee2mqtt = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
mqtt = {
|
||||||
|
server = "mqtt://localhost:${toString cfg.mosquittoPort}";
|
||||||
|
};
|
||||||
|
serial = {
|
||||||
|
port = cfg.zigbeeDevicePath;
|
||||||
|
};
|
||||||
|
# ... additional settings
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### MQTT
|
||||||
|
|
||||||
|
MQTT is configured as a dependency for the Home Assistant module.
|
||||||
|
|
||||||
|
### Thread Border Router
|
||||||
|
|
||||||
|
The Thread Border Router in `services/thread/default.nix` provides Thread network connectivity for Matter devices.
|
||||||
|
|
||||||
|
## Automations
|
||||||
|
|
||||||
|
The module includes predefined automations in the `automations/` directory:
|
||||||
|
|
||||||
|
1. **Light Switch Automations** - For controlling lights via physical switches
|
||||||
|
2. **Motion Light Automations** - For motion-activated lighting
|
||||||
|
|
||||||
|
## Using the Module
|
||||||
|
|
||||||
|
To use this module in a system configuration:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ config, ... }:
|
||||||
|
{
|
||||||
|
mjallen.services.home-assistant = {
|
||||||
|
enable = true;
|
||||||
|
# Optional: customize ports and device paths
|
||||||
|
mosquittoPort = 1883;
|
||||||
|
zigbee2mqttPort = 8080;
|
||||||
|
zigbeeDevicePath = "/dev/ttyUSB0";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Extending the Module
|
||||||
|
|
||||||
|
### Adding Custom Components
|
||||||
|
|
||||||
|
To add a custom component:
|
||||||
|
|
||||||
|
1. Add the package to `packages/`
|
||||||
|
2. Add it to the `customComponents` list in `services/homeassistant/default.nix`
|
||||||
|
|
||||||
|
### Adding Custom Automations
|
||||||
|
|
||||||
|
To add a custom automation:
|
||||||
|
|
||||||
|
1. Create a new directory in `automations/`
|
||||||
|
2. Implement the automation in `default.nix`
|
||||||
|
3. Import it in the system configuration
|
||||||
22
docs/systems/README.md
Normal file
22
docs/systems/README.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# System Configurations
|
||||||
|
|
||||||
|
This directory contains documentation for each system configuration in this repository.
|
||||||
|
|
||||||
|
## Systems
|
||||||
|
|
||||||
|
- [Desktop (matt-nixos)](./matt-nixos.md) - Main desktop computer
|
||||||
|
- [NAS (jallen-nas)](./jallen-nas.md) - Home server and NAS
|
||||||
|
- [NUC (nuc-nixos)](./nuc-nixos.md) - Intel NUC
|
||||||
|
- [Raspberry Pi 5](./pi5.md) - Raspberry Pi 5
|
||||||
|
- [MacBook Pro (nixOS)](./macbook-pro-nixos.md) - MacBook Pro running NixOS
|
||||||
|
|
||||||
|
## Common Configuration
|
||||||
|
|
||||||
|
All systems share certain common configurations through the modules system. These include:
|
||||||
|
|
||||||
|
- Base system configuration
|
||||||
|
- User management
|
||||||
|
- Network configuration
|
||||||
|
- Security settings
|
||||||
|
|
||||||
|
Each system then adds its specific configurations on top of these common modules.
|
||||||
101
docs/systems/jallen-nas.md
Normal file
101
docs/systems/jallen-nas.md
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# NAS Server (jallen-nas)
|
||||||
|
|
||||||
|
This document describes the configuration for the NAS server system.
|
||||||
|
|
||||||
|
## Hardware
|
||||||
|
|
||||||
|
The NAS server is built on AMD hardware:
|
||||||
|
|
||||||
|
- CPU: AMD processor
|
||||||
|
- Hardware-specific modules:
|
||||||
|
- `nixos-hardware.nixosModules.common-pc`
|
||||||
|
- `nixos-hardware.nixosModules.common-cpu-amd`
|
||||||
|
- `nixos-hardware.nixosModules.common-cpu-amd-pstate`
|
||||||
|
- `nixos-hardware.nixosModules.common-hidpi`
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
The NAS hosts various services:
|
||||||
|
|
||||||
|
### Media Services
|
||||||
|
|
||||||
|
- **Jellyfin** - Media server
|
||||||
|
- **Jellyseerr** - Media request manager
|
||||||
|
- **Sonarr** - TV show management
|
||||||
|
- **Radarr** - Movie management
|
||||||
|
- **Lidarr** - Music management
|
||||||
|
- **Bazarr** - Subtitle management
|
||||||
|
- **Music Assistant** - Music streaming integration with Home Assistant
|
||||||
|
|
||||||
|
### Download Services
|
||||||
|
|
||||||
|
- **Transmission** - Torrent client
|
||||||
|
- **NZBGet** - Usenet downloader
|
||||||
|
- **Prowlarr** - Indexer manager
|
||||||
|
|
||||||
|
### Document Management
|
||||||
|
|
||||||
|
- **Paperless-ngx** - Document management system
|
||||||
|
|
||||||
|
### File Sharing
|
||||||
|
|
||||||
|
- **Samba** - Windows file sharing
|
||||||
|
- **Nextcloud** - Self-hosted cloud storage
|
||||||
|
|
||||||
|
### AI Services
|
||||||
|
|
||||||
|
- **Ollama** - Local AI model hosting
|
||||||
|
|
||||||
|
### Smart Home
|
||||||
|
|
||||||
|
- **Home Assistant** - Smart home controller
|
||||||
|
- **Zigbee2MQTT** - Zigbee device integration
|
||||||
|
- **MQTT** - Message broker for IoT devices
|
||||||
|
- **Thread Border Router** - Thread network for smart home devices
|
||||||
|
|
||||||
|
## Storage Configuration
|
||||||
|
|
||||||
|
The NAS uses multiple storage devices:
|
||||||
|
|
||||||
|
1. **System Drive** - For the operating system
|
||||||
|
2. **Data Drives** - Configured as a storage array for media and data
|
||||||
|
|
||||||
|
## Network Configuration
|
||||||
|
|
||||||
|
The NAS is configured with:
|
||||||
|
|
||||||
|
- Static IP address
|
||||||
|
- Firewall rules for the various services
|
||||||
|
- Tailscale for secure remote access
|
||||||
|
|
||||||
|
## Backup Strategy
|
||||||
|
|
||||||
|
The NAS implements a comprehensive backup strategy:
|
||||||
|
|
||||||
|
1. **System Backup** - Regular backups of the NixOS configuration
|
||||||
|
2. **Data Backup** - Backups of important data to secondary storage
|
||||||
|
3. **Off-site Backup** - Critical data is backed up off-site
|
||||||
|
|
||||||
|
## Usage and Management
|
||||||
|
|
||||||
|
### Accessing Services
|
||||||
|
|
||||||
|
Most services are available through a reverse proxy, which provides:
|
||||||
|
- HTTPS access
|
||||||
|
- Authentication via Authentik
|
||||||
|
- Subdomain-based routing
|
||||||
|
|
||||||
|
### Adding Storage
|
||||||
|
|
||||||
|
To add additional storage to the NAS:
|
||||||
|
|
||||||
|
1. Add the physical drive to the system
|
||||||
|
2. Update the disko configuration
|
||||||
|
3. Rebuild the system with `nixos-rebuild switch`
|
||||||
|
|
||||||
|
### Monitoring
|
||||||
|
|
||||||
|
The system can be monitored through:
|
||||||
|
- Prometheus metrics
|
||||||
|
- Grafana dashboards
|
||||||
|
- Home Assistant sensors
|
||||||
213
docs/troubleshooting.md
Normal file
213
docs/troubleshooting.md
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
# Troubleshooting Guide
|
||||||
|
|
||||||
|
This guide provides solutions for common issues that may arise when using this NixOS configuration.
|
||||||
|
|
||||||
|
## System Issues
|
||||||
|
|
||||||
|
### Failed System Build
|
||||||
|
|
||||||
|
**Problem**: `nixos-rebuild switch` fails with an error.
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
|
||||||
|
1. **Syntax Errors**:
|
||||||
|
- Check the error message for file and line number information
|
||||||
|
- Verify the syntax in the mentioned file
|
||||||
|
- Common issues include missing semicolons, curly braces, or mismatched quotes
|
||||||
|
|
||||||
|
2. **Missing Dependencies**:
|
||||||
|
- If the error mentions a missing package or dependency:
|
||||||
|
```
|
||||||
|
git pull # Update to the latest version
|
||||||
|
nix flake update # Update the flake inputs
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Conflicting Modules**:
|
||||||
|
- Look for modules that might be configuring the same options incompatibly
|
||||||
|
- Disable one of the conflicting modules or adjust their configurations
|
||||||
|
|
||||||
|
4. **Disk Space Issues**:
|
||||||
|
- Check available disk space with `df -h`
|
||||||
|
- Clear old generations: `sudo nix-collect-garbage -d`
|
||||||
|
|
||||||
|
### Boot Issues
|
||||||
|
|
||||||
|
**Problem**: System fails to boot after a configuration change.
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
|
||||||
|
1. **Boot into a Previous Generation**:
|
||||||
|
- At the boot menu, select an older generation
|
||||||
|
- Once booted, revert the problematic change:
|
||||||
|
```
|
||||||
|
cd /etc/nixos
|
||||||
|
git revert HEAD # Or edit the files directly
|
||||||
|
sudo nixos-rebuild switch
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Boot from Installation Media**:
|
||||||
|
- Boot from a NixOS installation media
|
||||||
|
- Mount your system:
|
||||||
|
```
|
||||||
|
sudo mount /dev/disk/by-label/nixos /mnt
|
||||||
|
sudo mount /dev/disk/by-label/boot /mnt/boot # If separate boot partition
|
||||||
|
```
|
||||||
|
- Chroot into your system:
|
||||||
|
```
|
||||||
|
sudo nixos-enter --root /mnt
|
||||||
|
cd /etc/nixos
|
||||||
|
git revert HEAD # Or edit the files directly
|
||||||
|
nixos-rebuild switch --install-bootloader
|
||||||
|
```
|
||||||
|
|
||||||
|
## Home Assistant Issues
|
||||||
|
|
||||||
|
### Home Assistant Fails to Start
|
||||||
|
|
||||||
|
**Problem**: Home Assistant service fails to start.
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
|
||||||
|
1. **Check Service Status**:
|
||||||
|
```
|
||||||
|
systemctl status home-assistant
|
||||||
|
journalctl -u home-assistant -n 100
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Database Issues**:
|
||||||
|
- Check PostgreSQL is running: `systemctl status postgresql`
|
||||||
|
- Verify database connection settings in Home Assistant configuration
|
||||||
|
|
||||||
|
3. **Permission Issues**:
|
||||||
|
- Check ownership and permissions on config directory:
|
||||||
|
```
|
||||||
|
ls -la /var/lib/homeassistant
|
||||||
|
sudo chown -R hass:hass /var/lib/homeassistant
|
||||||
|
sudo chmod -R 750 /var/lib/homeassistant
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Custom Component Issues**:
|
||||||
|
- Try disabling custom components to isolate the issue:
|
||||||
|
- Edit `modules/nixos/homeassistant/services/homeassistant/default.nix`
|
||||||
|
- Comment out the `customComponents` section
|
||||||
|
- Rebuild: `sudo nixos-rebuild switch`
|
||||||
|
|
||||||
|
### Zigbee Device Connection Issues
|
||||||
|
|
||||||
|
**Problem**: Zigbee devices fail to connect or are unstable.
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
|
||||||
|
1. **Verify Device Path**:
|
||||||
|
- Check the Zigbee coordinator is properly detected:
|
||||||
|
```
|
||||||
|
ls -la /dev/ttyUSB*
|
||||||
|
```
|
||||||
|
- Update the device path if needed:
|
||||||
|
- Edit your system configuration
|
||||||
|
- Set `mjallen.services.home-assistant.zigbeeDevicePath` to the correct path
|
||||||
|
- Rebuild: `sudo nixos-rebuild switch`
|
||||||
|
|
||||||
|
2. **Interference Issues**:
|
||||||
|
- Move the Zigbee coordinator away from other wireless devices
|
||||||
|
- Try a USB extension cable to improve positioning
|
||||||
|
- Change Zigbee channel in Zigbee2MQTT configuration
|
||||||
|
|
||||||
|
3. **Reset Zigbee2MQTT**:
|
||||||
|
```
|
||||||
|
systemctl restart zigbee2mqtt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Automation Issues
|
||||||
|
|
||||||
|
**Problem**: Automations don't run as expected.
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
|
||||||
|
1. **Check Automation Status**:
|
||||||
|
- In Home Assistant UI, verify the automation is enabled
|
||||||
|
- Check Home Assistant logs for automation execution errors
|
||||||
|
|
||||||
|
2. **Entity Issues**:
|
||||||
|
- Verify entity IDs are correct
|
||||||
|
- Check if entities are available/connected
|
||||||
|
- Test direct service calls to verify entity control works
|
||||||
|
|
||||||
|
3. **Trigger Issues**:
|
||||||
|
- Test the automation manually via Developer Tools > Services
|
||||||
|
- Use `automation.trigger` service with the automation's entity_id
|
||||||
|
|
||||||
|
## Flake Issues
|
||||||
|
|
||||||
|
### Flake Input Update Errors
|
||||||
|
|
||||||
|
**Problem**: `nix flake update` fails or causes issues.
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
|
||||||
|
1. **Selective Updates**:
|
||||||
|
- Update specific inputs instead of all at once:
|
||||||
|
```
|
||||||
|
nix flake lock --update-input nixpkgs
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Rollback Flake Lock**:
|
||||||
|
- If an update causes issues, revert to previous flake.lock:
|
||||||
|
```
|
||||||
|
git checkout HEAD^ -- flake.lock
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Pin to Specific Revisions**:
|
||||||
|
- In `flake.nix`, pin problematic inputs to specific revisions:
|
||||||
|
```nix
|
||||||
|
nixpkgs-stable.url = "github:NixOS/nixpkgs/5233fd2ba76a3accb05f88b08917450363be8899";
|
||||||
|
```
|
||||||
|
|
||||||
|
## Secret Management Issues
|
||||||
|
|
||||||
|
### Sops Decryption Errors
|
||||||
|
|
||||||
|
**Problem**: Sops fails to decrypt secrets.
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
|
||||||
|
1. **Key Issues**:
|
||||||
|
- Verify your GPG key is available and unlocked
|
||||||
|
- Check `.sops.yaml` includes your key fingerprint
|
||||||
|
|
||||||
|
2. **Permission Issues**:
|
||||||
|
- Check file permissions on secret files
|
||||||
|
- Make sure the user running `nixos-rebuild` has access to the GPG key
|
||||||
|
|
||||||
|
## Network Issues
|
||||||
|
|
||||||
|
### Firewall Blocks Services
|
||||||
|
|
||||||
|
**Problem**: Services are not accessible due to firewall rules.
|
||||||
|
|
||||||
|
**Solutions**:
|
||||||
|
|
||||||
|
1. **Check Firewall Status**:
|
||||||
|
```
|
||||||
|
sudo nix-shell -p iptables --run "iptables -L"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Verify Firewall Configuration**:
|
||||||
|
- Check if ports are properly allowed in the configuration
|
||||||
|
- Add missing ports if necessary
|
||||||
|
|
||||||
|
3. **Temporary Disable Firewall** (for testing only):
|
||||||
|
```
|
||||||
|
sudo systemctl stop firewall
|
||||||
|
# After testing
|
||||||
|
sudo systemctl start firewall
|
||||||
|
```
|
||||||
|
|
||||||
|
## Getting Help
|
||||||
|
|
||||||
|
If you encounter an issue not covered in this guide:
|
||||||
|
|
||||||
|
1. Check the NixOS Wiki: https://nixos.wiki/
|
||||||
|
2. Search the NixOS Discourse forum: https://discourse.nixos.org/
|
||||||
|
3. Join the NixOS Matrix/Discord community for real-time help
|
||||||
|
4. File an issue in the repository if you believe you've found a bug
|
||||||
208
docs/version.schema.json
Normal file
208
docs/version.schema.json
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "https://example.invalid/version.schema.json",
|
||||||
|
"title": "Unified Package Version Schema",
|
||||||
|
"description": "Schema for a unified version.json used by packages/",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"schemaVersion",
|
||||||
|
"sources"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"schemaVersion": {
|
||||||
|
"type": "integer",
|
||||||
|
"enum": [1],
|
||||||
|
"description": "Schema version. Start at 1; bump on breaking changes."
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Common variables available for template substitution in string fields.",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultVariant": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Optional default variant name for consumers."
|
||||||
|
},
|
||||||
|
"sources": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Base component sources keyed by component name.",
|
||||||
|
"minProperties": 1,
|
||||||
|
"additionalProperties": {
|
||||||
|
"$ref": "#/$defs/SourceSpec"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variants": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Optional variants/channels/flavors; each overlays the base.",
|
||||||
|
"additionalProperties": {
|
||||||
|
"$ref": "#/$defs/VariantSpec"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notes": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Optional free-form human notes/documentation.",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$defs": {
|
||||||
|
"SourceSpecBase": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"fetcher": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["github", "git", "url", "pypi", "none"],
|
||||||
|
"description": "Fetcher type for this source."
|
||||||
|
},
|
||||||
|
"hash": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^sha[0-9]+-",
|
||||||
|
"description": "SRI hash for the fetched artifact. Required unless fetcher is 'none'."
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Optional version string metadata for this component."
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Optional free-form metadata for consumer logic.",
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"owner": { "type": "string", "description": "GitHub owner/org (github fetcher)." },
|
||||||
|
"repo": { "type": "string", "description": "GitHub repository (github fetcher)." },
|
||||||
|
"tag": { "type": "string", "description": "Git tag (github fetcher). Mutually exclusive with 'rev'." },
|
||||||
|
"rev": { "type": "string", "description": "Commit revision (github/git fetchers)." },
|
||||||
|
"submodules": { "type": "boolean", "description": "Whether to fetch submodules (github/git fetchers)." },
|
||||||
|
|
||||||
|
"url": { "type": "string", "description": "Final URL (url fetcher). May be templated." },
|
||||||
|
"urlTemplate": { "type": "string", "description": "Template for URL (url fetcher); supports ${var}." },
|
||||||
|
|
||||||
|
"name": { "type": "string", "description": "PyPI dist name (pypi fetcher)." }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"SourceSpec": {
|
||||||
|
"allOf": [
|
||||||
|
{ "$ref": "#/$defs/SourceSpecBase" },
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": { "fetcher": { "const": "github" } },
|
||||||
|
"required": ["fetcher"]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"required": ["owner", "repo"],
|
||||||
|
"oneOf": [
|
||||||
|
{ "required": ["tag"] },
|
||||||
|
{ "required": ["rev"] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": { "fetcher": { "const": "git" } },
|
||||||
|
"required": ["fetcher"]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"required": ["url", "rev"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": { "fetcher": { "const": "url" } },
|
||||||
|
"required": ["fetcher"]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"oneOf": [
|
||||||
|
{ "required": ["url"] },
|
||||||
|
{ "required": ["urlTemplate"] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": { "fetcher": { "const": "pypi" } },
|
||||||
|
"required": ["fetcher"]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"required": ["name", "version"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": { "fetcher": { "enum": ["github", "git", "url", "pypi"] } },
|
||||||
|
"required": ["fetcher"]
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"required": ["hash"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
"SourceOverride": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"description": "Partial override of a source within a variant. All fields optional.",
|
||||||
|
"properties": {
|
||||||
|
"fetcher": { "type": "string", "enum": ["github", "git", "url", "pypi", "none"] },
|
||||||
|
"hash": { "type": "string", "pattern": "^sha[0-9]+-" },
|
||||||
|
"version": { "type": "string" },
|
||||||
|
"extra": { "type": "object", "additionalProperties": true },
|
||||||
|
|
||||||
|
"owner": { "type": "string" },
|
||||||
|
"repo": { "type": "string" },
|
||||||
|
"tag": { "type": "string" },
|
||||||
|
"rev": { "type": "string" },
|
||||||
|
"submodules": { "type": "boolean" },
|
||||||
|
|
||||||
|
"url": { "type": "string" },
|
||||||
|
"urlTemplate": { "type": "string" },
|
||||||
|
|
||||||
|
"name": { "type": "string" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"VariantSpec": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"inherits": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Optional base variant to inherit from."
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Variant-level variables that overlay top-level variables.",
|
||||||
|
"additionalProperties": { "type": "string" }
|
||||||
|
},
|
||||||
|
"sources": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Per-component overrides for this variant.",
|
||||||
|
"additionalProperties": { "$ref": "#/$defs/SourceOverride" }
|
||||||
|
},
|
||||||
|
"platforms": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Optional per-system overrides to support differing hashes/fields by platform.",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"sources": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": { "$ref": "#/$defs/SourceOverride" }
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": { "type": "string" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1410
flake.lock
generated
1410
flake.lock
generated
File diff suppressed because it is too large
Load Diff
227
flake.nix
227
flake.nix
@@ -1,30 +1,45 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = rec {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable-small";
|
||||||
nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.05";
|
nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.11";
|
||||||
|
|
||||||
|
nixpkgs-otbr.url = "github:mrene/nixpkgs/openthread-border-router";
|
||||||
|
|
||||||
|
home-manager-stable = {
|
||||||
|
url = "github:nix-community/home-manager/release-25.11";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs-stable";
|
||||||
|
};
|
||||||
|
|
||||||
|
home-manager-unstable = {
|
||||||
|
url = "github:nix-community/home-manager";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||||
|
};
|
||||||
|
|
||||||
|
nixpkgs = nixpkgs-unstable;
|
||||||
|
home-manager = home-manager-unstable;
|
||||||
|
|
||||||
# The name "snowfall-lib" is required due to how Snowfall Lib processes your
|
# The name "snowfall-lib" is required due to how Snowfall Lib processes your
|
||||||
# flake's inputs.
|
# flake's inputs.
|
||||||
snowfall-lib = {
|
snowfall-lib = {
|
||||||
url = "github:snowfallorg/lib";
|
url = "github:mjallen18/snowfall-lib";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
|
|
||||||
chaotic.url = "github:chaotic-cx/nyx/nyxpkgs-unstable";
|
|
||||||
|
|
||||||
home-manager = {
|
|
||||||
url = "github:nix-community/home-manager";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# nixos-generators = {
|
||||||
|
# url = "github:nix-community/nixos-generators";
|
||||||
|
# inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
# };
|
||||||
|
|
||||||
impermanence.url = "github:nix-community/impermanence";
|
impermanence.url = "github:nix-community/impermanence";
|
||||||
|
|
||||||
lanzaboote.url = "github:nix-community/lanzaboote/v0.4.2";
|
lanzaboote.url = "github:nix-community/lanzaboote/v1.0.0";
|
||||||
|
|
||||||
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
||||||
|
|
||||||
sops-nix.url = "github:Mic92/sops-nix";
|
sops-nix.url = "github:Mic92/sops-nix";
|
||||||
|
|
||||||
|
nix-cachyos-kernel.url = "github:xddxdd/nix-cachyos-kernel/release";
|
||||||
|
|
||||||
steam-rom-manager = {
|
steam-rom-manager = {
|
||||||
url = "github:mjallen18/nix-steam-rom-manager";
|
url = "github:mjallen18/nix-steam-rom-manager";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
@@ -35,24 +50,21 @@
|
|||||||
|
|
||||||
nix-vscode-extensions.url = "github:nix-community/nix-vscode-extensions";
|
nix-vscode-extensions.url = "github:nix-community/nix-vscode-extensions";
|
||||||
|
|
||||||
authentik-nix.url = "github:nix-community/authentik-nix";
|
authentik-nix = {
|
||||||
|
url = "github:nix-community/authentik-nix";
|
||||||
crowdsec.url = "git+https://codeberg.org/kampka/nix-flake-crowdsec.git";
|
# inputs.nixpkgs.follows = "nixpkgs-stable";
|
||||||
|
};
|
||||||
|
|
||||||
nixai.url = "github:olafkfreund/nix-ai-help";
|
nixai.url = "github:olafkfreund/nix-ai-help";
|
||||||
|
|
||||||
disko = {
|
disko = {
|
||||||
# the fork is needed for partition attributes support
|
# the fork is needed for partition attributes support
|
||||||
url = "github:nvmd/disko/gpt-attrs";
|
# url = "github:nvmd/disko/gpt-attrs";
|
||||||
# url = "github:nix-community/disko";
|
url = "github:nix-community/disko";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
nixos-raspberrypi.url = "github:mjallen18/nixos-raspberrypi";
|
darwin.url = "github:nix-darwin/nix-darwin/master";
|
||||||
|
|
||||||
jovian.url = "github:Jovian-Experiments/Jovian-NixOS";
|
|
||||||
|
|
||||||
darwin.url = "github:LnL7/nix-darwin";
|
|
||||||
|
|
||||||
nix-homebrew.url = "github:zhaofengli/nix-homebrew";
|
nix-homebrew.url = "github:zhaofengli/nix-homebrew";
|
||||||
|
|
||||||
@@ -68,7 +80,10 @@
|
|||||||
|
|
||||||
nixos-apple-silicon.url = "github:nix-community/nixos-apple-silicon";
|
nixos-apple-silicon.url = "github:nix-community/nixos-apple-silicon";
|
||||||
|
|
||||||
pre-commit-hooks-nix.url = "github:cachix/pre-commit-hooks.nix";
|
pre-commit-hooks-nix = {
|
||||||
|
url = "github:cachix/pre-commit-hooks.nix";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
treefmt-nix = {
|
treefmt-nix = {
|
||||||
url = "github:numtide/treefmt-nix";
|
url = "github:numtide/treefmt-nix";
|
||||||
@@ -81,12 +96,34 @@
|
|||||||
nixpkgs.follows = "nixpkgs";
|
nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
lsfg-vk = {
|
||||||
|
url = "github:pabloaul/lsfg-vk-flake";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
nix-plist-manager.url = "github:sushydev/nix-plist-manager";
|
||||||
|
|
||||||
|
nix-rosetta-builder = {
|
||||||
|
url = "github:cpick/nix-rosetta-builder";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
stylix = {
|
||||||
|
url = "github:nix-community/stylix";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
jovian = {
|
||||||
|
url = "github:Jovian-Experiments/Jovian-NixOS";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# We will handle this in the next section.
|
# We will handle this in the next section.
|
||||||
outputs = inputs:
|
outputs =
|
||||||
let
|
inputs:
|
||||||
snowfall = inputs.snowfall-lib.mkFlake {
|
inputs.snowfall-lib.mkFlake {
|
||||||
# You must provide our flake inputs to Snowfall Lib.
|
# You must provide our flake inputs to Snowfall Lib.
|
||||||
inherit inputs;
|
inherit inputs;
|
||||||
|
|
||||||
@@ -95,25 +132,39 @@
|
|||||||
# Nix files to a separate directory.
|
# Nix files to a separate directory.
|
||||||
src = ./.;
|
src = ./.;
|
||||||
|
|
||||||
|
overlays = with inputs; [
|
||||||
|
nix-vscode-extensions.overlays.default
|
||||||
|
nix-cachyos-kernel.overlays.default
|
||||||
|
];
|
||||||
|
|
||||||
# Add a module to a specific host.
|
# Add a module to a specific host.
|
||||||
systems = {
|
systems = {
|
||||||
# common modules
|
# common modules
|
||||||
modules.nixos = with inputs; [
|
modules.nixos = with inputs; [
|
||||||
|
# nix-cachyos-kernel.nixosModules.default
|
||||||
authentik-nix.nixosModules.default
|
authentik-nix.nixosModules.default
|
||||||
chaotic.nixosModules.default
|
|
||||||
crowdsec.nixosModules.crowdsec
|
|
||||||
crowdsec.nixosModules.crowdsec-firewall-bouncer
|
|
||||||
disko.nixosModules.disko
|
disko.nixosModules.disko
|
||||||
impermanence.nixosModules.impermanence
|
impermanence.nixosModules.impermanence
|
||||||
lanzaboote.nixosModules.lanzaboote
|
lanzaboote.nixosModules.lanzaboote
|
||||||
sops-nix.nixosModules.sops
|
sops-nix.nixosModules.sops
|
||||||
home-manager.nixosModules.home-manager
|
home-manager.nixosModules.home-manager
|
||||||
|
nix-index-database.nixosModules.nix-index
|
||||||
|
stylix.nixosModules.stylix
|
||||||
|
];
|
||||||
|
|
||||||
|
modules.home = with inputs; [
|
||||||
|
nix-index-database.homeManagerModules.nix-index
|
||||||
|
steam-rom-manager.homeManagerModules.default
|
||||||
];
|
];
|
||||||
|
|
||||||
# common darwin modules
|
# common darwin modules
|
||||||
modules.darwin = with inputs; [
|
modules.darwin = with inputs; [
|
||||||
nix-homebrew.darwinModules.nix-homebrew
|
nix-homebrew.darwinModules.nix-homebrew
|
||||||
home-manager.darwinModules.home-manager
|
home-manager.darwinModules.home-manager
|
||||||
|
nix-plist-manager.darwinModules.default
|
||||||
|
nix-rosetta-builder.darwinModules.default
|
||||||
|
nix-index-database.darwinModules.nix-index
|
||||||
|
stylix.darwinModules.stylix
|
||||||
];
|
];
|
||||||
|
|
||||||
# Host config
|
# Host config
|
||||||
@@ -121,85 +172,53 @@
|
|||||||
# ######################################################
|
# ######################################################
|
||||||
# Desktop #
|
# Desktop #
|
||||||
# ######################################################
|
# ######################################################
|
||||||
desktop = {
|
matt-nixos = {
|
||||||
modules = with inputs; [
|
modules = with inputs; [
|
||||||
nixos-hardware.nixosModules.common-cpu-amd
|
nixos-hardware.nixosModules.common-cpu-amd
|
||||||
nixos-hardware.nixosModules.common-cpu-amd-pstate
|
nixos-hardware.nixosModules.common-cpu-amd-pstate
|
||||||
nixos-hardware.nixosModules.common-cpu-amd-zenpower
|
# nixos-hardware.nixosModules.common-cpu-amd-zenpower
|
||||||
nixos-hardware.nixosModules.common-gpu-amd
|
nixos-hardware.nixosModules.common-gpu-amd
|
||||||
nixos-hardware.nixosModules.common-hidpi
|
nixos-hardware.nixosModules.common-hidpi
|
||||||
nixos-hardware.nixosModules.common-pc
|
nixos-hardware.nixosModules.common-pc
|
||||||
|
lsfg-vk.nixosModules.default
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
# ######################################################
|
# ######################################################
|
||||||
# NAS #
|
# NAS #
|
||||||
# ######################################################
|
# ######################################################
|
||||||
nas = {
|
jallen-nas = {
|
||||||
modules = with inputs; [
|
modules = with inputs; [
|
||||||
nixos-hardware.nixosModules.common-pc
|
nixos-hardware.nixosModules.common-pc
|
||||||
nixos-hardware.nixosModules.common-cpu-amd
|
nixos-hardware.nixosModules.common-cpu-amd
|
||||||
nixos-hardware.nixosModules.common-cpu-amd-pstate
|
nixos-hardware.nixosModules.common-cpu-amd-pstate
|
||||||
nixos-hardware.nixosModules.common-cpu-amd-zenpower
|
# nixos-hardware.nixosModules.common-cpu-amd-zenpower
|
||||||
nixos-hardware.nixosModules.common-hidpi
|
nixos-hardware.nixosModules.common-hidpi
|
||||||
home-manager.nixosModules.home-manager
|
home-manager.nixosModules.home-manager
|
||||||
];
|
];
|
||||||
# overlays = with inputs; [ crowdsec.overlays.default ];
|
|
||||||
};
|
|
||||||
|
|
||||||
# ######################################################
|
|
||||||
# Steamdeck #
|
|
||||||
# ######################################################
|
|
||||||
deck = {
|
|
||||||
modules = with inputs; [
|
|
||||||
disko.nixosModules.disko
|
|
||||||
jovian.nixosModules.jovian
|
|
||||||
nixos-hardware.nixosModules.common-cpu-amd
|
|
||||||
nixos-hardware.nixosModules.common-cpu-amd-pstate
|
|
||||||
nixos-hardware.nixosModules.common-cpu-amd-zenpower
|
|
||||||
nixos-hardware.nixosModules.common-gpu-amd
|
|
||||||
nixos-hardware.nixosModules.common-hidpi
|
|
||||||
nixos-hardware.nixosModules.common-pc
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# ######################################################
|
# ######################################################
|
||||||
# NUC #
|
# NUC #
|
||||||
# ######################################################
|
# ######################################################
|
||||||
nuc = {
|
nuc-nixos = {
|
||||||
modules = with inputs; [
|
modules = with inputs; [
|
||||||
disko.nixosModules.disko
|
disko.nixosModules.disko
|
||||||
nixos-hardware.nixosModules.common-cpu-amd
|
nixos-hardware.nixosModules.common-cpu-amd
|
||||||
nixos-hardware.nixosModules.common-cpu-amd-pstate
|
nixos-hardware.nixosModules.common-cpu-amd-pstate
|
||||||
nixos-hardware.nixosModules.common-cpu-amd-zenpower
|
# nixos-hardware.nixosModules.common-cpu-amd-zenpower
|
||||||
nixos-hardware.nixosModules.common-gpu-amd
|
nixos-hardware.nixosModules.common-gpu-amd
|
||||||
nixos-hardware.nixosModules.common-hidpi
|
nixos-hardware.nixosModules.common-hidpi
|
||||||
nixos-hardware.nixosModules.common-pc
|
nixos-hardware.nixosModules.common-pc
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
# ######################################################
|
|
||||||
# Pi4 #
|
|
||||||
# ######################################################
|
|
||||||
pi4 = {
|
|
||||||
modules = with inputs; [
|
|
||||||
disko.nixosModules.disko
|
|
||||||
nixos-raspberrypi.nixosModules.raspberry-pi-4.base
|
|
||||||
nixos-raspberrypi.nixosModules.raspberry-pi-4.display-vc4
|
|
||||||
nixos-raspberrypi.lib.inject-overlays
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
# ######################################################
|
# ######################################################
|
||||||
# Pi5 #
|
# Pi5 #
|
||||||
# ######################################################
|
# ######################################################
|
||||||
pi5 = {
|
pi5 = {
|
||||||
modules = with inputs; [
|
modules = with inputs; [
|
||||||
disko.nixosModules.disko
|
disko.nixosModules.disko
|
||||||
nixos-raspberrypi.nixosModules.raspberry-pi-5.base
|
|
||||||
nixos-raspberrypi.nixosModules.raspberry-pi-5.display-vc4
|
|
||||||
nixos-raspberrypi.nixosModules.raspberry-pi-5.bluetooth
|
|
||||||
nixos-raspberrypi.lib.inject-overlays
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -209,33 +228,24 @@
|
|||||||
macbook-pro-nixos = {
|
macbook-pro-nixos = {
|
||||||
modules = with inputs; [
|
modules = with inputs; [
|
||||||
nixos-apple-silicon.nixosModules.default
|
nixos-apple-silicon.nixosModules.default
|
||||||
|
lsfg-vk.nixosModules.default
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
overlays = with inputs; [ nix-vscode-extensions.overlays.default ];
|
# ######################################################
|
||||||
|
# AllyX #
|
||||||
homes = {
|
# ######################################################
|
||||||
modules = with inputs; [
|
allyx = {
|
||||||
nix-index-database.homeModules.nix-index
|
modules = with inputs; [
|
||||||
sops-nix.homeManagerModules.sops
|
nixos-hardware.nixosModules.common-cpu-amd
|
||||||
];
|
nixos-hardware.nixosModules.common-cpu-amd-pstate
|
||||||
|
# nixos-hardware.nixosModules.common-cpu-amd-zenpower
|
||||||
overlays = with inputs; [
|
nixos-hardware.nixosModules.common-gpu-amd
|
||||||
nix-vscode-extensions.overlays.default
|
nixos-hardware.nixosModules.common-hidpi
|
||||||
];
|
nixos-hardware.nixosModules.common-pc
|
||||||
|
lsfg-vk.nixosModules.default
|
||||||
users = {
|
jovian.nixosModules.jovian
|
||||||
# "matt@desktop" = {
|
];
|
||||||
# modules = with inputs; [
|
|
||||||
# sops-nix.homeManagerModules.sops
|
|
||||||
# ];
|
|
||||||
# };
|
|
||||||
"deck@deck" = {
|
|
||||||
modules = with inputs; [
|
|
||||||
steam-rom-manager.homeManagerModules.default
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -248,20 +258,33 @@
|
|||||||
|
|
||||||
# Add flake metadata that can be processed by tools like Snowfall Frost.
|
# Add flake metadata that can be processed by tools like Snowfall Frost.
|
||||||
meta = {
|
meta = {
|
||||||
# A slug to use in documentation when displaying things like file paths.
|
# A slug to use in documentation when displaying things like file paths.
|
||||||
name = "mjallen";
|
name = "mjallen";
|
||||||
|
|
||||||
# A title to show for your flake, typically the name.
|
# A title to show for your flake, typically the name.
|
||||||
title = "mjallen Flake";
|
title = "mjallen Flake";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
channels-config = {
|
||||||
|
allowUnfree = true;
|
||||||
|
allowUnsupportedSystem = true;
|
||||||
|
permittedInsecurePackages = [
|
||||||
|
# ...
|
||||||
|
# "libsoup-2.74.3"
|
||||||
|
# "mbedtls-2.28.10"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
outputs-builder = channels: {
|
outputs-builder = channels: {
|
||||||
formatter = inputs.treefmt-nix.lib.mkWrapper channels.nixpkgs ./treefmt.nix;
|
formatter = inputs.treefmt-nix.lib.mkWrapper channels.nixpkgs ./treefmt.nix;
|
||||||
|
|
||||||
|
# Add mjallen-lib to the flake outputs
|
||||||
|
overlays = {
|
||||||
|
mjallen-lib = _final: _prev: {
|
||||||
|
mjallen-lib = (import ./lib { inherit inputs; }).mjallen-lib;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
in
|
}
|
||||||
snowfall // {
|
|
||||||
nixosConfigurations = snowfall.nixosConfigurations;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
{ lib, pkgs, home, ... }:
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
|
inherit (lib.${namespace}) enabled disabled;
|
||||||
shellAliases = {
|
shellAliases = {
|
||||||
update-switch = "darwin-rebuild switch --flake ~/nix-config";
|
update-switch = "darwin-rebuild switch --flake ~/nix-config";
|
||||||
update-flake = "nix flake update ~/nix-config";
|
update-flake = "nix flake update ~/nix-config";
|
||||||
@@ -9,20 +15,17 @@ let
|
|||||||
age
|
age
|
||||||
cpufetch
|
cpufetch
|
||||||
deadnix
|
deadnix
|
||||||
direnv
|
iproute2mac
|
||||||
nixfmt-rfc-style
|
nebula
|
||||||
|
nixfmt
|
||||||
|
nodePackages.nodejs
|
||||||
|
uv
|
||||||
sops
|
sops
|
||||||
tree
|
tree
|
||||||
wget
|
wget
|
||||||
];
|
];
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# imports = [
|
|
||||||
# ../../modules/home/defaults.nix
|
|
||||||
# ../../modules/home/git.nix
|
|
||||||
# ../../modules/home/shell.nix
|
|
||||||
# ../../modules/home/vscode.nix
|
|
||||||
# ];
|
|
||||||
# Home Manager needs a bit of information about you and the
|
# Home Manager needs a bit of information about you and the
|
||||||
# paths it should manage.
|
# paths it should manage.
|
||||||
home = {
|
home = {
|
||||||
@@ -30,7 +33,7 @@ in
|
|||||||
homeDirectory = "/Users/mattjallen";
|
homeDirectory = "/Users/mattjallen";
|
||||||
packages = lib.mkForce packages;
|
packages = lib.mkForce packages;
|
||||||
sessionVariables = {
|
sessionVariables = {
|
||||||
NH_DARWIN_FLAKE = "${home.homeDirectory}/nix-config#mac";
|
NH_DARWIN_FLAKE = lib.mkForce "/Users/mattjallen/nix-config";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -40,20 +43,238 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# programs.nix-plist-manager = {
|
||||||
|
# enable = true;
|
||||||
|
# options = {
|
||||||
|
# applications = {
|
||||||
|
# finder = {
|
||||||
|
# settings = {
|
||||||
|
# general = {
|
||||||
|
# showTheseItemsOnTheDesktop = {
|
||||||
|
# hardDisks = false;
|
||||||
|
# externalDisks = true;
|
||||||
|
# cdsDvdsAndiPods = false;
|
||||||
|
# connectedServers = false;
|
||||||
|
# };
|
||||||
|
# openFoldersInTabsInsteadOfNewWindows = true;
|
||||||
|
# };
|
||||||
|
# sidebar = {
|
||||||
|
# recentTags = true;
|
||||||
|
# };
|
||||||
|
# advanced = {
|
||||||
|
# removeItemsFromTheTrashAfter30Days = true;
|
||||||
|
# showAllFilenameExtensions = true;
|
||||||
|
# showWarningBeforeChangingAnExtension = true;
|
||||||
|
# showWarningBeforeRemovingFromiCloudDrive = true;
|
||||||
|
# showWarningBeforeEmptyingTheTrash = true;
|
||||||
|
# keepFoldersOnTop = {
|
||||||
|
# inWindowsWhenSortingByName = true;
|
||||||
|
# onDesktop = true;
|
||||||
|
# };
|
||||||
|
# whenPerformingASearch = "Search This Mac";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# menuBar = {
|
||||||
|
# view = {
|
||||||
|
# showTabBar = true;
|
||||||
|
# showSidebar = true;
|
||||||
|
# showPathBar = true;
|
||||||
|
# showStatusBar = true;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# systemSettings = {
|
||||||
|
# appearance = {
|
||||||
|
# appearance = "Dark";
|
||||||
|
# accentColor = "Multicolor";
|
||||||
|
# # clickInTheScrollBarTo = "Jump to the next page";
|
||||||
|
# sidebarIconSize = "Medium";
|
||||||
|
# showScrollBars = "When scrolling";
|
||||||
|
# };
|
||||||
|
# controlCenter = {
|
||||||
|
# wifi = true;
|
||||||
|
# bluetooth = true;
|
||||||
|
# airdrop = true;
|
||||||
|
# stageManager = true;
|
||||||
|
# focusModes = "active";
|
||||||
|
# screenMirroring = "active";
|
||||||
|
# display = "never";
|
||||||
|
# sound = "always";
|
||||||
|
# nowPlaying = "active";
|
||||||
|
# accessibilityShortcuts = "unset";
|
||||||
|
# musicRecognition = {
|
||||||
|
# showInMenuBar = false;
|
||||||
|
# showInControlCenter = true;
|
||||||
|
# };
|
||||||
|
# hearing = "unset";
|
||||||
|
# fastUserSwitching = {
|
||||||
|
# showInMenuBar = false;
|
||||||
|
# showInControlCenter = true;
|
||||||
|
# };
|
||||||
|
# keyboardBrightness = {
|
||||||
|
# showInMenuBar = false;
|
||||||
|
# showInControlCenter = true;
|
||||||
|
# };
|
||||||
|
# battery = {
|
||||||
|
# showInMenuBar = false;
|
||||||
|
# showInControlCenter = false;
|
||||||
|
# };
|
||||||
|
# batteryShowPercentage = true;
|
||||||
|
# # menuBarOnly = {
|
||||||
|
# # spotlight = false;
|
||||||
|
# # siri = true;
|
||||||
|
# # };
|
||||||
|
# # automaticallyHideAndShowTheMenuBar = "In Full Screen Only";
|
||||||
|
# };
|
||||||
|
# desktopAndDock = {
|
||||||
|
# desktopAndStageManager = {
|
||||||
|
# showItems = {
|
||||||
|
# onDesktop = true;
|
||||||
|
# inStageManager = true;
|
||||||
|
# };
|
||||||
|
# clickWallpaperToRevealDesktop = "Always";
|
||||||
|
# stageManager = false;
|
||||||
|
# showRecentAppsInStageManager = true;
|
||||||
|
# showWindowsFromAnApplication = "All at Once";
|
||||||
|
# };
|
||||||
|
# dock = {
|
||||||
|
# animateOpeningApplications = true;
|
||||||
|
# automaticallyHideAndShowTheDock = enabled;
|
||||||
|
# doubleClickAWindowsTitleBarTo = "Minimize";
|
||||||
|
# magnification = disabled;
|
||||||
|
# minimizeWindowsIntoApplicationIcon = true;
|
||||||
|
# minimizeWindowsUsing = "Genie Effect";
|
||||||
|
# positionOnScreen = "Bottom";
|
||||||
|
# showIndicatorsForOpenApplications = true;
|
||||||
|
# showSuggestedAndRecentAppsInDock = false;
|
||||||
|
# size = 64; # 16 - 128
|
||||||
|
# # persistentApps = [
|
||||||
|
# # { app = "/Applications/Clock.app"; }
|
||||||
|
# # { folder = "/Applications"; }
|
||||||
|
# # { app = "/Applications/Safari.app"; }
|
||||||
|
# # { app = "/Applications/Firefox.app"; }
|
||||||
|
# # { app = "/Applications/Tabby.app"; }
|
||||||
|
# # { app = "/Applications/Termius.app"; }
|
||||||
|
# # { app = "/Applications/Muic.app"; }
|
||||||
|
# # { app = "/Applications/Vesktop.app"; }
|
||||||
|
# # { app = "/Applications/Messages.app"; }
|
||||||
|
# # { app = "/Applications/Calendar.app"; }
|
||||||
|
# # { app = "/Applications/Reminders.app"; }
|
||||||
|
# # { app = "/Applications/Notes.app"; }
|
||||||
|
# # { app = "/Applications/Weather.app"; }
|
||||||
|
# # { app = "/Applications/Maps.app"; }
|
||||||
|
# # { app = "/Applications/App Store.app"; }
|
||||||
|
# # { app = "/Applications/System Settings.app"; }
|
||||||
|
# # { app = "/Applications/ChatGPT.app"; }
|
||||||
|
# # { app = "/Applications/Nextcloud.app"; }
|
||||||
|
# # { app = "/Applications/VSCodium.app"; }
|
||||||
|
# # { app = "/Applications/Omnissa Horizon Client.app"; }
|
||||||
|
# # { app = "/Applications/Proton Pass.app"; }
|
||||||
|
# # { app = "/Applications/OrcaSlicer.app"; }
|
||||||
|
# # { app = "/Applications/AlDente.app"; }
|
||||||
|
# # ];
|
||||||
|
# # persistentOthers = [
|
||||||
|
# # "~/Downloads"
|
||||||
|
# # ];
|
||||||
|
# };
|
||||||
|
# hotCorners = {
|
||||||
|
# # ["-" "Mission Control" "Application Windows" "Desktop" "Start Screen Saver" "Disable Screen Saver" "Dashboard" "Put Display to Sleep" "Launchpad" "Notification Center" "Lock Screen" "Quick Note"]
|
||||||
|
# topLeft = "-";
|
||||||
|
# topRight = "-";
|
||||||
|
# bottomLeft = "-";
|
||||||
|
# bottomRight = "-";
|
||||||
|
# };
|
||||||
|
# missionControl = {
|
||||||
|
# automaticallyRearrangeSpacesBasedOnMostRecentUse = true;
|
||||||
|
# displaysHaveSeparateSpaces = true;
|
||||||
|
# dragWindowsToTopOfScreenToEnterMissionControl = true;
|
||||||
|
# groupWindowsByApplication = true;
|
||||||
|
# whenSwitchingToAnApplicationSwitchToAspaceWithOpenWindowsForTheApplication = true;
|
||||||
|
# };
|
||||||
|
# widgets = {
|
||||||
|
# showWidgets = {
|
||||||
|
# onDesktop = true;
|
||||||
|
# inStageManager = true;
|
||||||
|
# };
|
||||||
|
# widgetStyle = "Automatic";
|
||||||
|
# useIphoneWidgets = true;
|
||||||
|
# };
|
||||||
|
# windows = {
|
||||||
|
# askToKeepChangesWhenClosingDocuments = true;
|
||||||
|
# closeWindowsWhenQuittingAnApplication = true;
|
||||||
|
# dragWindowsToScreenEdgesToTile = true;
|
||||||
|
# dragWindowsToMenuBarToFillScreen = true;
|
||||||
|
# holdOptionKeyWhileDraggingWindowsToTile = true;
|
||||||
|
# preferTabsWhenOpeningDocuments = "In Full Screen";
|
||||||
|
# tiledWindowsHaveMargin = false;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# focus = {
|
||||||
|
# shareAcrossDevices = true;
|
||||||
|
# };
|
||||||
|
# # general.dateAndTime."24HourTime" = false;
|
||||||
|
# notifications = {
|
||||||
|
# notificationCenter = {
|
||||||
|
# showPreviews = "When Unlocked";
|
||||||
|
# summarizeNotifications = true;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# sound = {
|
||||||
|
# soundEffects = {
|
||||||
|
# alertSound = "Boop";
|
||||||
|
# alertVolume = 0.7;
|
||||||
|
# playFeedbackWhenVolumeIsChanged = true;
|
||||||
|
# playUserInterfaceSoundEffects = true;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# spotlight = {
|
||||||
|
# helpAppleImproveSearch = false;
|
||||||
|
# # searchResults = {
|
||||||
|
# # applications = true;
|
||||||
|
# # calculator = true;
|
||||||
|
# # contacts = true;
|
||||||
|
# # conversion = true;
|
||||||
|
# # definition = true;
|
||||||
|
# # developer = true;
|
||||||
|
# # documents = true;
|
||||||
|
# # eventsAndReminders = true;
|
||||||
|
# # folders = true;
|
||||||
|
# # fonts = false;
|
||||||
|
# # images = true;
|
||||||
|
# # mailAndMessages = true;
|
||||||
|
# # movies = true;
|
||||||
|
# # music = true;
|
||||||
|
# # other = false;
|
||||||
|
# # pdfDocuments = true;
|
||||||
|
# # presentations = true;
|
||||||
|
# # siriSuggestions = false;
|
||||||
|
# # systemSettings = true;
|
||||||
|
# # tips = false;
|
||||||
|
# # websites = true;
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
|
||||||
# Manage bug in compilations - who uses manpages in 2024 anyways? :P
|
# Manage bug in compilations - who uses manpages in 2024 anyways? :P
|
||||||
manual.manpages.enable = false;
|
manual.manpages = enabled;
|
||||||
|
|
||||||
# Override defaults that arent supported
|
# Override defaults that arent supported
|
||||||
programs = {
|
programs = {
|
||||||
mangohud.enable = lib.mkForce false;
|
mangohud = lib.mkForce disabled;
|
||||||
|
|
||||||
nh = {
|
nh = {
|
||||||
flake = "${home.homeDirectory}/nix-config";
|
flake = lib.mkForce "/Users/mattjallen/nix-config";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
pass-secret-service.enable = lib.mkForce false;
|
pass-secret-service = lib.mkForce disabled;
|
||||||
nextcloud-client.enable = lib.mkForce false;
|
nextcloud-client = lib.mkForce disabled;
|
||||||
|
kdeconnect = {
|
||||||
|
enable = false;
|
||||||
|
indicator = false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
{ pkgs, lib, ... }:
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
theme = import (lib.snowfall.fs.get-file "modules/home/desktop/theme/nord.nix");
|
inherit (lib.${namespace}) enabled disabled;
|
||||||
shellAliases = {
|
|
||||||
update-boot = "sudo nixos-rebuild boot --max-jobs 10 --build-host admin@10.0.1.3";
|
|
||||||
update-switch = "sudo nixos-rebuild switch --max-jobs 10 --build-host admin@10.0.1.3";
|
|
||||||
update-flake = "nix flake update mac-nixpkgs mac-nixos-apple-silicon mac-home-manager mac-impermanence mac-sops-nix --flake /etc/nixos";
|
|
||||||
update-nas = "nixos-rebuild switch --use-remote-sudo --target-host admin@10.0.1.3 --build-host admin@10.0.1.3 --flake ~/nix-config#jallen-nas";
|
|
||||||
};
|
|
||||||
fontName = "JetBrainsMono NFM";
|
|
||||||
fontPackage = pkgs.nerd-fonts.jetbrains-mono;
|
|
||||||
# Displays
|
# Displays
|
||||||
display = {
|
display = {
|
||||||
input = "eDP-1";
|
input = "eDP-1";
|
||||||
@@ -22,17 +19,30 @@ in
|
|||||||
home.homeDirectory = "/home/matt";
|
home.homeDirectory = "/home/matt";
|
||||||
home.stateVersion = "23.11";
|
home.stateVersion = "23.11";
|
||||||
|
|
||||||
mjallen = {
|
${namespace} = {
|
||||||
desktop.hyprland = {
|
desktop.gnome = enabled;
|
||||||
enable = true;
|
programs.hyprland = {
|
||||||
|
enable = false;
|
||||||
primaryDisplay = "eDP-1";
|
primaryDisplay = "eDP-1";
|
||||||
|
debug.disableScaleChecks = true;
|
||||||
|
|
||||||
wallpaper = [
|
monitorv2 = [
|
||||||
"${display.input}, /run/wallpaper.jpg"
|
{
|
||||||
];
|
name = display.input;
|
||||||
|
mode = "${display.resolution}@${display.refreshRate}";
|
||||||
monitor = [
|
position = "0x0";
|
||||||
"${display.input},${display.resolution}@${display.refreshRate},0x0,1.25,bitdepth,10,cm,hdr,sdrbrightness,1.2,sdrsaturation,0.98"
|
scale = 1.25;
|
||||||
|
extra = [
|
||||||
|
"bitdepth"
|
||||||
|
"10"
|
||||||
|
"cm"
|
||||||
|
"hdr"
|
||||||
|
"sdrbrightness"
|
||||||
|
"1.2"
|
||||||
|
"sdrsaturation"
|
||||||
|
"0.98"
|
||||||
|
];
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
workspace = [
|
workspace = [
|
||||||
@@ -41,61 +51,54 @@ in
|
|||||||
"name:steam, monitor:${display.input}, default:false, special, class:(.*[Ss]team.*)"
|
"name:steam, monitor:${display.input}, default:false, special, class:(.*[Ss]team.*)"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
windowRule = [
|
windowRule = [
|
||||||
"size 2160 3356, tag:horizonrdp"
|
# "size 2160 3356, tag:horizonrdp"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
hyprpaper = {
|
||||||
|
wallpaperPath = "/run/wallpaper.jpg";
|
||||||
|
};
|
||||||
|
|
||||||
|
keybinds = {
|
||||||
|
bind = [
|
||||||
|
"$mod, A, exec, chromium --app=\"https://music.apple.com\""
|
||||||
|
|
||||||
|
"SHIFT, XF86MonBrightnessUp, exec, lightctl -D kbd_backlight up"
|
||||||
|
"SHIFT, XF86MonBrightnessDown, exec, lightctl -D kbd_backlight down"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
defaultApps = {
|
defaultApps = {
|
||||||
browser = pkgs.firefox;
|
browser = pkgs.firefox;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extraConfig = ''
|
||||||
|
exec-once = brightnessctl -d kbd_backlight s 50%
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
programs = {
|
programs = {
|
||||||
btop.enable = true;
|
btop = enabled;
|
||||||
kitty = {
|
kitty = disabled;
|
||||||
enable = true;
|
mako = disabled;
|
||||||
font = {
|
nwg-dock = disabled;
|
||||||
name = fontName;
|
nwg-drawer = disabled;
|
||||||
package = fontPackage;
|
nwg-panel = disabled;
|
||||||
};
|
|
||||||
};
|
|
||||||
mako = {
|
|
||||||
enable = true;
|
|
||||||
fontName = fontName;
|
|
||||||
};
|
|
||||||
nwg-dock.enable = true;
|
|
||||||
nwg-drawer.enable = true;
|
|
||||||
nwg-panel = {
|
|
||||||
enable = true;
|
|
||||||
defaultApps = {
|
|
||||||
browser = pkgs.firefox;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
waybar = {
|
waybar = {
|
||||||
enable = true;
|
enable = false;
|
||||||
|
|
||||||
layer = "bottom";
|
layer = "bottom";
|
||||||
|
|
||||||
modules-right = [
|
temperature = {
|
||||||
"tray"
|
cpu = enabled;
|
||||||
"temperature"
|
gpu = enabled;
|
||||||
"temperature#gpu"
|
};
|
||||||
"keyboard-state#capslock"
|
|
||||||
"keyboard-state#numlock"
|
|
||||||
"wireplumber#sink"
|
|
||||||
"bluetooth"
|
|
||||||
"network"
|
|
||||||
"idle_inhibitor"
|
|
||||||
"clock"
|
|
||||||
"battery"
|
|
||||||
"custom/weather"
|
|
||||||
];
|
|
||||||
|
|
||||||
extraModules = {
|
extraModules = {
|
||||||
"custom/lights" = {
|
"custom/lights" = {
|
||||||
tooltip = false;
|
tooltip = false;
|
||||||
exec = "waybar-hass --get_light light.living_room_lights";
|
exec = "waybar-hass --get_light light.living_room_lights";
|
||||||
interval = "once";
|
interval = "once";
|
||||||
format = "{text}";#"";
|
format = "{text}"; # "";
|
||||||
on-click = "waybar-hass --toggle_light light.living_room_lights";
|
on-click = "waybar-hass --toggle_light light.living_room_lights";
|
||||||
return-type = "json";
|
return-type = "json";
|
||||||
};
|
};
|
||||||
@@ -103,32 +106,70 @@ in
|
|||||||
|
|
||||||
extraModulesStyle = ''
|
extraModulesStyle = ''
|
||||||
#custom-lights {
|
#custom-lights {
|
||||||
color: ${theme.frost.nord8};
|
color: @base0C;
|
||||||
background-color: ${theme.polarNight.nord0};
|
opacity: 0.85;
|
||||||
${theme.defaultOpacity}
|
background-color: @base00;
|
||||||
${theme.borderLeft}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#custom-lights:hover {
|
#custom-lights:hover {
|
||||||
background: ${theme.polarNight.nord3};
|
background: @base03;
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
windowOffset = 75;
|
||||||
};
|
};
|
||||||
wlogout.enable = true;
|
wlogout = disabled;
|
||||||
wofi.enable = true;
|
wofi = disabled;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
home.packages = with pkgs; [
|
home.packages =
|
||||||
iw
|
with pkgs.${namespace};
|
||||||
iwd
|
[
|
||||||
orca-slicer
|
# librepods
|
||||||
vscodium
|
librepods-beta
|
||||||
];
|
]
|
||||||
|
++ (with pkgs; [
|
||||||
|
bolt-launcher
|
||||||
|
iw
|
||||||
|
iwd
|
||||||
|
orca-slicer
|
||||||
|
vscodium
|
||||||
|
|
||||||
|
gnomeExtensions.notch-clock-offset
|
||||||
|
]);
|
||||||
|
|
||||||
|
services = {
|
||||||
|
kdeconnect = {
|
||||||
|
enable = lib.mkForce true;
|
||||||
|
indicator = lib.mkForce true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
programs = {
|
programs = {
|
||||||
password-store.enable = true;
|
password-store = enabled;
|
||||||
|
};
|
||||||
|
|
||||||
zsh.shellAliases = shellAliases;
|
dconf = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0".name = "Keyboard Backlight +";
|
||||||
|
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0".binding = "<Super>MonBrightnessUp";
|
||||||
|
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0".command = "brightnessctl -d kbd_backlight s +10";
|
||||||
|
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1".name = "Keyboard Backlight -";
|
||||||
|
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1".binding = "<Super>MonBrightnessDown";
|
||||||
|
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1".command = "brightnessctl -d kbd_backlight s 10-";
|
||||||
|
|
||||||
|
"org/gnome/shell".enabled-extensions = [
|
||||||
|
"notch-clock-offset@christophbrill.de"
|
||||||
|
];
|
||||||
|
|
||||||
|
"org/gnome/shell/extensions/notch-clock-offset".percent = 40;
|
||||||
|
|
||||||
|
"org/gnome/settings-daemon/plugins/media-keys".custom-keybindings = [
|
||||||
|
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/"
|
||||||
|
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/"
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
{ lib, ... }:
|
|
||||||
let
|
|
||||||
shellAliases = {
|
|
||||||
ll = "ls -alh";
|
|
||||||
update-boot = "sudo nixos-rebuild boot --max-jobs 10 --build-host admin@10.0.1.3";
|
|
||||||
update-switch = "sudo nixos-rebuild switch --max-jobs 10 --build-host admin@10.0.1.3";
|
|
||||||
update-flake = "nix flake update pi4-nixpkgs pi4-home-manager pi4-impermanence pi4-sops-nix pi4-nixos-hardware pi4-nixos-raspberrypi pi4-disko --flake /etc/nixos";
|
|
||||||
update-nas = "nixos-rebuild switch --use-remote-sudo --target-host admin@10.0.1.3 --build-host admin@10.0.1.3 --flake ~/nix-config#jallen-nas";
|
|
||||||
nas-ssh = "kitten ssh admin@10.0.1.3";
|
|
||||||
ducks = "du -cksh * | sort -hr | head -n 15";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
../../../modules/home/home
|
|
||||||
../../../modules/home/programs/git
|
|
||||||
../../../modules/home/programs/zsh
|
|
||||||
];
|
|
||||||
|
|
||||||
home.username = "matt";
|
|
||||||
|
|
||||||
sops = {
|
|
||||||
age.keyFile = "/home/matt/.config/sops/age/keys.txt";
|
|
||||||
defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
|
|
||||||
validateSopsFiles = false;
|
|
||||||
secrets = {
|
|
||||||
"ssh-keys-public/pi4" = {
|
|
||||||
path = "/home/matt/.ssh/id_ed25519.pub";
|
|
||||||
mode = "0644";
|
|
||||||
};
|
|
||||||
"ssh-keys-private/pi4" = {
|
|
||||||
path = "/home/matt/.ssh/id_ed25519";
|
|
||||||
mode = "0600";
|
|
||||||
};
|
|
||||||
# "ssh-keys-public/desktop-nixos" = {
|
|
||||||
# path = "/home/matt/.ssh/authorized_keys";
|
|
||||||
# mode = "0600";
|
|
||||||
# };
|
|
||||||
|
|
||||||
# "ssh-keys-public/desktop-nixos-root" = {
|
|
||||||
# path = "/home/matt/.ssh/authorized_keys2";
|
|
||||||
# mode = "0600";
|
|
||||||
# };
|
|
||||||
|
|
||||||
# "ssh-keys-public/desktop-windows" = {
|
|
||||||
# path = "/home/matt/.ssh/authorized_keys3";
|
|
||||||
# mode = "0600";
|
|
||||||
# };
|
|
||||||
|
|
||||||
# "ssh-keys-public/macbook-macos" = {
|
|
||||||
# path = "/home/matt/.ssh/authorized_keys4";
|
|
||||||
# mode = "0600";
|
|
||||||
# };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
programs = {
|
|
||||||
mangohud.enable = lib.mkForce true;
|
|
||||||
zsh.shellAliases = shellAliases;
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
|
||||||
nextcloud-client.enable = lib.mkForce true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
{ pkgs, lib, config, namespace, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
shellAliases = {
|
inherit (lib.${namespace}) disabled;
|
||||||
update-boot = "sudo nixos-rebuild boot --max-jobs 10 --build-host admin@10.0.1.3";
|
|
||||||
update-switch = "sudo nixos-rebuild switch --max-jobs 10 --build-host admin@10.0.1.3";
|
|
||||||
update-flake = "nix flake update pi5-nixpkgs pi5-home-manager pi5-impermanence pi5-nixos-hardware pi5-sops-nix nixos-raspberrypi --flake /etc/nixos";
|
|
||||||
update-nas = "nixos-rebuild switch --use-remote-sudo --target-host admin@10.0.1.3 --build-host admin@10.0.1.3 --flake ~/nix-config#jallen-nas";
|
|
||||||
nas-ssh = "kitten ssh admin@10.0.1.3";
|
|
||||||
};
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -51,7 +50,11 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
programs = {
|
services = {
|
||||||
zsh.shellAliases = shellAliases;
|
nextcloud-client = lib.mkForce disabled;
|
||||||
|
kdeconnect = {
|
||||||
|
enable = false;
|
||||||
|
indicator = false;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
18
homes/aarch64-linux/root@macbook-pro-nixos/default.nix
Normal file
18
homes/aarch64-linux/root@macbook-pro-nixos/default.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}) disabled;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.username = "root";
|
||||||
|
services = {
|
||||||
|
nextcloud-client = lib.mkForce disabled;
|
||||||
|
kdeconnect = {
|
||||||
|
enable = false;
|
||||||
|
indicator = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{ config, lib, ... }:
|
|
||||||
let
|
|
||||||
shellAliases = {
|
|
||||||
update-boot = "nixos-rebuild boot --max-jobs 10";
|
|
||||||
update-switch = "nixos-rebuild switch --max-jobs 10";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
home = {
|
|
||||||
username = "root";
|
|
||||||
homeDirectory = lib.mkForce "/${config.home.username}";
|
|
||||||
enableNixpkgsReleaseCheck = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
programs = {
|
|
||||||
zsh.shellAliases = shellAliases;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
18
homes/aarch64-linux/root@pi5/default.nix
Normal file
18
homes/aarch64-linux/root@pi5/default.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}) disabled;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.username = "root";
|
||||||
|
services = {
|
||||||
|
nextcloud-client = lib.mkForce disabled;
|
||||||
|
kdeconnect = {
|
||||||
|
enable = false;
|
||||||
|
indicator = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
175
homes/x86_64-linux/admin@jallen-nas/default.nix
Executable file
175
homes/x86_64-linux/admin@jallen-nas/default.nix
Executable file
@@ -0,0 +1,175 @@
|
|||||||
|
{ pkgs, namespace, ... }:
|
||||||
|
{
|
||||||
|
home = {
|
||||||
|
username = "admin";
|
||||||
|
packages =
|
||||||
|
with pkgs;
|
||||||
|
[
|
||||||
|
heroic
|
||||||
|
python3
|
||||||
|
python3Packages.requests
|
||||||
|
python3Packages.mcp
|
||||||
|
jq
|
||||||
|
]
|
||||||
|
++ (with pkgs.${namespace}; [
|
||||||
|
moondeck-buddy
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
${namespace} = {
|
||||||
|
sops.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
sops = {
|
||||||
|
age.keyFile = "/home/admin/.config/sops/age/keys.txt";
|
||||||
|
defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
|
||||||
|
validateSopsFiles = false;
|
||||||
|
secrets = {
|
||||||
|
"ssh-keys-public/jallen-nas" = {
|
||||||
|
path = "/home/admin/.ssh/id_ed25519.pub";
|
||||||
|
mode = "0644";
|
||||||
|
};
|
||||||
|
"ssh-keys-private/jallen-nas" = {
|
||||||
|
path = "/home/admin/.ssh/id_ed25519";
|
||||||
|
mode = "0600";
|
||||||
|
};
|
||||||
|
"ssh-keys-public/desktop-nixos" = {
|
||||||
|
path = "/home/admin/.ssh/authorized_keys";
|
||||||
|
mode = "0600";
|
||||||
|
};
|
||||||
|
|
||||||
|
"ssh-keys-public/desktop-nixos-root" = {
|
||||||
|
path = "/home/admin/.ssh/authorized_keys2";
|
||||||
|
mode = "0600";
|
||||||
|
};
|
||||||
|
|
||||||
|
"ssh-keys-public/desktop-windows" = {
|
||||||
|
path = "/home/admin/.ssh/authorized_keys3";
|
||||||
|
mode = "0600";
|
||||||
|
};
|
||||||
|
|
||||||
|
"ssh-keys-public/macbook-macos" = {
|
||||||
|
path = "/home/admin/.ssh/authorized_keys4";
|
||||||
|
mode = "0600";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
programs = {
|
||||||
|
bash = {
|
||||||
|
shellAliases = {
|
||||||
|
"llama-status" =
|
||||||
|
"curl -s http://localhost:8127/health 2>/dev/null && echo 'LLaMA.cpp server is running' || echo 'LLaMA.cpp server is not responding'";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
neovim = {
|
||||||
|
enable = true;
|
||||||
|
viAlias = true;
|
||||||
|
vimAlias = true;
|
||||||
|
defaultEditor = true;
|
||||||
|
plugins = [
|
||||||
|
pkgs.vimPlugins.nvim-tree-lua
|
||||||
|
{
|
||||||
|
plugin = pkgs.vimPlugins.vim-startify;
|
||||||
|
config = "let g:startify_change_to_vcs_root = 0";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
steam-rom-manager = {
|
||||||
|
enable = true;
|
||||||
|
steamUsername = "mjallen18";
|
||||||
|
|
||||||
|
# Optional: override default paths if needed
|
||||||
|
environmentVariables = {
|
||||||
|
romsDirectory = "/home/admin/Emulation/roms";
|
||||||
|
steamDirectory = "/home/admin/.local/share/Steam";
|
||||||
|
};
|
||||||
|
|
||||||
|
emulators = {
|
||||||
|
"Non-SRM Shortcuts" = {
|
||||||
|
enable = true;
|
||||||
|
parserType = "Non-SRM Shortcuts";
|
||||||
|
extraArgs = "";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
opencode = {
|
||||||
|
enable = true;
|
||||||
|
enableMcpIntegration = true;
|
||||||
|
settings = {
|
||||||
|
provider = {
|
||||||
|
nas = {
|
||||||
|
npm = "@ai-sdk/openai-compatible";
|
||||||
|
name = "llama-server (local)";
|
||||||
|
options = {
|
||||||
|
baseURL = "http://jallen-nas.local:8127/v1";
|
||||||
|
};
|
||||||
|
models = {
|
||||||
|
Qwen3-Coder-Next-Q4_0 = {
|
||||||
|
name = "Qwen3 Coder (local)";
|
||||||
|
modalities = {
|
||||||
|
input = [
|
||||||
|
"image"
|
||||||
|
"text"
|
||||||
|
];
|
||||||
|
output = [ "text" ];
|
||||||
|
};
|
||||||
|
limit = {
|
||||||
|
context = 262144;
|
||||||
|
output = 262144;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# "GLM-4.7-Flash-REAP-23B-A3B-UD-Q3_K_XL": {
|
||||||
|
# "name": "GLM 4.7 Flash (local)",
|
||||||
|
# "modalities": { "input": ["image", "text"], "output": ["text"] },
|
||||||
|
# "limit": {
|
||||||
|
# "context": 262144,
|
||||||
|
# "output": 262144
|
||||||
|
# }
|
||||||
|
# };
|
||||||
|
# "Nemotron-3-Nano-30B-A3B-IQ4_XS": {
|
||||||
|
# "name": "Nemotron-3-Nano (local)",
|
||||||
|
# "modalities": { "input": ["image", "text"], "output": ["text"] },
|
||||||
|
# "limit": {
|
||||||
|
# "context": 262144,
|
||||||
|
# "output": 262144
|
||||||
|
# }
|
||||||
|
# };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mcp = {
|
||||||
|
enable = true;
|
||||||
|
servers = {
|
||||||
|
nixos = {
|
||||||
|
command = "nix";
|
||||||
|
args = [
|
||||||
|
"run"
|
||||||
|
"github:utensils/mcp-nixos"
|
||||||
|
"--"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
hass-mcp = {
|
||||||
|
command = "uvx";
|
||||||
|
args = [ "hass-mcp" ];
|
||||||
|
env = {
|
||||||
|
HA_URL = "http://nuc-nixos.local:8123";
|
||||||
|
HA_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI1ZDM2MTliNWNjMGY0ZGI2OWQzOTQ4Mjk0ZDFmNjAxMCIsImlhdCI6MTc3MDc2MjA1NywiZXhwIjoyMDg2MTIyMDU3fQ.P52jeX8GQcdGdzpbU3NCWZMUjkJZHFnOeR8--jy9dF8";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
mcp-server-code-runner = {
|
||||||
|
command = "npm";
|
||||||
|
args = [
|
||||||
|
"-y"
|
||||||
|
"mcp-server-code-runner@latest"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
let
|
|
||||||
shellAliases = {
|
|
||||||
update-boot = "sudo nixos-rebuild boot --max-jobs 10";
|
|
||||||
update-switch = "sudo nixos-rebuild switch --max-jobs 10";
|
|
||||||
update-flake = "nix flake update nas-nixpkgs nas-authentik-nix nas-cosmic nas-crowdsec nas-home-manager nas-impermanence nas-lanzaboote nas-nixos-hardware nas-sops-nix --flake /etc/nixos";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
home.username = "admin";
|
|
||||||
|
|
||||||
# mjallen.home.enable = true;
|
|
||||||
|
|
||||||
sops = {
|
|
||||||
age.keyFile = "/home/admin/.config/sops/age/keys.txt";
|
|
||||||
defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
|
|
||||||
validateSopsFiles = false;
|
|
||||||
secrets = {
|
|
||||||
"ssh-keys-public/jallen-nas" = {
|
|
||||||
path = "/home/admin/.ssh/id_ed25519.pub";
|
|
||||||
mode = "0644";
|
|
||||||
};
|
|
||||||
"ssh-keys-private/jallen-nas" = {
|
|
||||||
path = "/home/admin/.ssh/id_ed25519";
|
|
||||||
mode = "0600";
|
|
||||||
};
|
|
||||||
"ssh-keys-public/desktop-nixos" = {
|
|
||||||
path = "/home/admin/.ssh/authorized_keys";
|
|
||||||
mode = "0600";
|
|
||||||
};
|
|
||||||
|
|
||||||
"ssh-keys-public/desktop-nixos-root" = {
|
|
||||||
path = "/home/admin/.ssh/authorized_keys2";
|
|
||||||
mode = "0600";
|
|
||||||
};
|
|
||||||
|
|
||||||
"ssh-keys-public/desktop-windows" = {
|
|
||||||
path = "/home/admin/.ssh/authorized_keys3";
|
|
||||||
mode = "0600";
|
|
||||||
};
|
|
||||||
|
|
||||||
"ssh-keys-public/macbook-macos" = {
|
|
||||||
path = "/home/admin/.ssh/authorized_keys4";
|
|
||||||
mode = "0600";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
programs = {
|
|
||||||
neovim = {
|
|
||||||
enable = true;
|
|
||||||
viAlias = true;
|
|
||||||
vimAlias = true;
|
|
||||||
defaultEditor = true;
|
|
||||||
plugins = [
|
|
||||||
pkgs.vimPlugins.nvim-tree-lua
|
|
||||||
{
|
|
||||||
plugin = pkgs.vimPlugins.vim-startify;
|
|
||||||
config = "let g:startify_change_to_vcs_root = 0";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
zsh.shellAliases = shellAliases;
|
|
||||||
};
|
|
||||||
|
|
||||||
# services.nixai = {
|
|
||||||
# enable = true;
|
|
||||||
# mcp = {
|
|
||||||
# enable = true;
|
|
||||||
# # Optional: custom socket path (uses `$HOME` expansion)
|
|
||||||
# socketPath = "$HOME/.local/share/nixai/mcp.sock";
|
|
||||||
# };
|
|
||||||
# # Optional: integrate with VS Code
|
|
||||||
# vscodeIntegration = true;
|
|
||||||
# };
|
|
||||||
}
|
|
||||||
37
homes/x86_64-linux/admin@nuc-nixos/default.nix
Executable file
37
homes/x86_64-linux/admin@nuc-nixos/default.nix
Executable file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}) disabled;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.username = "admin";
|
||||||
|
|
||||||
|
# Configure systemd user service for protonmail-bridge
|
||||||
|
systemd.user.services.protonmail-bridge = {
|
||||||
|
Service = {
|
||||||
|
Environment = [
|
||||||
|
"GNUPGHOME=/home/admin/.gnupg"
|
||||||
|
"PASSWORD_STORE_DIR=/home/admin/.local/password-store"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
nextcloud-client = lib.mkForce disabled;
|
||||||
|
kdeconnect = {
|
||||||
|
enable = false;
|
||||||
|
indicator = false;
|
||||||
|
};
|
||||||
|
protonmail-bridge = {
|
||||||
|
enable = true;
|
||||||
|
extraPackages = with pkgs; [
|
||||||
|
pass
|
||||||
|
libsecret
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{ pkgs,... }:
|
|
||||||
let
|
|
||||||
shellAliases = {
|
|
||||||
update-boot = "sudo nixos-rebuild boot --max-jobs 10";
|
|
||||||
update-switch = "sudo nixos-rebuild switch --max-jobs 10";
|
|
||||||
update-flake = "nix flake update nas-nixpkgs nas-authentik-nix nas-cosmic nas-crowdsec nas-home-manager nas-impermanence nas-lanzaboote nas-nixos-hardware nas-sops-nix --flake /etc/nixos";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
home.username = "admin";
|
|
||||||
|
|
||||||
programs = {
|
|
||||||
zsh.shellAliases = shellAliases;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
{ pkgs, ... }:
|
|
||||||
let
|
|
||||||
shellAliases = {
|
|
||||||
update-boot = "sudo nixos-rebuild boot --max-jobs 10 --build-host admin@10.0.1.3";
|
|
||||||
update-switch = "sudo nixos-rebuild switch --max-jobs 10";
|
|
||||||
update-flake = "nix flake update steamdeck-nixpkgs steamdeck-chaotic steamdeck-home-manager steamdeck-impermanence steamdeck-jovian steamdeck-lanzaboote steamdeck-nixos-hardware steamdeck-sops-nix steamdeck-steam-rom-manager --flake /etc/nixos";
|
|
||||||
nas-ssh = "ssh admin@10.0.1.3";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
home.username = "deck";
|
|
||||||
|
|
||||||
sops = {
|
|
||||||
age.keyFile = "/home/deck/.config/sops/age/keys.txt";
|
|
||||||
defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
|
|
||||||
validateSopsFiles = false;
|
|
||||||
secrets = {
|
|
||||||
"ssh-keys-public/deck" = {
|
|
||||||
path = "/home/deck/.ssh/id_ed25519.pub";
|
|
||||||
mode = "0644";
|
|
||||||
};
|
|
||||||
"ssh-keys-private/deck" = {
|
|
||||||
path = "/home/deck/.ssh/id_ed25519";
|
|
||||||
mode = "0600";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
programs = {
|
|
||||||
steam-rom-manager = {
|
|
||||||
enable = true;
|
|
||||||
steamUsername = "mjallen18";
|
|
||||||
|
|
||||||
# Optional: override default paths if needed
|
|
||||||
environmentVariables = {
|
|
||||||
romsDirectory = "/home/deck/Emulation/roms";
|
|
||||||
steamDirectory = "/home/deck/.local/share/Steam";
|
|
||||||
};
|
|
||||||
|
|
||||||
emulators = {
|
|
||||||
ryujinx.enable = true;
|
|
||||||
|
|
||||||
dolphin-gamecube = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs.dolphin-emu;
|
|
||||||
romFolder = "gc";
|
|
||||||
fileTypes = [ ".iso" ".ISO" ".gcm" ".GCM" ".ciso" ".CISO" "rvz" ];
|
|
||||||
extraArgs = "-b -e \"\${filePath}\"";
|
|
||||||
};
|
|
||||||
|
|
||||||
pcsx2.enable = true;
|
|
||||||
mgba.enable = true;
|
|
||||||
|
|
||||||
"Non-SRM Shortcuts" = {
|
|
||||||
enable = true;
|
|
||||||
parserType = "Non-SRM Shortcuts";
|
|
||||||
extraArgs = "";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
zsh.shellAliases = shellAliases;
|
|
||||||
};
|
|
||||||
|
|
||||||
home.packages = with pkgs; [
|
|
||||||
dolphin-emu
|
|
||||||
heroic
|
|
||||||
mgba
|
|
||||||
prismlauncher
|
|
||||||
ryujinx-greemdev
|
|
||||||
vmware-horizon-client
|
|
||||||
];
|
|
||||||
}
|
|
||||||
89
homes/x86_64-linux/matt@allyx/default.nix
Executable file
89
homes/x86_64-linux/matt@allyx/default.nix
Executable file
@@ -0,0 +1,89 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}) enabled;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.username = "matt";
|
||||||
|
|
||||||
|
${namespace}.desktop.gnome = enabled;
|
||||||
|
|
||||||
|
sops = {
|
||||||
|
age.keyFile = "/home/matt/.config/sops/age/keys.txt";
|
||||||
|
defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
|
||||||
|
validateSopsFiles = false;
|
||||||
|
secrets = {
|
||||||
|
"ssh-keys-public/matt" = {
|
||||||
|
path = "/home/matt/.ssh/id_ed25519.pub";
|
||||||
|
mode = "0644";
|
||||||
|
};
|
||||||
|
"ssh-keys-private/matt" = {
|
||||||
|
path = "/home/matt/.ssh/id_ed25519";
|
||||||
|
mode = "0600";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
programs = {
|
||||||
|
steam-rom-manager = {
|
||||||
|
enable = true;
|
||||||
|
steamUsername = "mjallen18";
|
||||||
|
|
||||||
|
environmentVariables = {
|
||||||
|
romsDirectory = "/media/sdcard/Emulation/roms";
|
||||||
|
steamDirectory = "/home/matt/.local/share/Steam";
|
||||||
|
};
|
||||||
|
|
||||||
|
enabledProviders = [ "sgdb" "steamCDN" ];
|
||||||
|
imageProviderSettings.sgdb = {
|
||||||
|
nsfw = false;
|
||||||
|
humor = false;
|
||||||
|
imageMotionTypes = [ "static" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
emulators = {
|
||||||
|
# --- Nintendo ---
|
||||||
|
ryujinx.enable = true; # Switch (ryubing fork)
|
||||||
|
yuzu.enable = true; # Switch (eden fork)
|
||||||
|
dolphin-emu.enable = true; # GameCube / Wii
|
||||||
|
cemu.enable = true; # Wii U
|
||||||
|
melonDS.enable = true; # DS
|
||||||
|
citra.enable = true; # 3DS (azahar fork)
|
||||||
|
mgba.enable = true; # Game Boy / GBC
|
||||||
|
mgba-gba.enable = true; # Game Boy Advance
|
||||||
|
|
||||||
|
# --- Sony ---
|
||||||
|
duckstation.enable = false; # PS1
|
||||||
|
pcsx2.enable = true; # PS2
|
||||||
|
rpcs3.enable = true; # PS3
|
||||||
|
ppsspp.enable = true; # PSP
|
||||||
|
|
||||||
|
# --- Microsoft ---
|
||||||
|
xemu.enable = true; # Xbox
|
||||||
|
|
||||||
|
# --- Platform parsers (no ROM scanning; artwork only / launcher integration) ---
|
||||||
|
"Non-SRM Shortcuts".enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
home.packages =
|
||||||
|
with pkgs;
|
||||||
|
[
|
||||||
|
dolphin-emu
|
||||||
|
heroic
|
||||||
|
mgba
|
||||||
|
moonlight-qt
|
||||||
|
prismlauncher
|
||||||
|
ryubing
|
||||||
|
omnissa-horizon-client
|
||||||
|
]
|
||||||
|
++ (with pkgs.${namespace}; [
|
||||||
|
discord-krisp
|
||||||
|
# librepods-beta
|
||||||
|
]);
|
||||||
|
}
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
{ pkgs, namespace, ... }:
|
|
||||||
let
|
|
||||||
shellAliases = {
|
|
||||||
update-boot = "sudo nixos-rebuild boot --max-jobs 10 --build-host admin@10.0.1.3";
|
|
||||||
update-switch = "sudo nixos-rebuild switch --max-jobs 10 --build-host admin@10.0.1.3";
|
|
||||||
update-flake = "nix flake update desktop-nixpkgs desktop-chaotic desktop-home-manager desktop-impermanence desktop-lanzaboote desktop-nixos-hardware desktop-sops-nix desktop-steam-rom-manager --flake /etc/nixos";
|
|
||||||
update-nas = "nixos-rebuild switch --use-remote-sudo --target-host admin@10.0.1.3 --build-host admin@10.0.1.3 --flake ~/nix-config#jallen-nas";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
home.username = "matt";
|
|
||||||
|
|
||||||
services = {
|
|
||||||
remmina = {
|
|
||||||
enable = true;
|
|
||||||
addRdpMimeTypeAssoc = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
programs = {
|
|
||||||
password-store.enable = true;
|
|
||||||
|
|
||||||
zsh.shellAliases = shellAliases;
|
|
||||||
};
|
|
||||||
|
|
||||||
home.packages = with pkgs; [
|
|
||||||
bottles
|
|
||||||
compose2nix
|
|
||||||
discord
|
|
||||||
distrobox
|
|
||||||
heroic
|
|
||||||
stable.vmware-horizon-client
|
|
||||||
jq
|
|
||||||
lutris
|
|
||||||
lzip
|
|
||||||
morph
|
|
||||||
orca-slicer
|
|
||||||
piper
|
|
||||||
prismlauncher
|
|
||||||
protontricks
|
|
||||||
protonvpn-gui
|
|
||||||
python3
|
|
||||||
smile
|
|
||||||
unigine-heaven
|
|
||||||
via
|
|
||||||
virt-manager
|
|
||||||
vorta
|
|
||||||
waydroid-helper
|
|
||||||
];
|
|
||||||
}
|
|
||||||
210
homes/x86_64-linux/matt@matt-nixos/default.nix
Executable file
210
homes/x86_64-linux/matt@matt-nixos/default.nix
Executable file
@@ -0,0 +1,210 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}) enabled disabled;
|
||||||
|
displayLeft = {
|
||||||
|
input = "DP-1";
|
||||||
|
resolution = "3840x2160";
|
||||||
|
refreshRate = "120.00000";
|
||||||
|
};
|
||||||
|
displayRight = {
|
||||||
|
input = "DP-2";
|
||||||
|
resolution = "3840x2160";
|
||||||
|
refreshRate = "240.00000";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.username = "matt";
|
||||||
|
|
||||||
|
${namespace} = {
|
||||||
|
sops = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
shell-aliases = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
desktop.gnome = enabled;
|
||||||
|
|
||||||
|
programs = {
|
||||||
|
hyprland = {
|
||||||
|
enable = false;
|
||||||
|
primaryDisplay = "DP-1";
|
||||||
|
|
||||||
|
monitorv2 = [
|
||||||
|
{
|
||||||
|
name = displayLeft.input;
|
||||||
|
mode = "${displayLeft.resolution}@${displayLeft.refreshRate}";
|
||||||
|
position = "0x0";
|
||||||
|
scale = 1.0;
|
||||||
|
extra = [
|
||||||
|
# "bitdepth"
|
||||||
|
# "10"
|
||||||
|
# "cm"
|
||||||
|
# "hdredid"
|
||||||
|
# "sdrbrightness"
|
||||||
|
# "1.2"
|
||||||
|
# "sdrsaturation"
|
||||||
|
# "0.98"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = displayRight.input;
|
||||||
|
mode = "${displayRight.resolution}@${displayRight.refreshRate}";
|
||||||
|
position = "3840x0";
|
||||||
|
scale = 1.0;
|
||||||
|
extra = [
|
||||||
|
# "bitdepth"
|
||||||
|
# "10"
|
||||||
|
# "cm"
|
||||||
|
# "hdredid"
|
||||||
|
# "sdrbrightness"
|
||||||
|
# "1.5"
|
||||||
|
# "sdrsaturation"
|
||||||
|
# "0.98"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
workspace = [
|
||||||
|
"name:firefox, monitor:${displayRight.input}, default:false, special, class:(.*firefox.*)"
|
||||||
|
"name:discord, monitor:${displayRight.input}, default:true, special, title:(.*vesktop.*), title:(.*Apple Music.*)"
|
||||||
|
"name:steam, monitor:${displayLeft.input}, default:false, special, class:(.*[Ss]team.*)"
|
||||||
|
];
|
||||||
|
|
||||||
|
windowRule = [
|
||||||
|
"match:tag horizonrdp, size 2160 7680"
|
||||||
|
];
|
||||||
|
|
||||||
|
autostartCommands = [
|
||||||
|
"[silent] firefox"
|
||||||
|
"[silent] discord"
|
||||||
|
"[silent] chromium --app=\"https://music.apple.com\""
|
||||||
|
"[silent] steam"
|
||||||
|
];
|
||||||
|
|
||||||
|
hyprpaper = {
|
||||||
|
wallpaperPath = "/run/wallpaper.jpg";
|
||||||
|
};
|
||||||
|
|
||||||
|
keybinds = {
|
||||||
|
bind = [
|
||||||
|
"$mod, A, exec, chromium --app=\"https://music.apple.com\""
|
||||||
|
"$mod, C, exec, discord"
|
||||||
|
"$mod, G, exec, steam"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
defaultApps = {
|
||||||
|
browser = pkgs.firefox;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
btop = enabled;
|
||||||
|
kitty = disabled;
|
||||||
|
mako = disabled;
|
||||||
|
nwg-dock = disabled;
|
||||||
|
nwg-drawer = disabled;
|
||||||
|
nwg-panel = disabled;
|
||||||
|
waybar = {
|
||||||
|
enable = false;
|
||||||
|
|
||||||
|
layer = "bottom";
|
||||||
|
|
||||||
|
network.interface = "wlp9s0";
|
||||||
|
temperature = {
|
||||||
|
cpu = enabled;
|
||||||
|
gpu = enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
extraModules = {
|
||||||
|
"custom/lights" = {
|
||||||
|
tooltip = false;
|
||||||
|
exec = "waybar-hass --get_light light.living_room_lights";
|
||||||
|
interval = "once";
|
||||||
|
format = "{text}"; # "";
|
||||||
|
on-click = "waybar-hass --toggle_light light.living_room_lights";
|
||||||
|
return-type = "json";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
extraModulesStyle = ''
|
||||||
|
#custom-lights {
|
||||||
|
color: @base0C;
|
||||||
|
background-color: @base00;
|
||||||
|
opacity: 0.85;
|
||||||
|
border-left: 5px solid @base0C;
|
||||||
|
}
|
||||||
|
|
||||||
|
#custom-lights:hover {
|
||||||
|
background: @base03;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
wlogout = disabled;
|
||||||
|
wofi = disabled;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
remmina = {
|
||||||
|
enable = true;
|
||||||
|
addRdpMimeTypeAssoc = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
programs = {
|
||||||
|
password-store = enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
home.packages =
|
||||||
|
with pkgs;
|
||||||
|
[
|
||||||
|
bolt-launcher
|
||||||
|
clevis
|
||||||
|
compose2nix
|
||||||
|
distrobox
|
||||||
|
heroic
|
||||||
|
home-manager
|
||||||
|
omnissa-horizon-client
|
||||||
|
jq
|
||||||
|
lzip
|
||||||
|
morph
|
||||||
|
orca-slicer
|
||||||
|
piper
|
||||||
|
prismlauncher
|
||||||
|
protontricks
|
||||||
|
protonvpn-gui
|
||||||
|
runelite
|
||||||
|
smile
|
||||||
|
via
|
||||||
|
virt-manager
|
||||||
|
vorta
|
||||||
|
waydroid-helper
|
||||||
|
]
|
||||||
|
++ (with pkgs.${namespace}; [
|
||||||
|
discord-krisp
|
||||||
|
# librepods
|
||||||
|
]);
|
||||||
|
|
||||||
|
specialisation = {
|
||||||
|
"cosmic".configuration = {
|
||||||
|
${namespace} = {
|
||||||
|
programs = {
|
||||||
|
hyprland = lib.mkForce disabled;
|
||||||
|
kitty = lib.mkForce disabled;
|
||||||
|
mako = lib.mkForce disabled;
|
||||||
|
nwg-dock = lib.mkForce disabled;
|
||||||
|
nwg-drawer = lib.mkForce disabled;
|
||||||
|
nwg-panel = lib.mkForce disabled;
|
||||||
|
waybar = lib.mkForce disabled;
|
||||||
|
wlogout = lib.mkForce disabled;
|
||||||
|
wofi = lib.mkForce disabled;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
18
homes/x86_64-linux/nixos@iso-minimal/default.nix
Normal file
18
homes/x86_64-linux/nixos@iso-minimal/default.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}) disabled;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.username = "nixos";
|
||||||
|
services = {
|
||||||
|
nextcloud-client = lib.mkForce disabled;
|
||||||
|
kdeconnect = {
|
||||||
|
enable = false;
|
||||||
|
indicator = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
18
homes/x86_64-linux/root@allyx/default.nix
Normal file
18
homes/x86_64-linux/root@allyx/default.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}) disabled;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.username = "root";
|
||||||
|
services = {
|
||||||
|
nextcloud-client = lib.mkForce disabled;
|
||||||
|
kdeconnect = {
|
||||||
|
enable = false;
|
||||||
|
indicator = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
18
homes/x86_64-linux/root@iso-minimal/default.nix
Normal file
18
homes/x86_64-linux/root@iso-minimal/default.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}) disabled;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.username = "root";
|
||||||
|
services = {
|
||||||
|
nextcloud-client = lib.mkForce disabled;
|
||||||
|
kdeconnect = {
|
||||||
|
enable = false;
|
||||||
|
indicator = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
18
homes/x86_64-linux/root@jallen-nas/default.nix
Normal file
18
homes/x86_64-linux/root@jallen-nas/default.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}) disabled;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.username = "root";
|
||||||
|
services = {
|
||||||
|
nextcloud-client = lib.mkForce disabled;
|
||||||
|
kdeconnect = {
|
||||||
|
enable = false;
|
||||||
|
indicator = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
18
homes/x86_64-linux/root@matt-nixos/default.nix
Normal file
18
homes/x86_64-linux/root@matt-nixos/default.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}) disabled;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.username = "root";
|
||||||
|
services = {
|
||||||
|
nextcloud-client = lib.mkForce disabled;
|
||||||
|
kdeconnect = {
|
||||||
|
enable = false;
|
||||||
|
indicator = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
18
homes/x86_64-linux/root@nuc-nixos/default.nix
Normal file
18
homes/x86_64-linux/root@nuc-nixos/default.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}) disabled;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.username = "root";
|
||||||
|
services = {
|
||||||
|
nextcloud-client = lib.mkForce disabled;
|
||||||
|
kdeconnect = {
|
||||||
|
enable = false;
|
||||||
|
indicator = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{ config, lib, ... }:
|
|
||||||
let
|
|
||||||
shellAliases = {
|
|
||||||
update-boot = "nixos-rebuild boot --max-jobs 10";
|
|
||||||
update-switch = "nixos-rebuild switch --max-jobs 10";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
home = {
|
|
||||||
username = "root";
|
|
||||||
homeDirectory = lib.mkForce "/${config.home.username}";
|
|
||||||
};
|
|
||||||
|
|
||||||
programs = {
|
|
||||||
zsh.shellAliases = shellAliases;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
130
lib/README.md
Normal file
130
lib/README.md
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
# mjallen-lib Utility Functions
|
||||||
|
|
||||||
|
This directory contains utility functions that can be used to enhance your Nix configuration. These functions are inspired by the khanelinix repository and provide a more explicit and modular approach to building Nix configurations.
|
||||||
|
|
||||||
|
## Directory Structure
|
||||||
|
|
||||||
|
- `default.nix`: Main entry point that imports and exposes all utility functions
|
||||||
|
- `module/`: Utilities for module creation and option handling
|
||||||
|
- `file/`: Utilities for file handling and module discovery
|
||||||
|
- `system/`: Utilities for system configuration building
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
### 1. Import the Library
|
||||||
|
|
||||||
|
The library is already imported in your flake.nix file through the outputs-builder:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
outputs-builder = channels: {
|
||||||
|
formatter = inputs.treefmt-nix.lib.mkWrapper channels.nixpkgs ./treefmt.nix;
|
||||||
|
|
||||||
|
# Add mjallen-lib to the flake outputs
|
||||||
|
overlays = {
|
||||||
|
mjallen-lib = final: prev: {
|
||||||
|
mjallen-lib = (import ./lib { inherit inputs; }).mjallen-lib;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
This makes the mjallen-lib available to all your modules through the extended lib.
|
||||||
|
|
||||||
|
### 2. Use the Module Utilities
|
||||||
|
|
||||||
|
The module utilities provide functions for creating modules with consistent options:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ lib, ... }:
|
||||||
|
let
|
||||||
|
inherit (lib.mjallen.module) mkModule mkOpt mkBoolOpt;
|
||||||
|
in
|
||||||
|
mkModule {
|
||||||
|
name = "mymodule";
|
||||||
|
description = "My awesome module";
|
||||||
|
options = {
|
||||||
|
setting1 = mkOpt lib.types.str "default" "Description of setting1";
|
||||||
|
setting2 = mkBoolOpt false "Description of setting2";
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
# Module implementation
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Use the File Utilities
|
||||||
|
|
||||||
|
The file utilities provide functions for file handling and module discovery:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ lib, ... }:
|
||||||
|
let
|
||||||
|
inherit (lib.mjallen.file) safeImport importModulesRecursive;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# Import a file with error handling
|
||||||
|
myConfig = safeImport ./my-config.nix {};
|
||||||
|
|
||||||
|
# Import all modules recursively
|
||||||
|
imports = importModulesRecursive ./modules;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Use the System Utilities
|
||||||
|
|
||||||
|
The system utilities provide functions for building system configurations:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ lib, ... }:
|
||||||
|
let
|
||||||
|
inherit (lib.mjallen.system.common) mkHomeManagerConfig;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# Build home-manager configurations
|
||||||
|
homeManagerConfig = mkHomeManagerConfig {
|
||||||
|
extendedLib = lib;
|
||||||
|
inputs = inputs;
|
||||||
|
system = "x86_64-linux";
|
||||||
|
matchingHomes = { ... };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available Functions
|
||||||
|
|
||||||
|
### Module Utilities
|
||||||
|
|
||||||
|
- `mkModule`: Create a module with common options
|
||||||
|
- `mkOpt`: Create an option with a type, default value, and description
|
||||||
|
- `mkOpt'`: Create an option with a type and default value (no description)
|
||||||
|
- `mkBoolOpt`: Create a boolean option with a default value and description
|
||||||
|
- `mkBoolOpt'`: Create a boolean option with a default value (no description)
|
||||||
|
- `enabled`: Standard enable pattern
|
||||||
|
- `disabled`: Standard disable pattern
|
||||||
|
- `capitalize`: Capitalize a string
|
||||||
|
- `boolToNum`: Convert a boolean to a number
|
||||||
|
- `default-attrs`: Apply mkDefault to all attributes
|
||||||
|
- `force-attrs`: Apply mkForce to all attributes
|
||||||
|
- `nested-default-attrs`: Apply default-attrs to nested attributes
|
||||||
|
- `nested-force-attrs`: Apply force-attrs to nested attributes
|
||||||
|
|
||||||
|
### File Utilities
|
||||||
|
|
||||||
|
- `readFile`: Read a file and return its contents
|
||||||
|
- `pathExists`: Check if a file exists
|
||||||
|
- `safeImport`: Import a nix file with error handling
|
||||||
|
- `scanDir`: Scan a directory and return directory names
|
||||||
|
- `getFile`: Get a file path relative to the flake root
|
||||||
|
- `importModulesRecursive`: Recursively discover and import all Nix modules in a directory tree
|
||||||
|
- `scanSystems`: Recursively scan systems directory structure
|
||||||
|
- `filterNixOSSystems`: Filter systems for NixOS (Linux)
|
||||||
|
- `filterDarwinSystems`: Filter systems for Darwin (macOS)
|
||||||
|
- `scanHomes`: Scan homes directory structure for home configurations
|
||||||
|
|
||||||
|
### System Utilities
|
||||||
|
|
||||||
|
- `mkExtendedLib`: Extend the nixpkgs lib with mjallen-lib
|
||||||
|
- `mkNixpkgsConfig`: Create a nixpkgs configuration
|
||||||
|
- `mkHomeConfigs`: Create home configurations for a system and hostname
|
||||||
|
- `mkHomeManagerConfig`: Create a home-manager configuration
|
||||||
|
- `mkSpecialArgs`: Create special arguments for a system configuration
|
||||||
3
lib/base64/ascii
Normal file
3
lib/base64/ascii
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
|
||||||
62
lib/base64/default.nix
Normal file
62
lib/base64/default.nix
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
{ inputs }:
|
||||||
|
let
|
||||||
|
inherit (inputs.nixpkgs.lib)
|
||||||
|
concatLists
|
||||||
|
concatMapStrings
|
||||||
|
foldl'
|
||||||
|
genList
|
||||||
|
hasSuffix
|
||||||
|
imap0
|
||||||
|
length
|
||||||
|
mod
|
||||||
|
nameValuePair
|
||||||
|
stringToCharacters
|
||||||
|
sublist
|
||||||
|
substring
|
||||||
|
take
|
||||||
|
;
|
||||||
|
in
|
||||||
|
rec {
|
||||||
|
base64Table = builtins.listToAttrs (
|
||||||
|
imap0 (i: c: nameValuePair c i) (
|
||||||
|
# The '=' is included so the main algorithm doesn't fail before we can trim the result
|
||||||
|
stringToCharacters "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
# Generated using python3:
|
||||||
|
# print(''.join([ chr(n) for n in range(1, 256) ]), file=open('ascii', 'w'))
|
||||||
|
ascii = builtins.readFile ./ascii;
|
||||||
|
|
||||||
|
decode =
|
||||||
|
str:
|
||||||
|
let
|
||||||
|
paddingCount =
|
||||||
|
if hasSuffix "==" str then
|
||||||
|
2
|
||||||
|
else if hasSuffix "=" str then
|
||||||
|
1
|
||||||
|
else
|
||||||
|
0;
|
||||||
|
|
||||||
|
numbers64 = map (c: base64Table.${c}) (stringToCharacters str);
|
||||||
|
|
||||||
|
allBytes = concatLists (
|
||||||
|
genList (
|
||||||
|
i:
|
||||||
|
let
|
||||||
|
v = foldl' (acc: el: acc * 64 + el) 0 (sublist (i * 4) 4 numbers64);
|
||||||
|
in
|
||||||
|
[
|
||||||
|
(mod (v / 256 / 256) 256)
|
||||||
|
(mod (v / 256) 256)
|
||||||
|
(mod v 256)
|
||||||
|
]
|
||||||
|
) (length numbers64 / 4)
|
||||||
|
);
|
||||||
|
|
||||||
|
finalBytes = take (length allBytes - paddingCount) allBytes;
|
||||||
|
|
||||||
|
in
|
||||||
|
concatMapStrings (n: substring (n - 1) 1 ascii) finalBytes;
|
||||||
|
}
|
||||||
25
lib/default.nix
Normal file
25
lib/default.nix
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{ inputs, ... }:
|
||||||
|
{
|
||||||
|
mjallen-lib = {
|
||||||
|
# Import module utilities
|
||||||
|
module = import ./module { inherit inputs; };
|
||||||
|
|
||||||
|
# Import file utilities
|
||||||
|
file = import ./file { inherit inputs; };
|
||||||
|
|
||||||
|
# Import system utilities
|
||||||
|
system = import ./system { inherit inputs; };
|
||||||
|
|
||||||
|
# Import reverse proxy utilities
|
||||||
|
reverseproxy = import ./reverseproxy { inherit inputs; };
|
||||||
|
|
||||||
|
# Import examples
|
||||||
|
examples = import ./examples { inherit inputs; };
|
||||||
|
|
||||||
|
# Import versioning utilities
|
||||||
|
versioning = import ./versioning {
|
||||||
|
lib = inputs.nixpkgs.lib;
|
||||||
|
inherit inputs;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
8
lib/examples/default.nix
Normal file
8
lib/examples/default.nix
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
# Import all examples
|
||||||
|
sops = import ./sops.nix;
|
||||||
|
homeSops = import ./home-sops.nix;
|
||||||
|
fileUtils = import ./file-utils.nix;
|
||||||
|
systemUtils = import ./system-utils.nix;
|
||||||
|
}
|
||||||
60
lib/examples/file-utils.nix
Normal file
60
lib/examples/file-utils.nix
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
{ lib, namespace, ... }:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}.file)
|
||||||
|
readFile
|
||||||
|
pathExists
|
||||||
|
safeImport
|
||||||
|
scanDir
|
||||||
|
getFile
|
||||||
|
importModulesRecursive
|
||||||
|
scanSystems
|
||||||
|
filterNixOSSystems
|
||||||
|
filterDarwinSystems
|
||||||
|
scanHomes
|
||||||
|
;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# Example of reading a file
|
||||||
|
myFileContent = readFile ./example.txt;
|
||||||
|
|
||||||
|
# Example of checking if a file exists
|
||||||
|
fileExists = pathExists ./example.txt;
|
||||||
|
|
||||||
|
# Example of safely importing a file
|
||||||
|
myConfig = safeImport ./my-config.nix { };
|
||||||
|
|
||||||
|
# Example of scanning a directory
|
||||||
|
directoryContents = scanDir ./modules;
|
||||||
|
|
||||||
|
# Example of getting a file path relative to the flake root
|
||||||
|
flakeFile = getFile "flake.nix";
|
||||||
|
|
||||||
|
# Example of importing modules recursively
|
||||||
|
modules = importModulesRecursive ./modules;
|
||||||
|
|
||||||
|
# Example of scanning systems
|
||||||
|
allSystems = scanSystems ./systems;
|
||||||
|
|
||||||
|
# Example of filtering systems
|
||||||
|
nixosSystems = filterNixOSSystems allSystems;
|
||||||
|
darwinSystems = filterDarwinSystems allSystems;
|
||||||
|
|
||||||
|
# Example of scanning homes
|
||||||
|
allHomes = scanHomes ./homes;
|
||||||
|
|
||||||
|
# Example of using these functions together
|
||||||
|
nixosConfigurations = lib.mapAttrs' (
|
||||||
|
_name:
|
||||||
|
{ system, hostname, ... }:
|
||||||
|
{
|
||||||
|
name = hostname;
|
||||||
|
value = lib.nixosSystem {
|
||||||
|
inherit system;
|
||||||
|
modules = [
|
||||||
|
{ networking.hostName = hostname; }
|
||||||
|
]
|
||||||
|
++ importModulesRecursive ./modules/nixos;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) nixosSystems;
|
||||||
|
}
|
||||||
40
lib/examples/home-sops.nix
Normal file
40
lib/examples/home-sops.nix
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}.module) mkModule mkOpt;
|
||||||
|
in
|
||||||
|
mkModule {
|
||||||
|
name = "sops";
|
||||||
|
description = "SOPS secret management for home-manager";
|
||||||
|
options = {
|
||||||
|
defaultSopsFile = mkOpt lib.types.path null "Default sops file.";
|
||||||
|
|
||||||
|
sshKeyPaths = mkOpt (lib.types.listOf lib.types.str) [ ] "SSH Key paths to use.";
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
age
|
||||||
|
sops
|
||||||
|
ssh-to-age
|
||||||
|
];
|
||||||
|
|
||||||
|
sops = {
|
||||||
|
inherit (config.${namespace}.sops) defaultSopsFile;
|
||||||
|
defaultSopsFormat = "yaml";
|
||||||
|
|
||||||
|
age = {
|
||||||
|
generateKey = true;
|
||||||
|
keyFile = "${config.home.homeDirectory}/.config/sops/age/keys.txt";
|
||||||
|
sshKeyPaths = [
|
||||||
|
"${config.home.homeDirectory}/.ssh/id_ed25519"
|
||||||
|
]
|
||||||
|
++ config.${namespace}.sops.sshKeyPaths;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
117
lib/examples/reverseproxy.nix
Normal file
117
lib/examples/reverseproxy.nix
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# Example usage of the reverse proxy utilities
|
||||||
|
{ lib, namespace, ... }:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace} - lib.reverseproxy)
|
||||||
|
mkReverseProxy
|
||||||
|
mkReverseProxies
|
||||||
|
templates
|
||||||
|
middlewares
|
||||||
|
urls
|
||||||
|
;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# Example 1: Simple reverse proxy for a local service
|
||||||
|
simpleProxy = mkReverseProxy {
|
||||||
|
name = "myapp";
|
||||||
|
subdomain = "myapp";
|
||||||
|
url = "http://127.0.0.1:3000";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Example 2: Authenticated service with custom middlewares
|
||||||
|
authProxy = mkReverseProxy {
|
||||||
|
name = "admin-panel";
|
||||||
|
subdomain = "admin";
|
||||||
|
url = "http://127.0.0.1:8080";
|
||||||
|
middlewares = middlewares.authBasic;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Example 3: Container-based service
|
||||||
|
containerProxy = mkReverseProxy {
|
||||||
|
name = "nextcloud";
|
||||||
|
subdomain = "cloud";
|
||||||
|
url = urls.container "nextcloud" 80;
|
||||||
|
middlewares = middlewares.basic;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Example 4: Multiple proxies at once
|
||||||
|
multipleProxies = mkReverseProxies [
|
||||||
|
{
|
||||||
|
name = "grafana";
|
||||||
|
subdomain = "grafana";
|
||||||
|
url = urls.localhost 3000;
|
||||||
|
middlewares = middlewares.authBasic;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "prometheus";
|
||||||
|
subdomain = "prometheus";
|
||||||
|
url = urls.localhost 9090;
|
||||||
|
middlewares = middlewares.internal;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "alertmanager";
|
||||||
|
subdomain = "alerts";
|
||||||
|
url = urls.localhost 9093;
|
||||||
|
middlewares = middlewares.authBasic;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
# Example 5: Using templates for common patterns
|
||||||
|
webappExample = templates.webapp {
|
||||||
|
name = "webapp";
|
||||||
|
subdomain = "app";
|
||||||
|
port = 8080;
|
||||||
|
};
|
||||||
|
|
||||||
|
authWebappExample = templates.authWebapp {
|
||||||
|
name = "secure-app";
|
||||||
|
subdomain = "secure";
|
||||||
|
port = 9000;
|
||||||
|
};
|
||||||
|
|
||||||
|
containerExample = templates.containerService {
|
||||||
|
name = "gitea";
|
||||||
|
subdomain = "git";
|
||||||
|
containerName = "gitea";
|
||||||
|
port = 3000;
|
||||||
|
};
|
||||||
|
|
||||||
|
internalExample = templates.internalService {
|
||||||
|
name = "internal-api";
|
||||||
|
subdomain = "api-internal";
|
||||||
|
port = 8000;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Example 6: Custom domain and advanced configuration
|
||||||
|
customProxy = mkReverseProxy {
|
||||||
|
name = "custom-service";
|
||||||
|
subdomain = "custom";
|
||||||
|
url = "http://10.0.1.100:8080";
|
||||||
|
domain = "example.com";
|
||||||
|
priority = 20;
|
||||||
|
rule = "Host(`custom.example.com`) && PathPrefix(`/api`)";
|
||||||
|
middlewares = [
|
||||||
|
"crowdsec"
|
||||||
|
"whitelist-geoblock"
|
||||||
|
"rate-limit"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Example usage in a Traefik configuration:
|
||||||
|
#
|
||||||
|
# mjallen.services.traefik = {
|
||||||
|
# enable = true;
|
||||||
|
# extraServices = multipleProxies.extraServices;
|
||||||
|
# extraRouters = multipleProxies.extraRouters;
|
||||||
|
# };
|
||||||
|
#
|
||||||
|
# Or for individual proxies:
|
||||||
|
#
|
||||||
|
# mjallen.services.traefik = {
|
||||||
|
# enable = true;
|
||||||
|
# extraServices = [ simpleProxy.service ];
|
||||||
|
# extraRouters = [{
|
||||||
|
# inherit (simpleProxy.router) subdomain entryPoints middlewares;
|
||||||
|
# service = simpleProxy.router.service;
|
||||||
|
# }];
|
||||||
|
# };
|
||||||
|
}
|
||||||
45
lib/examples/sops.nix
Normal file
45
lib/examples/sops.nix
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}.module) mkModule mkOpt mkBoolOpt;
|
||||||
|
in
|
||||||
|
mkModule {
|
||||||
|
name = "sops";
|
||||||
|
description = "SOPS secret management";
|
||||||
|
options = {
|
||||||
|
defaultSopsFile = mkOpt lib.types.path null "Default sops file.";
|
||||||
|
|
||||||
|
generateAgeKey = mkBoolOpt true "Whether to automatically generate an age key if one doesn't exist.";
|
||||||
|
|
||||||
|
ageKeyPath =
|
||||||
|
mkOpt (lib.types.nullOr lib.types.str) null
|
||||||
|
"Custom path to the age key file. If null, will use the default path.";
|
||||||
|
|
||||||
|
sshKeyPaths = mkOpt (lib.types.listOf lib.types.str) [
|
||||||
|
"/etc/ssh/ssh_host_ed25519_key"
|
||||||
|
] "SSH Key paths to use.";
|
||||||
|
|
||||||
|
validateSopsFiles = mkBoolOpt false "Whether to validate that sops files exist.";
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
sops = {
|
||||||
|
inherit (config.${namespace}.sops) defaultSopsFile validateSopsFiles;
|
||||||
|
|
||||||
|
age = {
|
||||||
|
inherit (config.${namespace}.sops) generateAgeKey;
|
||||||
|
|
||||||
|
keyFile =
|
||||||
|
if config.${namespace}.sops.ageKeyPath != null then
|
||||||
|
config.${namespace}.sops.ageKeyPath
|
||||||
|
else
|
||||||
|
"${config.users.users.${config.${namespace}.user.name}.home}/.config/sops/age/keys.txt";
|
||||||
|
|
||||||
|
sshKeyPaths = config.${namespace}.sops.sshKeyPaths;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
132
lib/examples/system-utils.nix
Normal file
132
lib/examples/system-utils.nix
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
{ inputs, namespace, ... }:
|
||||||
|
let
|
||||||
|
inherit (inputs.self.${namespace} - lib.system.common)
|
||||||
|
mkExtendedLib
|
||||||
|
mkNixpkgsConfig
|
||||||
|
mkHomeConfigs
|
||||||
|
mkHomeManagerConfig
|
||||||
|
mkSpecialArgs
|
||||||
|
;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# Example of creating NixOS configurations
|
||||||
|
nixosConfigurations =
|
||||||
|
let
|
||||||
|
# Get all systems
|
||||||
|
allSystems = inputs.self.${namespace} - lib.file.scanSystems ../systems;
|
||||||
|
|
||||||
|
# Filter for NixOS systems
|
||||||
|
nixosSystems = inputs.self.${namespace} - lib.file.filterNixOSSystems allSystems;
|
||||||
|
in
|
||||||
|
inputs.nixpkgs.lib.mapAttrs' (
|
||||||
|
_name:
|
||||||
|
{ system, hostname, ... }:
|
||||||
|
let
|
||||||
|
# Create extended lib with mjallen-lib
|
||||||
|
extendedLib = mkExtendedLib inputs.self inputs.nixpkgs;
|
||||||
|
|
||||||
|
# Find matching home configurations for this system
|
||||||
|
matchingHomes = mkHomeConfigs {
|
||||||
|
flake = inputs.self;
|
||||||
|
inherit system hostname;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Create home-manager configuration
|
||||||
|
homeManagerConfig = mkHomeManagerConfig {
|
||||||
|
inherit
|
||||||
|
extendedLib
|
||||||
|
inputs
|
||||||
|
system
|
||||||
|
matchingHomes
|
||||||
|
;
|
||||||
|
isNixOS = true;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = hostname;
|
||||||
|
value = inputs.nixpkgs.lib.nixosSystem {
|
||||||
|
inherit system;
|
||||||
|
|
||||||
|
# Pass special arguments to modules
|
||||||
|
specialArgs = mkSpecialArgs {
|
||||||
|
inherit inputs hostname extendedLib;
|
||||||
|
username = "mjallen";
|
||||||
|
};
|
||||||
|
|
||||||
|
modules = [
|
||||||
|
# Set lib to extended lib
|
||||||
|
{ _module.args.lib = extendedLib; }
|
||||||
|
|
||||||
|
# Configure nixpkgs
|
||||||
|
{
|
||||||
|
nixpkgs = {
|
||||||
|
inherit system;
|
||||||
|
}
|
||||||
|
// mkNixpkgsConfig inputs.self;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Import home-manager module
|
||||||
|
inputs.home-manager.nixosModules.home-manager
|
||||||
|
|
||||||
|
# Auto-inject home configurations
|
||||||
|
homeManagerConfig
|
||||||
|
|
||||||
|
# Import all nixos modules recursively
|
||||||
|
../${system}/${hostname}
|
||||||
|
]
|
||||||
|
++ (extendedLib.${namespace}.file.importModulesRecursive ../modules/nixos);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) nixosSystems;
|
||||||
|
|
||||||
|
# Example of creating home-manager configurations
|
||||||
|
homeConfigurations =
|
||||||
|
let
|
||||||
|
# Get all homes
|
||||||
|
allHomes = inputs.self.${namespace} - lib.file.scanHomes ../homes;
|
||||||
|
in
|
||||||
|
inputs.nixpkgs.lib.mapAttrs' (
|
||||||
|
_name:
|
||||||
|
{
|
||||||
|
system,
|
||||||
|
username,
|
||||||
|
hostname,
|
||||||
|
userAtHost,
|
||||||
|
path,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
# Create extended lib with mjallen-lib
|
||||||
|
extendedLib = mkExtendedLib inputs.self inputs.nixpkgs;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = userAtHost;
|
||||||
|
value = inputs.home-manager.lib.homeManagerConfiguration {
|
||||||
|
pkgs = import inputs.nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
inherit ((mkNixpkgsConfig inputs.self)) config overlays;
|
||||||
|
};
|
||||||
|
|
||||||
|
extraSpecialArgs = {
|
||||||
|
inherit
|
||||||
|
inputs
|
||||||
|
hostname
|
||||||
|
username
|
||||||
|
system
|
||||||
|
;
|
||||||
|
inherit (inputs) self;
|
||||||
|
lib = extendedLib;
|
||||||
|
};
|
||||||
|
|
||||||
|
modules = [
|
||||||
|
# Set lib to extended lib
|
||||||
|
{ _module.args.lib = extendedLib; }
|
||||||
|
|
||||||
|
# Import the home configuration
|
||||||
|
path
|
||||||
|
]
|
||||||
|
++ (extendedLib.${namespace}.file.importModulesRecursive ../modules/home);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) allHomes;
|
||||||
|
}
|
||||||
127
lib/file/default.nix
Normal file
127
lib/file/default.nix
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
{ inputs, ... }@args:
|
||||||
|
let
|
||||||
|
# Get self from args or default to ../.. (the flake root)
|
||||||
|
self = if args ? self then args.self else ../..;
|
||||||
|
|
||||||
|
inherit (inputs.nixpkgs.lib)
|
||||||
|
genAttrs
|
||||||
|
filterAttrs
|
||||||
|
hasPrefix
|
||||||
|
foldl'
|
||||||
|
;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# Read a file and return its contents
|
||||||
|
readFile = path: builtins.readFile path;
|
||||||
|
|
||||||
|
# Check if a file exists
|
||||||
|
pathExists = path: builtins.pathExists path;
|
||||||
|
|
||||||
|
# Import a nix file with error handling
|
||||||
|
safeImport = path: default: if builtins.pathExists path then import path else default;
|
||||||
|
|
||||||
|
# Scan a directory and return directory names
|
||||||
|
scanDir = path: builtins.attrNames (builtins.readDir path);
|
||||||
|
|
||||||
|
# Get a file path relative to the flake root (similar to Snowfall's get-file)
|
||||||
|
getFile = relativePath: self + "/${relativePath}";
|
||||||
|
|
||||||
|
# Recursively discover and import all Nix modules in a directory tree
|
||||||
|
importModulesRecursive =
|
||||||
|
path:
|
||||||
|
let
|
||||||
|
# Helper function to recursively walk directories
|
||||||
|
walkDir =
|
||||||
|
currentPath:
|
||||||
|
let
|
||||||
|
currentEntries = builtins.readDir currentPath;
|
||||||
|
entryNames = builtins.attrNames currentEntries;
|
||||||
|
|
||||||
|
# Get all directories that contain default.nix
|
||||||
|
directoriesWithDefault = builtins.filter (
|
||||||
|
name:
|
||||||
|
currentEntries.${name} == "directory" && builtins.pathExists (currentPath + "/${name}/default.nix")
|
||||||
|
) entryNames;
|
||||||
|
|
||||||
|
# Get ALL directories (to recurse into)
|
||||||
|
allDirectories = builtins.filter (name: currentEntries.${name} == "directory") entryNames;
|
||||||
|
|
||||||
|
# Import directories that have default.nix
|
||||||
|
directoryImports = map (name: currentPath + "/${name}") directoriesWithDefault;
|
||||||
|
|
||||||
|
# Recursively walk ALL subdirectories
|
||||||
|
subDirImports = builtins.concatLists (map (dir: walkDir (currentPath + "/${dir}")) allDirectories);
|
||||||
|
|
||||||
|
in
|
||||||
|
directoryImports ++ subDirImports;
|
||||||
|
|
||||||
|
in
|
||||||
|
walkDir path;
|
||||||
|
|
||||||
|
# Recursively scan systems directory structure
|
||||||
|
scanSystems =
|
||||||
|
systemsPath:
|
||||||
|
let
|
||||||
|
systemArchs = builtins.attrNames (builtins.readDir systemsPath);
|
||||||
|
|
||||||
|
generateSystemConfigs =
|
||||||
|
system:
|
||||||
|
let
|
||||||
|
systemPath = systemsPath + "/${system}";
|
||||||
|
hosts = builtins.attrNames (builtins.readDir systemPath);
|
||||||
|
in
|
||||||
|
genAttrs hosts (hostname: {
|
||||||
|
inherit system hostname;
|
||||||
|
path = systemPath + "/${hostname}";
|
||||||
|
});
|
||||||
|
in
|
||||||
|
foldl' (acc: system: acc // generateSystemConfigs system) { } systemArchs;
|
||||||
|
|
||||||
|
# Filter systems for NixOS (Linux)
|
||||||
|
filterNixOSSystems =
|
||||||
|
systems:
|
||||||
|
filterAttrs (
|
||||||
|
_name: { system, ... }: hasPrefix "x86_64-linux" system || hasPrefix "aarch64-linux" system
|
||||||
|
) systems;
|
||||||
|
|
||||||
|
# Filter systems for Darwin (macOS)
|
||||||
|
filterDarwinSystems =
|
||||||
|
systems:
|
||||||
|
filterAttrs (
|
||||||
|
_name: { system, ... }: hasPrefix "aarch64-darwin" system || hasPrefix "x86_64-darwin" system
|
||||||
|
) systems;
|
||||||
|
|
||||||
|
# Scan homes directory structure for home configurations
|
||||||
|
scanHomes =
|
||||||
|
homesPath:
|
||||||
|
let
|
||||||
|
systemArchs = builtins.attrNames (builtins.readDir homesPath);
|
||||||
|
|
||||||
|
generateHomeConfigs =
|
||||||
|
system:
|
||||||
|
let
|
||||||
|
systemPath = homesPath + "/${system}";
|
||||||
|
userAtHosts = builtins.attrNames (builtins.readDir systemPath);
|
||||||
|
|
||||||
|
parseUserAtHost =
|
||||||
|
userAtHost:
|
||||||
|
let
|
||||||
|
# Split "username@hostname" into parts
|
||||||
|
parts = builtins.split "@" userAtHost;
|
||||||
|
username = builtins.head parts;
|
||||||
|
hostname = builtins.elemAt parts 2; # After split: [username, "@", hostname]
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit
|
||||||
|
system
|
||||||
|
username
|
||||||
|
hostname
|
||||||
|
userAtHost
|
||||||
|
;
|
||||||
|
path = systemPath + "/${userAtHost}";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
genAttrs userAtHosts parseUserAtHost;
|
||||||
|
in
|
||||||
|
foldl' (acc: system: acc // generateHomeConfigs system) { } systemArchs;
|
||||||
|
}
|
||||||
264
lib/module/default.nix
Normal file
264
lib/module/default.nix
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
{
|
||||||
|
inputs,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (inputs.nixpkgs.lib)
|
||||||
|
mapAttrs
|
||||||
|
mkOption
|
||||||
|
types
|
||||||
|
toUpper
|
||||||
|
substring
|
||||||
|
stringLength
|
||||||
|
mkDefault
|
||||||
|
mkForce
|
||||||
|
;
|
||||||
|
|
||||||
|
base64Lib = import ../base64 { inherit inputs; };
|
||||||
|
in
|
||||||
|
rec {
|
||||||
|
|
||||||
|
# Conditionally enable modules based on system
|
||||||
|
enableForSystem =
|
||||||
|
system: modules:
|
||||||
|
builtins.filter (
|
||||||
|
mod: mod.systems or [ ] == [ ] || builtins.elem system (mod.systems or [ ])
|
||||||
|
) modules;
|
||||||
|
|
||||||
|
# Create a module with common options
|
||||||
|
mkModule =
|
||||||
|
{
|
||||||
|
name,
|
||||||
|
description ? "",
|
||||||
|
options ? { },
|
||||||
|
moduleConfig ? { },
|
||||||
|
domain ? "services",
|
||||||
|
config,
|
||||||
|
serviceName ? name,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.${namespace}.${domain}.${name};
|
||||||
|
|
||||||
|
# Create reverse proxy configuration using mkReverseProxy
|
||||||
|
reverseProxyConfig = lib.${namespace}.mkReverseProxy {
|
||||||
|
inherit name;
|
||||||
|
subdomain = cfg.reverseProxy.subdomain;
|
||||||
|
url = "http://${config.${namespace}.network.ipv4.address}:${toString cfg.port}";
|
||||||
|
middlewares = cfg.reverseProxy.middlewares;
|
||||||
|
};
|
||||||
|
|
||||||
|
defaultConfig = {
|
||||||
|
${namespace}.services.traefik = lib.mkIf cfg.reverseProxy.enable {
|
||||||
|
reverseProxies = [ reverseProxyConfig ];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Open firewall
|
||||||
|
networking.firewall = lib.mkIf cfg.openFirewall {
|
||||||
|
allowedTCPPorts = [ cfg.port ];
|
||||||
|
allowedUDPPorts = [ cfg.port ];
|
||||||
|
};
|
||||||
|
|
||||||
|
users = lib.mkIf cfg.createUser {
|
||||||
|
users.${name} = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = name;
|
||||||
|
home = cfg.configDir;
|
||||||
|
};
|
||||||
|
groups.${name} = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.${serviceName} = {
|
||||||
|
requires = [
|
||||||
|
"media-nas-main.mount"
|
||||||
|
# "openvpn-us.protonvpn.udp.service"
|
||||||
|
];
|
||||||
|
after = lib.mkForce [
|
||||||
|
"media-nas-main.mount"
|
||||||
|
# "openvpn-us.protonvpn.udp.service"
|
||||||
|
];
|
||||||
|
# serviceConfig = {
|
||||||
|
# NetworkNamespacePath = lib.mkIf cfg.enableVpn "/run/netns/vpn";
|
||||||
|
# # Consider also setting DNS *inside* the netns (see note below).
|
||||||
|
# };
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
postgresql = lib.mkIf cfg.configureDb {
|
||||||
|
enable = true;
|
||||||
|
ensureDatabases = [ name ];
|
||||||
|
ensureUsers = [
|
||||||
|
{
|
||||||
|
name = name;
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
redis.servers.${name} = lib.mkIf cfg.redis.enable {
|
||||||
|
enable = true;
|
||||||
|
port = cfg.redis.port;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# systemd.tmpfiles.rules = [
|
||||||
|
# "d ${cfg.configDir} 0700 ${name} ${name} - -"
|
||||||
|
# # "d ${cfg.configDir}/server-files 0775 ${name} ${name} - -"
|
||||||
|
# # "d ${cfg.configDir}/user-files 0775 ${name} ${name} - -"
|
||||||
|
# ];
|
||||||
|
}
|
||||||
|
// moduleConfig;
|
||||||
|
in
|
||||||
|
{ lib, ... }:
|
||||||
|
{
|
||||||
|
options.${namespace}.${domain}.${name} = lib.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
enable = lib.mkEnableOption description;
|
||||||
|
|
||||||
|
port = mkOpt types.int 80 "Port for ${name} to be hosted on";
|
||||||
|
|
||||||
|
configDir = mkOpt types.str "/media/nas/main/appdata" "Path to the config dir";
|
||||||
|
|
||||||
|
dataDir = mkOpt types.str "/media/nas/main" "Path to the data dir";
|
||||||
|
|
||||||
|
createUser = mkBoolOpt false "create a user for this module/service";
|
||||||
|
|
||||||
|
configureDb = mkBoolOpt false "Manage db for this service";
|
||||||
|
|
||||||
|
environmentFile = mkOpt types.str "" "Environment File";
|
||||||
|
|
||||||
|
puid = mkOpt types.str "911" "default user id";
|
||||||
|
|
||||||
|
pgid = mkOpt types.str "1000" "default group id";
|
||||||
|
|
||||||
|
timeZone = mkOpt types.str "America/Chicago" "default timezone";
|
||||||
|
|
||||||
|
listenAddress = mkOpt types.str "0.0.0.0" "Environment File";
|
||||||
|
|
||||||
|
openFirewall = mkBoolOpt true "Open the firewall";
|
||||||
|
|
||||||
|
enableVpn = mkBoolOpt true "Enable routing through VPN";
|
||||||
|
|
||||||
|
redis = {
|
||||||
|
enable = lib.mkEnableOption "enable redis";
|
||||||
|
|
||||||
|
port = mkOpt types.int 80 "Port for ${name} redis to be hosted on";
|
||||||
|
};
|
||||||
|
|
||||||
|
hashedPassword =
|
||||||
|
mkOpt (types.nullOr types.str)
|
||||||
|
"$y$j9T$EkPXmsmIMFFZ.WRrBYCxS1$P0kwo6e4.WM5DsqUcEqWC3MrZp5KfCjxffraMFZWu06"
|
||||||
|
"Hashed password for code-server authentication";
|
||||||
|
|
||||||
|
extraEnvironment =
|
||||||
|
mkOpt (types.attrsOf types.str) { }
|
||||||
|
"Extra environment variables for code-server";
|
||||||
|
|
||||||
|
reverseProxy = mkReverseProxyOpt name;
|
||||||
|
}
|
||||||
|
// options;
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable defaultConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
# container
|
||||||
|
mkContainer =
|
||||||
|
{
|
||||||
|
name,
|
||||||
|
localAddress ? "127.0.0.1",
|
||||||
|
ports ? [ 80 ],
|
||||||
|
bindMounts ? { },
|
||||||
|
config ? { },
|
||||||
|
}:
|
||||||
|
{ lib, ... }:
|
||||||
|
{
|
||||||
|
containers.${name} = {
|
||||||
|
inherit localAddress bindMounts;
|
||||||
|
|
||||||
|
config = config // {
|
||||||
|
networking = {
|
||||||
|
firewall = {
|
||||||
|
enable = true;
|
||||||
|
allowedTCPPorts = ports;
|
||||||
|
};
|
||||||
|
# Use systemd-resolved inside the container
|
||||||
|
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
|
||||||
|
useHostResolvConf = lib.mkForce false;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.resolved.enable = true;
|
||||||
|
system.stateVersion = "23.11";
|
||||||
|
};
|
||||||
|
autoStart = lib.mkDefault true;
|
||||||
|
privateNetwork = lib.mkDefault true;
|
||||||
|
hostAddress = lib.mkDefault "10.0.1.3";
|
||||||
|
};
|
||||||
|
|
||||||
|
networking = {
|
||||||
|
nat.forwardPorts = map (port: {
|
||||||
|
destination = lib.mkDefault "${localAddress}:${toString port}";
|
||||||
|
sourcePort = lib.mkDefault port;
|
||||||
|
}) ports;
|
||||||
|
firewall = {
|
||||||
|
allowedTCPPorts = ports;
|
||||||
|
allowedUDPPorts = ports;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Migrated mjallen utilities
|
||||||
|
# Option creation helpers
|
||||||
|
mkOpt =
|
||||||
|
type: default: description:
|
||||||
|
mkOption { inherit type default description; };
|
||||||
|
|
||||||
|
mkOpt' = type: default: mkOpt type default null;
|
||||||
|
|
||||||
|
mkBoolOpt = mkOpt types.bool;
|
||||||
|
|
||||||
|
mkBoolOpt' = mkOpt' types.bool;
|
||||||
|
|
||||||
|
mkReverseProxyOpt = name: {
|
||||||
|
enable = mkBoolOpt false "Enable reverse proxy support";
|
||||||
|
|
||||||
|
subdomain = mkOpt types.str name "subdomain of the service";
|
||||||
|
|
||||||
|
middlewares = mkOpt (types.listOf types.str) [
|
||||||
|
"crowdsec"
|
||||||
|
"whitelist-geoblock"
|
||||||
|
] "List of middlewares to use";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Standard enable/disable patterns
|
||||||
|
enabled = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
disabled = {
|
||||||
|
enable = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
# String utilities
|
||||||
|
capitalize =
|
||||||
|
s:
|
||||||
|
let
|
||||||
|
len = stringLength s;
|
||||||
|
in
|
||||||
|
if len == 0 then "" else (toUpper (substring 0 1 s)) + (substring 1 len s);
|
||||||
|
|
||||||
|
# Boolean utilities
|
||||||
|
boolToNum = bool: if bool then 1 else 0;
|
||||||
|
|
||||||
|
# Attribute manipulation utilities
|
||||||
|
default-attrs = mapAttrs (_key: mkDefault);
|
||||||
|
|
||||||
|
force-attrs = mapAttrs (_key: mkForce);
|
||||||
|
|
||||||
|
nested-default-attrs = mapAttrs (_key: default-attrs);
|
||||||
|
|
||||||
|
nested-force-attrs = mapAttrs (_key: force-attrs);
|
||||||
|
}
|
||||||
|
// base64Lib
|
||||||
220
lib/reverseproxy/default.nix
Normal file
220
lib/reverseproxy/default.nix
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
{ inputs }:
|
||||||
|
let
|
||||||
|
inherit (inputs.nixpkgs.lib)
|
||||||
|
listToAttrs
|
||||||
|
nameValuePair
|
||||||
|
;
|
||||||
|
in
|
||||||
|
rec {
|
||||||
|
# Create a service configuration for Traefik
|
||||||
|
mkService =
|
||||||
|
{
|
||||||
|
name,
|
||||||
|
url,
|
||||||
|
loadBalancer ? { },
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
inherit name url;
|
||||||
|
config = {
|
||||||
|
loadBalancer = {
|
||||||
|
servers = [ { inherit url; } ];
|
||||||
|
}
|
||||||
|
// loadBalancer;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Create a router configuration for Traefik
|
||||||
|
mkRouter =
|
||||||
|
{
|
||||||
|
subdomain,
|
||||||
|
domain ? "mjallen.dev",
|
||||||
|
service,
|
||||||
|
entryPoints ? [ "websecure" ],
|
||||||
|
middlewares ? [
|
||||||
|
"crowdsec"
|
||||||
|
"whitelist-geoblock"
|
||||||
|
],
|
||||||
|
priority ? null,
|
||||||
|
rule ? null,
|
||||||
|
tls ? {
|
||||||
|
certResolver = "letsencrypt";
|
||||||
|
},
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
inherit
|
||||||
|
subdomain
|
||||||
|
service
|
||||||
|
entryPoints
|
||||||
|
middlewares
|
||||||
|
;
|
||||||
|
config = {
|
||||||
|
inherit
|
||||||
|
entryPoints
|
||||||
|
service
|
||||||
|
middlewares
|
||||||
|
tls
|
||||||
|
;
|
||||||
|
rule = if rule != null then rule else "Host(`${subdomain}.${domain}`)";
|
||||||
|
}
|
||||||
|
// (if priority != null then { inherit priority; } else { });
|
||||||
|
};
|
||||||
|
|
||||||
|
# Create both service and router for a simple reverse proxy setup
|
||||||
|
mkReverseProxy =
|
||||||
|
{
|
||||||
|
name,
|
||||||
|
subdomain,
|
||||||
|
url,
|
||||||
|
domain ? "mjallen.dev",
|
||||||
|
entryPoints ? [ "websecure" ],
|
||||||
|
middlewares ? [
|
||||||
|
"crowdsec"
|
||||||
|
"whitelist-geoblock"
|
||||||
|
],
|
||||||
|
priority ? null,
|
||||||
|
rule ? null,
|
||||||
|
tls ? {
|
||||||
|
certResolver = "letsencrypt";
|
||||||
|
},
|
||||||
|
loadBalancer ? { },
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
service = mkService {
|
||||||
|
inherit name url loadBalancer;
|
||||||
|
};
|
||||||
|
router = mkRouter {
|
||||||
|
inherit
|
||||||
|
subdomain
|
||||||
|
domain
|
||||||
|
entryPoints
|
||||||
|
middlewares
|
||||||
|
priority
|
||||||
|
rule
|
||||||
|
tls
|
||||||
|
;
|
||||||
|
service = name;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Convert a list of services to the format expected by Traefik module
|
||||||
|
servicesToConfig =
|
||||||
|
services: listToAttrs (map (service: nameValuePair service.name service.config) services);
|
||||||
|
|
||||||
|
# Convert a list of routers to the format expected by Traefik module
|
||||||
|
routersToConfig =
|
||||||
|
routers: listToAttrs (map (router: nameValuePair router.subdomain router.config) routers);
|
||||||
|
|
||||||
|
# Helper to create multiple reverse proxies at once
|
||||||
|
mkReverseProxies =
|
||||||
|
proxies:
|
||||||
|
let
|
||||||
|
results = map mkReverseProxy proxies;
|
||||||
|
services = map (result: result.service) results;
|
||||||
|
routers = map (result: result.router) results;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services = servicesToConfig services;
|
||||||
|
routers = routersToConfig routers;
|
||||||
|
extraServices = services;
|
||||||
|
extraRouters = map (router: {
|
||||||
|
inherit (router) subdomain entryPoints middlewares;
|
||||||
|
service = router.service;
|
||||||
|
}) routers;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Common middleware configurations
|
||||||
|
middlewares = {
|
||||||
|
# Authentication middleware
|
||||||
|
auth = [ "authentik" ];
|
||||||
|
|
||||||
|
# Basic security (default)
|
||||||
|
basic = [
|
||||||
|
"crowdsec"
|
||||||
|
"whitelist-geoblock"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Internal only access
|
||||||
|
internal = [
|
||||||
|
"crowdsec"
|
||||||
|
"whitelist-geoblock"
|
||||||
|
"internal-ipallowlist"
|
||||||
|
];
|
||||||
|
|
||||||
|
# WebSocket support
|
||||||
|
websocket = [
|
||||||
|
"crowdsec"
|
||||||
|
"whitelist-geoblock"
|
||||||
|
"onlyoffice-websocket"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Authenticated with basic security
|
||||||
|
authBasic = [
|
||||||
|
"crowdsec"
|
||||||
|
"whitelist-geoblock"
|
||||||
|
"authentik"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Common service URL builders
|
||||||
|
urls = {
|
||||||
|
# Local container service
|
||||||
|
container =
|
||||||
|
containerName: port: "http://\${config.containers.${containerName}.localAddress}:${toString port}";
|
||||||
|
|
||||||
|
# Local host service
|
||||||
|
localhost = port: "http://127.0.0.1:${toString port}";
|
||||||
|
|
||||||
|
# Network service
|
||||||
|
network = ip: port: "http://${ip}:${toString port}";
|
||||||
|
|
||||||
|
# Server IP service (using your server IP pattern)
|
||||||
|
server = port: "http://\${serverIp}:${toString port}";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Pre-configured reverse proxy templates
|
||||||
|
templates = {
|
||||||
|
# Standard web application
|
||||||
|
webapp =
|
||||||
|
{ port, ... }@args:
|
||||||
|
mkReverseProxy (
|
||||||
|
{
|
||||||
|
url = urls.localhost port;
|
||||||
|
middlewares = middlewares.basic;
|
||||||
|
}
|
||||||
|
// args
|
||||||
|
);
|
||||||
|
|
||||||
|
# Authenticated web application
|
||||||
|
authWebapp =
|
||||||
|
{ port, ... }@args:
|
||||||
|
mkReverseProxy (
|
||||||
|
{
|
||||||
|
url = urls.localhost port;
|
||||||
|
middlewares = middlewares.authBasic;
|
||||||
|
}
|
||||||
|
// args
|
||||||
|
);
|
||||||
|
|
||||||
|
# Container-based service
|
||||||
|
containerService =
|
||||||
|
{ containerName, port, ... }@args:
|
||||||
|
mkReverseProxy (
|
||||||
|
{
|
||||||
|
url = urls.container containerName port;
|
||||||
|
middlewares = middlewares.basic;
|
||||||
|
}
|
||||||
|
// args
|
||||||
|
);
|
||||||
|
|
||||||
|
# Internal-only service
|
||||||
|
internalService =
|
||||||
|
{ port, ... }@args:
|
||||||
|
mkReverseProxy (
|
||||||
|
{
|
||||||
|
url = urls.localhost port;
|
||||||
|
middlewares = middlewares.internal;
|
||||||
|
}
|
||||||
|
// args
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
103
lib/system/common.nix
Normal file
103
lib/system/common.nix
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
{ inputs, namespace }:
|
||||||
|
let
|
||||||
|
inherit (inputs.nixpkgs.lib) filterAttrs mapAttrs';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
mkExtendedLib =
|
||||||
|
flake: nixpkgs:
|
||||||
|
nixpkgs.lib.extend (
|
||||||
|
_final: _prev: {
|
||||||
|
mjallen = flake.${namespace} - lib;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
mkNixpkgsConfig = flake: {
|
||||||
|
overlays = builtins.attrValues flake.overlays;
|
||||||
|
config = {
|
||||||
|
allowAliases = false;
|
||||||
|
allowUnfree = true;
|
||||||
|
permittedInsecurePackages = [
|
||||||
|
# Add any permitted insecure packages here
|
||||||
|
"mbedtls-2.28.10"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mkHomeConfigs =
|
||||||
|
{
|
||||||
|
flake,
|
||||||
|
system,
|
||||||
|
hostname,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (flake.${namespace} - lib.file) scanHomes;
|
||||||
|
homesPath = ../../homes;
|
||||||
|
allHomes = scanHomes homesPath;
|
||||||
|
in
|
||||||
|
filterAttrs (
|
||||||
|
_name: homeConfig: homeConfig.system == system && homeConfig.hostname == hostname
|
||||||
|
) allHomes;
|
||||||
|
|
||||||
|
mkHomeManagerConfig =
|
||||||
|
{
|
||||||
|
extendedLib,
|
||||||
|
inputs,
|
||||||
|
system,
|
||||||
|
matchingHomes,
|
||||||
|
isNixOS ? true,
|
||||||
|
}:
|
||||||
|
if matchingHomes != { } then
|
||||||
|
{
|
||||||
|
home-manager = {
|
||||||
|
useGlobalPkgs = true;
|
||||||
|
useUserPackages = true;
|
||||||
|
extraSpecialArgs = {
|
||||||
|
inherit inputs system;
|
||||||
|
inherit (inputs) self;
|
||||||
|
lib = extendedLib;
|
||||||
|
};
|
||||||
|
sharedModules = [
|
||||||
|
{ _module.args.lib = extendedLib; }
|
||||||
|
]
|
||||||
|
++ (extendedLib.${namespace}.file.importModulesRecursive ../../modules/home);
|
||||||
|
users = mapAttrs' (_name: homeConfig: {
|
||||||
|
name = homeConfig.username;
|
||||||
|
value = {
|
||||||
|
imports = [ homeConfig.path ];
|
||||||
|
home = {
|
||||||
|
inherit (homeConfig) username;
|
||||||
|
homeDirectory = inputs.nixpkgs.lib.mkDefault (
|
||||||
|
if isNixOS then "/home/${homeConfig.username}" else "/Users/${homeConfig.username}"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// (
|
||||||
|
if isNixOS then
|
||||||
|
{
|
||||||
|
_module.args.username = homeConfig.username;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ }
|
||||||
|
);
|
||||||
|
}) matchingHomes;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ };
|
||||||
|
|
||||||
|
mkSpecialArgs =
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
hostname,
|
||||||
|
username,
|
||||||
|
extendedLib,
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
inherit inputs hostname username;
|
||||||
|
inherit (inputs) self;
|
||||||
|
lib = extendedLib;
|
||||||
|
namespace = "mjallen";
|
||||||
|
format = "system";
|
||||||
|
host = hostname;
|
||||||
|
};
|
||||||
|
}
|
||||||
5
lib/system/default.nix
Normal file
5
lib/system/default.nix
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{ inputs }:
|
||||||
|
{
|
||||||
|
# Common utilities used by system builders
|
||||||
|
common = import ./common.nix { inherit inputs; };
|
||||||
|
}
|
||||||
212
lib/versioning/default.nix
Normal file
212
lib/versioning/default.nix
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
inputs,
|
||||||
|
system ? "aarch64-linux",
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
pkgs = inputs.nixpkgs.legacyPackages.${system};
|
||||||
|
in
|
||||||
|
let
|
||||||
|
inherit (builtins)
|
||||||
|
isAttrs
|
||||||
|
isList
|
||||||
|
isString
|
||||||
|
hasAttr
|
||||||
|
getAttr
|
||||||
|
attrNames
|
||||||
|
toString
|
||||||
|
replaceStrings
|
||||||
|
;
|
||||||
|
|
||||||
|
mapAttrs = lib.mapAttrs;
|
||||||
|
recursiveUpdate = lib.recursiveUpdate;
|
||||||
|
|
||||||
|
# Deep-merge attrsets (right-biased).
|
||||||
|
deepMerge = a: b: recursiveUpdate a b;
|
||||||
|
|
||||||
|
# Merge component sources: base.sources overlaid by overrides (component-wise deep merge).
|
||||||
|
mergeSources =
|
||||||
|
baseSources: overrides:
|
||||||
|
baseSources
|
||||||
|
// mapAttrs (
|
||||||
|
name: ov: if hasAttr name baseSources then deepMerge (getAttr name baseSources) ov else ov
|
||||||
|
) overrides;
|
||||||
|
|
||||||
|
# Apply a single variant overlay (variables + sources).
|
||||||
|
applyVariantOnce =
|
||||||
|
selected: variant:
|
||||||
|
let
|
||||||
|
vVars = if variant ? variables then variant.variables else { };
|
||||||
|
vSrcs = if variant ? sources then variant.sources else { };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
variables = selected.variables // vVars;
|
||||||
|
sources = mergeSources selected.sources vSrcs;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Apply platform-specific overrides if present for the given system.
|
||||||
|
applyPlatforms =
|
||||||
|
selected: variant: system:
|
||||||
|
if system == null || !(variant ? platforms) || !(hasAttr system variant.platforms) then
|
||||||
|
selected
|
||||||
|
else
|
||||||
|
let
|
||||||
|
p = variant.platforms.${system};
|
||||||
|
pVars = if p ? variables then p.variables else { };
|
||||||
|
pSrcs = if p ? sources then p.sources else { };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
variables = selected.variables // pVars;
|
||||||
|
sources = mergeSources selected.sources pSrcs;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Resolve variant chain via inherits (ancestor first), then apply platforms.
|
||||||
|
resolveVariant =
|
||||||
|
spec: baseSelected: variantName: system:
|
||||||
|
if variantName == null || !(spec ? variants) || !(hasAttr variantName spec.variants) then
|
||||||
|
baseSelected
|
||||||
|
else
|
||||||
|
let
|
||||||
|
v = spec.variants.${variantName};
|
||||||
|
parentSelected =
|
||||||
|
if v ? inherits then resolveVariant spec baseSelected v.inherits system else baseSelected;
|
||||||
|
withVariant = applyVariantOnce parentSelected v;
|
||||||
|
in
|
||||||
|
applyPlatforms withVariant v system;
|
||||||
|
|
||||||
|
# Render ${var} substitutions in any string within attrs/lists.
|
||||||
|
renderValue =
|
||||||
|
value: vars:
|
||||||
|
if isString value then
|
||||||
|
let
|
||||||
|
keys = attrNames vars;
|
||||||
|
patterns = map (k: "\${" + k + "}") keys;
|
||||||
|
replacements = map (k: toString (getAttr k vars)) keys;
|
||||||
|
in
|
||||||
|
replaceStrings patterns replacements value
|
||||||
|
else if isAttrs value then
|
||||||
|
mapAttrs (_: v: renderValue v vars) value
|
||||||
|
else if isList value then
|
||||||
|
map (v: renderValue v vars) value
|
||||||
|
else
|
||||||
|
value;
|
||||||
|
|
||||||
|
# Decide fetcher for URL type based on optional extra.unpack hint.
|
||||||
|
useFetchZip = comp: comp ? extra && comp.extra ? unpack && comp.extra.unpack == "zip";
|
||||||
|
|
||||||
|
# Build a single src from a rendered component spec.
|
||||||
|
mkSrcFromRendered =
|
||||||
|
comp:
|
||||||
|
let
|
||||||
|
fetcher = if comp ? fetcher then comp.fetcher else "none";
|
||||||
|
in
|
||||||
|
if fetcher == "github" then
|
||||||
|
pkgs.fetchFromGitHub (
|
||||||
|
{
|
||||||
|
owner = comp.owner;
|
||||||
|
repo = comp.repo;
|
||||||
|
# Allow tag as rev (ignore null/empty tag)
|
||||||
|
rev = if comp ? tag && comp.tag != null && comp.tag != "" then comp.tag else comp.rev;
|
||||||
|
fetchSubmodules = if comp ? submodules then comp.submodules else false;
|
||||||
|
hash = comp.hash;
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs (comp ? name) { name = comp.name; }
|
||||||
|
)
|
||||||
|
else if fetcher == "git" then
|
||||||
|
pkgs.fetchgit {
|
||||||
|
url = comp.url;
|
||||||
|
rev = comp.rev;
|
||||||
|
fetchSubmodules = if comp ? submodules then comp.submodules else false;
|
||||||
|
hash = comp.hash;
|
||||||
|
}
|
||||||
|
else if fetcher == "url" then
|
||||||
|
let
|
||||||
|
url = if comp ? url then comp.url else comp.urlTemplate;
|
||||||
|
in
|
||||||
|
if useFetchZip comp then
|
||||||
|
pkgs.fetchzip (
|
||||||
|
{
|
||||||
|
inherit url;
|
||||||
|
hash = comp.hash;
|
||||||
|
}
|
||||||
|
// lib.optionalAttrs (comp ? extra && comp.extra ? stripRoot) { stripRoot = comp.extra.stripRoot; }
|
||||||
|
)
|
||||||
|
else
|
||||||
|
pkgs.fetchurl {
|
||||||
|
inherit url;
|
||||||
|
hash = comp.hash;
|
||||||
|
}
|
||||||
|
else if fetcher == "pypi" then
|
||||||
|
pkgs.python3Packages.fetchPypi {
|
||||||
|
pname = comp.name;
|
||||||
|
version = comp.version;
|
||||||
|
hash = comp.hash;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# fetcher == "none": pass-through (e.g., linux version/hash consumed by custom logic)
|
||||||
|
comp;
|
||||||
|
|
||||||
|
in
|
||||||
|
rec {
|
||||||
|
/*
|
||||||
|
Select a variant from a loaded version.json specification.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
let selected = versioning.selectVariant spec variantName system;
|
||||||
|
- spec: attrset from lib.importJSON ./version.json
|
||||||
|
- variantName: string or null (when null, uses spec.defaultVariant if present)
|
||||||
|
- system: string like "x86_64-linux" or null (to apply platforms overrides)
|
||||||
|
*/
|
||||||
|
selectVariant =
|
||||||
|
spec: variantName: system:
|
||||||
|
let
|
||||||
|
chosen =
|
||||||
|
if variantName != null then
|
||||||
|
variantName
|
||||||
|
else
|
||||||
|
(if spec ? defaultVariant then spec.defaultVariant else null);
|
||||||
|
baseSelected = {
|
||||||
|
variables = if spec ? variables then spec.variables else { };
|
||||||
|
sources = if spec ? sources then spec.sources else { };
|
||||||
|
};
|
||||||
|
in
|
||||||
|
resolveVariant spec baseSelected chosen system;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Render ${var} template substitutions across any value using provided variables.
|
||||||
|
Strings, attrsets, and lists are traversed.
|
||||||
|
*/
|
||||||
|
render = value: variables: renderValue value variables;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Render a component with variables and then build its src (or pass-through for fetcher "none").
|
||||||
|
Prefer using mkAllSources, which handles rendering for all components.
|
||||||
|
*/
|
||||||
|
mkSrc =
|
||||||
|
comp: variables:
|
||||||
|
let
|
||||||
|
rendered = renderValue comp variables;
|
||||||
|
in
|
||||||
|
mkSrcFromRendered rendered;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Produce an attrset of all sources for a selected spec:
|
||||||
|
mkAllSources selected
|
||||||
|
Where:
|
||||||
|
selected = selectVariant spec variantName system
|
||||||
|
Returns:
|
||||||
|
{ componentName = src | renderedComp (for "none"); ... }
|
||||||
|
*/
|
||||||
|
mkAllSources =
|
||||||
|
selected:
|
||||||
|
mapAttrs (
|
||||||
|
_name: comp:
|
||||||
|
if comp ? fetcher && comp.fetcher == "none" then
|
||||||
|
renderValue comp selected.variables
|
||||||
|
else
|
||||||
|
mkSrc (renderValue comp selected.variables) selected.variables
|
||||||
|
) selected.sources;
|
||||||
|
|
||||||
|
# Expose deepMerge for convenience (right-biased).
|
||||||
|
inherit deepMerge;
|
||||||
|
}
|
||||||
54
modules/darwin/home/default.nix
Normal file
54
modules/darwin/home/default.nix
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
options,
|
||||||
|
namespace,
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
options.${namespace}.home = with lib.types; {
|
||||||
|
configFile = lib.mkOption {
|
||||||
|
type = attrs;
|
||||||
|
default = { };
|
||||||
|
description = "A set of files to be managed by home-manager's <option>xdg.configFile</option>.";
|
||||||
|
};
|
||||||
|
extraOptions = lib.mkOption {
|
||||||
|
type = attrs;
|
||||||
|
default = { };
|
||||||
|
description = "Options to pass directly to home-manager.";
|
||||||
|
};
|
||||||
|
file = lib.mkOption {
|
||||||
|
type = attrs;
|
||||||
|
default = { };
|
||||||
|
description = "A set of files to be managed by home-manager's <option>home.file</option>.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
home-manager = {
|
||||||
|
# enables backing up existing files instead of erroring if conflicts exist
|
||||||
|
backupFileExtension = "backup";
|
||||||
|
|
||||||
|
useGlobalPkgs = true;
|
||||||
|
useUserPackages = true;
|
||||||
|
|
||||||
|
# Pass inputs so external modules can access them
|
||||||
|
extraSpecialArgs = {
|
||||||
|
inherit inputs namespace;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Make ALL external HM modules available globally
|
||||||
|
sharedModules = with inputs; [
|
||||||
|
sops-nix.homeManagerModules.sops
|
||||||
|
nix-plist-manager.homeManagerModules.default
|
||||||
|
nix-index-database.homeModules.nix-index
|
||||||
|
stylix.homeModules.stylix
|
||||||
|
# Add any other external HM modules here
|
||||||
|
];
|
||||||
|
|
||||||
|
users."mattjallen" = lib.mkAliasDefinitions options.${namespace}.home.extraOptions;
|
||||||
|
|
||||||
|
verbose = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
58
modules/darwin/nix/default.nix
Normal file
58
modules/darwin/nix/default.nix
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
nix = {
|
||||||
|
settings = {
|
||||||
|
# extra-sandbox-paths = [ config.programs.ccache.cacheDir ];
|
||||||
|
substituters = [
|
||||||
|
"http://jallen-nas.local:9012/nas-cache"
|
||||||
|
"https://nixos-apple-silicon.cachix.org"
|
||||||
|
"https://nixos-raspberrypi.cachix.org"
|
||||||
|
"https://nix-community.cachix.org"
|
||||||
|
"https://cache.nixos.org/"
|
||||||
|
];
|
||||||
|
trusted-public-keys = [
|
||||||
|
"nas-cache:eK0eRVAt9QNwbkLIyOo9N5Z5+zi6ukI4mSlL196C7Yg="
|
||||||
|
"nixos-apple-silicon.cachix.org-1:8psDu5SA5dAD7qA0zMy5UT292TxeEPzIz8VVEr2Js20="
|
||||||
|
"nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI="
|
||||||
|
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||||
|
];
|
||||||
|
warn-dirty = lib.mkForce false;
|
||||||
|
experimental-features = lib.mkForce [
|
||||||
|
"nix-command"
|
||||||
|
"flakes"
|
||||||
|
];
|
||||||
|
trusted-users = [
|
||||||
|
"@wheel"
|
||||||
|
"@admin"
|
||||||
|
];
|
||||||
|
|
||||||
|
builders-use-substitutes = true;
|
||||||
|
connect-timeout = lib.mkDefault 5;
|
||||||
|
fallback = true;
|
||||||
|
log-lines = lib.mkDefault 25;
|
||||||
|
|
||||||
|
max-free = lib.mkDefault (3000 * 1024 * 1024);
|
||||||
|
min-free = lib.mkDefault (512 * 1024 * 1024);
|
||||||
|
};
|
||||||
|
# Garbage collect automatically every week
|
||||||
|
gc = {
|
||||||
|
automatic = lib.mkDefault true;
|
||||||
|
options = lib.mkDefault "--delete-older-than 30d";
|
||||||
|
};
|
||||||
|
|
||||||
|
optimise.automatic = lib.mkDefault true;
|
||||||
|
};
|
||||||
|
|
||||||
|
nixpkgs = {
|
||||||
|
config = {
|
||||||
|
cudaSupport = lib.mkDefault config.${namespace}.hardware.nvidia.enable;
|
||||||
|
rocmSupport = lib.mkDefault config.${namespace}.hardware.amd.enable;
|
||||||
|
allowUnsupportedSystem = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
13
modules/darwin/programs/ssh/default.nix
Normal file
13
modules/darwin/programs/ssh/default.nix
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
config = {
|
||||||
|
programs.ssh.knownHosts = {
|
||||||
|
desktop = {
|
||||||
|
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPTBMydhOc6SnOdB5WrEd7X07DrboAtagCUgXiOJjLov matt@matt-nixos";
|
||||||
|
};
|
||||||
|
nas = {
|
||||||
|
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIwoHWOLSTGVif9hAhaMLl0qDA4roIzCNuyR6kyIXDOj admin@jallen-nas";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
cfg = config.mjallen.desktop.gnome;
|
cfg = config.${namespace}.desktop.gnome;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [ ./options.nix ];
|
imports = [ ./options.nix ];
|
||||||
@@ -17,7 +23,9 @@ in
|
|||||||
gnomeExtensions.bing-wallpaper-changer
|
gnomeExtensions.bing-wallpaper-changer
|
||||||
gnomeExtensions.dash-to-dock
|
gnomeExtensions.dash-to-dock
|
||||||
gnomeExtensions.dash-to-panel
|
gnomeExtensions.dash-to-panel
|
||||||
|
gnomeExtensions.caffeine
|
||||||
gnomeExtensions.gsconnect
|
gnomeExtensions.gsconnect
|
||||||
|
gnomeExtensions.nasa-apod
|
||||||
gnomeExtensions.random-wallpaper
|
gnomeExtensions.random-wallpaper
|
||||||
gnomeExtensions.tiling-assistant
|
gnomeExtensions.tiling-assistant
|
||||||
gnomeExtensions.user-themes
|
gnomeExtensions.user-themes
|
||||||
@@ -29,17 +37,22 @@ in
|
|||||||
dconf = {
|
dconf = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
"org/gnome/desktop/interface".clock-format = "12h";
|
"io/missioncenter/MissionCenter".performance-page-cpu-graph = 2; # logical processors
|
||||||
"org/gnome/desktop/interface".color-scheme = "prefer-dark";
|
"org/gnome/desktop/interface" = {
|
||||||
"org/gnome/desktop/interface".cursor-theme = lib.mkDefault "macOS";
|
clock-format = "12h";
|
||||||
"org/gnome/desktop/interface".enable-hot-corners = false;
|
color-scheme = "prefer-dark";
|
||||||
"org/gnome/desktop/interface".font-antialiasing = "grayscale";
|
cursor-theme = lib.mkDefault "macOS";
|
||||||
"org/gnome/desktop/interface".font-hinting = "slight";
|
enable-hot-corners = false;
|
||||||
"org/gnome/desktop/interface".gtk-theme = lib.mkDefault "Colloid-Dark";
|
font-antialiasing = "grayscale";
|
||||||
"org/gnome/desktop/interface".icon-theme = lib.mkDefault "Colloid-Dark";
|
font-hinting = "slight";
|
||||||
|
gtk-theme = lib.mkDefault "Colloid-Dark";
|
||||||
|
icon-theme = lib.mkDefault "Colloid-Dark";
|
||||||
|
};
|
||||||
"org/gnome/desktop/peripherals/mouse".accel-profile = "flat";
|
"org/gnome/desktop/peripherals/mouse".accel-profile = "flat";
|
||||||
"org/gnome/desktop/peripherals/touchpad".two-finger-scrolling-enabled = true;
|
"org/gnome/desktop/peripherals/touchpad" = {
|
||||||
"org/gnome/desktop/peripherals/touchpad".tap-to-click = true;
|
two-finger-scrolling-enabled = true;
|
||||||
|
tap-to-click = true;
|
||||||
|
};
|
||||||
"org/gnome/mutter".experimental-features = [
|
"org/gnome/mutter".experimental-features = [
|
||||||
"scale-monitor-framebuffer"
|
"scale-monitor-framebuffer"
|
||||||
"variable-refresh-rate"
|
"variable-refresh-rate"
|
||||||
@@ -48,22 +61,38 @@ in
|
|||||||
"org/gnome/shell".enabled-extensions = [
|
"org/gnome/shell".enabled-extensions = [
|
||||||
"allowlockedremotedesktop@kamens.us"
|
"allowlockedremotedesktop@kamens.us"
|
||||||
"appindicatorsupport@rgcjonas.gmail.com"
|
"appindicatorsupport@rgcjonas.gmail.com"
|
||||||
|
"caffeine@patapon.info"
|
||||||
"user-theme@gnome-shell-extensions.gcampax.github.com"
|
"user-theme@gnome-shell-extensions.gcampax.github.com"
|
||||||
"tiling-assistant@leleat-on-github"
|
"tiling-assistant@leleat-on-github"
|
||||||
"dash-to-dock@micxgx.gmail.com"
|
"dash-to-dock@micxgx.gmail.com"
|
||||||
"BingWallpaper@ineffable-gmail.com"
|
"BingWallpaper@ineffable-gmail.com"
|
||||||
"gsconnect@andyholmes.github.io"
|
"gsconnect@andyholmes.github.io"
|
||||||
];
|
];
|
||||||
"org/gnome/shell/extensions/bingwallpaper".override-lockscreen-blur = true;
|
"org/gnome/shell/extensions/bingwallpaper" = {
|
||||||
"org/gnome/shell/extensions/bingwallpaper".random-mode-enabled = true;
|
override-lockscreen-blur = true;
|
||||||
"org/gnome/shell/extensions/bingwallpaper".revert-to-current-image = false;
|
random-mode-enabled = false;
|
||||||
"org/gnome/shell/extensions/dash-to-panel".primary-monitor = 1;
|
selected-image = "current";
|
||||||
"org/gnome/shell/extensions/dash-to-panel".multi-monitors = false;
|
revert-to-current-image = false;
|
||||||
"org/gnome/shell/extensions/gsconnect".id = "4db35bd2-0dcd-42a3-9f77-ef3e8bb83182";
|
};
|
||||||
"org/gnome/shell/extensions/gsconnect".name = "matt-nixos";
|
"org/gnome/shell/extensions/caffeine" = {
|
||||||
|
enable-fullscreen = true;
|
||||||
|
enable-mpris = true;
|
||||||
|
inhibit-apps = [
|
||||||
|
"horizon-client.desktop"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"org/gnome/shell/extensions/dash-to-panel" = {
|
||||||
|
primary-monitor = 1;
|
||||||
|
multi-monitors = false;
|
||||||
|
};
|
||||||
|
"org/gnome/shell/extensions/gsconnect" = {
|
||||||
|
id = "4db35bd2-0dcd-42a3-9f77-ef3e8bb83182";
|
||||||
|
name = "matt-nixos";
|
||||||
|
};
|
||||||
"org/gnome/shell/extensions/user-theme".name = lib.mkDefault "Colloid-Dark";
|
"org/gnome/shell/extensions/user-theme".name = lib.mkDefault "Colloid-Dark";
|
||||||
|
"org/gnome/system/location".enabled = true;
|
||||||
"org/gtk/settings/file-chooser".clock-format = "12h";
|
"org/gtk/settings/file-chooser".clock-format = "12h";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{ lib, ... }:
|
{ lib, namespace, ... }:
|
||||||
with lib;
|
with lib;
|
||||||
{
|
{
|
||||||
options.mjallen.desktop.gnome = {
|
options.${namespace}.desktop.gnome = {
|
||||||
enable = mkEnableOption "enable gnome settings";
|
enable = mkEnableOption "enable gnome settings";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,403 +0,0 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
cfg = config.mjallen.desktop.hyprland;
|
|
||||||
drawer = "nwg-drawer -fm nautilus -term kitty -mb 10 -mt 10 -ml 10 -mr 10 -pbuseicontheme -i ${cfg.iconThemeName}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./options.nix
|
|
||||||
./packages.nix
|
|
||||||
./theme.nix
|
|
||||||
./variables.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
|
|
||||||
services = {
|
|
||||||
hyprpolkitagent.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
programs = {
|
|
||||||
vscode.profiles.default.userSettings."window"."titleBarStyle" = "custom";
|
|
||||||
};
|
|
||||||
|
|
||||||
wayland.windowManager.hyprland = {
|
|
||||||
enable = true;
|
|
||||||
xwayland.enable = true;
|
|
||||||
systemd.enable = true;
|
|
||||||
|
|
||||||
plugins = with pkgs.hyprlandPlugins; [
|
|
||||||
hyprgrass
|
|
||||||
];
|
|
||||||
|
|
||||||
settings = {
|
|
||||||
"$mod" = "SUPER";
|
|
||||||
|
|
||||||
# Mouse
|
|
||||||
# mouse_[up|down] - scroll wheel
|
|
||||||
# middle_mouse - 274
|
|
||||||
# thumb_up - 276
|
|
||||||
# thumb_down - 275
|
|
||||||
|
|
||||||
# l -> locked, will also work when an input inhibitor (e.g. a lockscreen) is active.
|
|
||||||
# r -> release, will trigger on release of a key.
|
|
||||||
# e -> repeat, will repeat when held.
|
|
||||||
# n -> non-consuming, key/mouse events will be passed to the active window in addition to triggering the dispatcher.
|
|
||||||
# m -> mouse, see below.
|
|
||||||
# t -> transparent, cannot be shadowed by other binds.
|
|
||||||
# i -> ignore mods, will ignore modifiers.
|
|
||||||
# s -> separate, will arbitrarily combine keys between each mod/key, see [Keysym combos](#keysym-combos) above.
|
|
||||||
# d -> has description, will allow you to write a description for your bind.
|
|
||||||
# p -> bypasses the app's requests to inhibit keybinds.
|
|
||||||
|
|
||||||
# https://wiki.hyprland.org/Configuring/Binds/
|
|
||||||
# https://wiki.hyprland.org/Configuring/Binds/#mouse-buttons
|
|
||||||
|
|
||||||
bind = [
|
|
||||||
"$mod, Return, exec, ${cfg.defaultApps.terminal.pname}"
|
|
||||||
"$mod, SPACE, exec, wofi --show drun"
|
|
||||||
", xf86Search, exec, wofi --show drun"
|
|
||||||
"$mod, Q, killactive, "
|
|
||||||
"$mod, M, exec, wlogout --protocol layer-shell"
|
|
||||||
"$mod, E, exec, ${cfg.defaultApps.fileExplorer.pname}"
|
|
||||||
"$mod, V, togglefloating, "
|
|
||||||
"$mod, D, exec, ${drawer}"
|
|
||||||
"$mod, P, pseudo, " # dwindle
|
|
||||||
"$mod, S, togglesplit, " # dwindle
|
|
||||||
"$mod SHIFT, Q, exec, hyprlock"
|
|
||||||
"$mod SHIFT, 4, exec, hyprshot -m region --clipboard-only"
|
|
||||||
"$mod, F, fullscreen, 1"
|
|
||||||
"$mod SHIFT, F, fullscreen, 0"
|
|
||||||
"$mod SHIFT, E, exec, smile"
|
|
||||||
|
|
||||||
"$mod, mouse:276, movecurrentworkspacetomonitor, ${cfg.display1.input}"
|
|
||||||
"$mod, mouse:275, movecurrentworkspacetomonitor, ${cfg.display2.input}"
|
|
||||||
|
|
||||||
# alt-tab between workspaces on active monitor
|
|
||||||
"$mod, Tab, workspace, m+1"
|
|
||||||
"$mod SHIFT, Tab, workspace, m-1"
|
|
||||||
|
|
||||||
"$mod, h, movefocus, l"
|
|
||||||
"$mod, l, movefocus, r"
|
|
||||||
"$mod, k, movefocus, u"
|
|
||||||
"$mod, j, movefocus, d"
|
|
||||||
|
|
||||||
"$mod, 1, workspace, 1"
|
|
||||||
"$mod, 2, workspace, 2"
|
|
||||||
"$mod, 3, workspace, 3"
|
|
||||||
"$mod, 4, workspace, 4"
|
|
||||||
"$mod, 5, workspace, 5"
|
|
||||||
"$mod, 6, workspace, 6"
|
|
||||||
"$mod, 7, workspace, 7"
|
|
||||||
"$mod, 8, workspace, 8"
|
|
||||||
"$mod, 9, workspace, 9"
|
|
||||||
"$mod, 0, workspace, 10"
|
|
||||||
|
|
||||||
"$mod ALT, 1, movetoworkspace, 1"
|
|
||||||
"$mod ALT, 2, movetoworkspace, 2"
|
|
||||||
"$mod ALT, 3, movetoworkspace, 3"
|
|
||||||
"$mod ALT, 4, movetoworkspace, 4"
|
|
||||||
"$mod ALT, 5, movetoworkspace, 5"
|
|
||||||
"$mod ALT, 6, movetoworkspace, 6"
|
|
||||||
"$mod ALT, 7, movetoworkspace, 7"
|
|
||||||
"$mod ALT, 8, movetoworkspace, 8"
|
|
||||||
"$mod ALT, 9, movetoworkspace, 9"
|
|
||||||
"$mod ALT, 0, movetoworkspace, discord"
|
|
||||||
|
|
||||||
"$mod CTRL, l, resizeactive, 10 0"
|
|
||||||
"$mod CTRL, h, resizeactive, -10 0"
|
|
||||||
"$mod CTRL, k, resizeactive, 0 -10"
|
|
||||||
"$mod CTRL, j, resizeactive, 0 10"
|
|
||||||
|
|
||||||
"$mod SHIFT, l, movewindow, r"
|
|
||||||
"$mod SHIFT, h, movewindow, l"
|
|
||||||
"$mod SHIFT, k, movewindow, u"
|
|
||||||
"$mod SHIFT, j, movewindow, d"
|
|
||||||
|
|
||||||
"$mod, b, exec, ${cfg.defaultApps.browser.pname}"
|
|
||||||
];
|
|
||||||
|
|
||||||
bindm = [
|
|
||||||
# Move/resize windows with mod + LMB/RMB and dragging
|
|
||||||
"$mod, mouse:272, movewindow"
|
|
||||||
"$mod, mouse:273, resizewindow"
|
|
||||||
# middle mouse will grab a window, mod + middle mouse will close it
|
|
||||||
"$mod SHIFT, mouse:274, movewindow"
|
|
||||||
];
|
|
||||||
|
|
||||||
bindel = [
|
|
||||||
", XF86AudioRaiseVolume, exec, wpctl set-volume -l 1.5 @DEFAULT_AUDIO_SINK@ 5%+"
|
|
||||||
", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"
|
|
||||||
];
|
|
||||||
|
|
||||||
bindl = [
|
|
||||||
", XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
|
|
||||||
", XF86AudioPlay, exec, playerctl play-pause"
|
|
||||||
", XF86AudioPrev, exec, playerctl previous"
|
|
||||||
", XF86AudioNext, exec, playerctl next"
|
|
||||||
", XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"
|
|
||||||
|
|
||||||
", XF86MonBrightnessUp, exec, brightnessctl set +5%"
|
|
||||||
", XF86MonBrightnessDown, exec, brightnessctl set 5%-"
|
|
||||||
|
|
||||||
"$mod, XF86MonBrightnessUp, exec, brightnessctl -d kbd_backlight set +10%"
|
|
||||||
"$mod, XF86MonBrightnessDown, exec, brightnessctl -d kbd_backlight set 10%-"
|
|
||||||
];
|
|
||||||
|
|
||||||
monitor = cfg.monitor;
|
|
||||||
monitorv2 = cfg.monitorv2 or { };
|
|
||||||
|
|
||||||
render = {
|
|
||||||
cm_fs_passthrough = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
misc = {
|
|
||||||
vrr = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
general = {
|
|
||||||
gaps_in = 5;
|
|
||||||
gaps_out = 10;
|
|
||||||
border_size = 1;
|
|
||||||
"col.active_border" = "rgb(8aadf4) rgb(24273A) rgb(24273A) rgb(8aadf4) 45deg";
|
|
||||||
"col.inactive_border" = "rgb(24273A) rgb(24273A) rgb(24273A) rgb(24273A) 45deg";
|
|
||||||
layout = "dwindle";
|
|
||||||
allow_tearing = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
decoration = {
|
|
||||||
rounding = 10;
|
|
||||||
blur = {
|
|
||||||
enabled = true;
|
|
||||||
size = 2;
|
|
||||||
passes = 2;
|
|
||||||
new_optimizations = true;
|
|
||||||
xray = false;
|
|
||||||
};
|
|
||||||
# drop_shadow = "yes";
|
|
||||||
# shadow_range = 4;
|
|
||||||
# shadow_render_power = "3";
|
|
||||||
# "col.shadow" = "rgba(1a1a1aee)";
|
|
||||||
};
|
|
||||||
|
|
||||||
animations = {
|
|
||||||
enabled = "yes";
|
|
||||||
bezier = [
|
|
||||||
"overshot, 0.05, 0.9, 0.1, 1.05"
|
|
||||||
"smoothOut, 0.36, 0, 0.66, -0.56"
|
|
||||||
"smoothIn, 0.25, 1, 0.5, 1"
|
|
||||||
];
|
|
||||||
animation = [
|
|
||||||
"windows, 1, 5, overshot, slide"
|
|
||||||
"windowsOut, 1, 4, smoothOut, slide"
|
|
||||||
"windowsMove, 1, 4, default"
|
|
||||||
"border, 1, 10, default"
|
|
||||||
"fade, 1, 10, smoothIn"
|
|
||||||
"fadeDim, 1, 10, smoothIn"
|
|
||||||
"workspaces, 1, 6, default"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
dwindle = {
|
|
||||||
pseudotile = "yes";
|
|
||||||
preserve_split = "yes";
|
|
||||||
};
|
|
||||||
|
|
||||||
misc = {
|
|
||||||
force_default_wallpaper = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
workspace = cfg.workspace;
|
|
||||||
|
|
||||||
windowrule = [
|
|
||||||
"float, title:(file_progress)"
|
|
||||||
"float, title:(.*[Cc]onfirm.*)"
|
|
||||||
"float, title:(.*[Dd]ialog.*)"
|
|
||||||
"float, title:(.*[Dd]ownload.*)"
|
|
||||||
"float, title:(.*[Nn]otification.*)"
|
|
||||||
"float, title:(.*[Ee]rror.*)"
|
|
||||||
"float, title:(.*[Ss]plash.*)"
|
|
||||||
"float, title:(.*[Cc]onfirmreset.*)"
|
|
||||||
"float, title:(.*[Ss]ign [Ii]n - .*)"
|
|
||||||
"float, title:(.*[Oo]pen [Ff]ile.*)"
|
|
||||||
"float, title:(.*branchdialog.*)"
|
|
||||||
"float, class:(.*pavucontrol.*)"
|
|
||||||
"move onscreen cursor 0% 0%, class:(.*pavucontrol.*)"
|
|
||||||
"float, class:(.*[Oo]verskride.*)"
|
|
||||||
"float, class:(.*FileRoller.*)"
|
|
||||||
"float, class:(.*wlogout.*)"
|
|
||||||
"idleinhibit stayfocused, title:(.*mpv.*)"
|
|
||||||
|
|
||||||
"float, class:(.*nm-connection-editor.*)"
|
|
||||||
"move onscreen cursor 0% 0%, class:(.*nm-connection-editor.*)"
|
|
||||||
|
|
||||||
"float, title:(Media viewer)"
|
|
||||||
"float, class:(it.mijorus.smile),title:(Smile)"
|
|
||||||
"float, class:(.blueman-manager-wrapped)$,title:(Bluetooth Devices)"
|
|
||||||
# Picture in picture windows
|
|
||||||
"float, title:(.*Picture-in-Picture.*)"
|
|
||||||
"pin, title::(.*Picture-in-Picture.*)"
|
|
||||||
|
|
||||||
# discord/vesktop
|
|
||||||
"workspace: name:discord, class:(.*vesktop)"
|
|
||||||
"float, class:(.*vesktop),title:(.*Discord Popout.*)"
|
|
||||||
"pin, class:(.*vesktop),title:(.*Discord Popout.*)"
|
|
||||||
|
|
||||||
# Music
|
|
||||||
"workspace: name:discord, class:(Apple Music.*)"
|
|
||||||
|
|
||||||
# Steam
|
|
||||||
"float, class:(.*[Ss]team), title:(.*[Ss]team.*)$"
|
|
||||||
"workspace name:steam silent, class:(.*[Ss]team), title:(.*[Ss]team.*)$"
|
|
||||||
"tile, class:(.*[Ss]team), title:(.*[Ss]team.*)$"
|
|
||||||
"float, class:(.*steam),title:(.*Friends List.*)"
|
|
||||||
|
|
||||||
# Code
|
|
||||||
"pin, class:(.*codium.*),title:(Save As)"
|
|
||||||
"float, class:(.*codium.*),title:(Save As)"
|
|
||||||
"float, class:(xdg-desktop-portal-gtk),title:(Open Workspace from File)"
|
|
||||||
|
|
||||||
# Game Tearing??? https://wiki.hyprland.org/Configuring/Tearing/
|
|
||||||
"immediate, class:(.*gamescope)"
|
|
||||||
|
|
||||||
# vmware
|
|
||||||
# this tag will set the below options to the vdi window
|
|
||||||
# this will have it auto open as a 2160x7680 window
|
|
||||||
# and makes multi-monitor work
|
|
||||||
"tag +horizonrdp, class:(.*[Vv][Mm]ware-view),title:(USPS Next VDI)"
|
|
||||||
|
|
||||||
"noanim, tag:horizonrdp"
|
|
||||||
"noblur, tag:horizonrdp"
|
|
||||||
"norounding, tag:horizonrdp"
|
|
||||||
"noshadow, tag:horizonrdp"
|
|
||||||
"immediate, tag:horizonrdp"
|
|
||||||
"allowsinput, tag:horizonrdp"
|
|
||||||
"noborder, tag:horizonrdp"
|
|
||||||
"nodim, tag:horizonrdp"
|
|
||||||
"nomaxsize, tag:horizonrdp"
|
|
||||||
"renderunfocused, tag:horizonrdp"
|
|
||||||
"idleinhibit, tag:horizonrdp"
|
|
||||||
"float, tag:horizonrdp"
|
|
||||||
# "size 2160 7680, tag:horizonrdp"
|
|
||||||
# "move onscreen 0 0, tag:horizonrdp"
|
|
||||||
# float the vmware window cause its annoying to use in fullscreen
|
|
||||||
"float, class:(.*[Vv][Mm]ware-view),title:([Vv][Mm]ware [Hh]orizon [Cc]lient)"
|
|
||||||
|
|
||||||
"tag +waydroid, class:([Ww]aydroid.*)"
|
|
||||||
"float, tag:waydroid"
|
|
||||||
"pin, tag:waydroid"
|
|
||||||
] ++ cfg.windowRule;
|
|
||||||
|
|
||||||
plugin = {
|
|
||||||
touch_gestures = {
|
|
||||||
# The default sensitivity is probably too low on tablet screens,
|
|
||||||
# I recommend turning it up to 4.0
|
|
||||||
sensitivity = "4.0";
|
|
||||||
|
|
||||||
# must be >= 3
|
|
||||||
workspace_swipe_fingers = "3";
|
|
||||||
|
|
||||||
# switching workspaces by swiping from an edge, this is separate from workspace_swipe_fingers
|
|
||||||
# and can be used at the same time
|
|
||||||
# possible values: l, r, u, or d
|
|
||||||
# to disable it set it to anything else
|
|
||||||
workspace_swipe_edge = "d";
|
|
||||||
|
|
||||||
# in milliseconds
|
|
||||||
long_press_delay = "400";
|
|
||||||
|
|
||||||
# resize windows by long-pressing on window borders and gaps.
|
|
||||||
# If general:resize_on_border is enabled, general:extend_border_grab_area is used for floating
|
|
||||||
# windows
|
|
||||||
resize_on_border_long_press = true;
|
|
||||||
|
|
||||||
# in pixels, the distance from the edge that is considered an edge
|
|
||||||
edge_margin = "10";
|
|
||||||
|
|
||||||
# emulates touchpad swipes when swiping in a direction that does not trigger workspace swipe.
|
|
||||||
# ONLY triggers when finger count is equal to workspace_swipe_fingers
|
|
||||||
#
|
|
||||||
# might be removed in the future in favor of event hooks
|
|
||||||
emulate_touchpad_swipe = false;
|
|
||||||
|
|
||||||
experimental = {
|
|
||||||
# send proper cancel events to windows instead of hacky touch_up events,
|
|
||||||
# NOT recommended as it crashed a few times, once it's stabilized I'll make it the default
|
|
||||||
send_cancel = "0";
|
|
||||||
};
|
|
||||||
|
|
||||||
hyprgrass-bind = [
|
|
||||||
# swipe left from right edge
|
|
||||||
", edge:r:l, workspace, +1"
|
|
||||||
|
|
||||||
# swipe up from bottom edge
|
|
||||||
", edge:d:u, exec, ${cfg.defaultApps.browser.pname}"
|
|
||||||
|
|
||||||
# swipe down from left edge
|
|
||||||
", edge:l:d, exec, pactl set-sink-volume @DEFAULT_SINK@ -4%"
|
|
||||||
|
|
||||||
# swipe down with 4 fingers
|
|
||||||
", swipe:4:d, killactive"
|
|
||||||
|
|
||||||
# swipe diagonally left and down with 3 fingers
|
|
||||||
# l (or r) must come before d and u
|
|
||||||
", swipe:3:ld, exec, foot"
|
|
||||||
|
|
||||||
# tap with 3 fingers
|
|
||||||
", tap:3, exec, foot"
|
|
||||||
|
|
||||||
# longpress can trigger mouse binds:
|
|
||||||
", longpress:2, movewindow"
|
|
||||||
", longpress:3, resizewindow"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
gestures = {
|
|
||||||
workspace_swipe = true;
|
|
||||||
workspace_swipe_cancel_ratio = "0.15";
|
|
||||||
};
|
|
||||||
|
|
||||||
input = {
|
|
||||||
kb_layout = "us";
|
|
||||||
|
|
||||||
kb_variant = "";
|
|
||||||
kb_model = "";
|
|
||||||
kb_options = "";
|
|
||||||
kb_rules = "";
|
|
||||||
|
|
||||||
numlock_by_default = true;
|
|
||||||
|
|
||||||
follow_mouse = 1;
|
|
||||||
|
|
||||||
touchpad = {
|
|
||||||
clickfinger_behavior = 1;
|
|
||||||
natural_scroll = "yes";
|
|
||||||
};
|
|
||||||
|
|
||||||
sensitivity = 0; # -1.0 - 1.0, 0 means no modification.
|
|
||||||
};
|
|
||||||
|
|
||||||
experimental = {
|
|
||||||
xx_color_management_v4 = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
debug = {
|
|
||||||
full_cm_proto = true;
|
|
||||||
disable_logs = true;
|
|
||||||
disable_scale_checks = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
extraConfig = ''
|
|
||||||
exec-once = dbus-update-activation-environment --systemd --all
|
|
||||||
exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
|
|
||||||
exec-once = /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1
|
|
||||||
exec-once = xhost +SI:localuser:root
|
|
||||||
exec-once = nwg-look -a
|
|
||||||
exec-once = nwg-dock-hyprland -d
|
|
||||||
'' + cfg.extraConfig or '''';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
{ lib, pkgs, ... }:
|
|
||||||
with lib;
|
|
||||||
{
|
|
||||||
options.mjallen.desktop.hyprland = {
|
|
||||||
enable = mkEnableOption "enable hyprland desktop";
|
|
||||||
|
|
||||||
primaryDisplay = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "DP-1";
|
|
||||||
};
|
|
||||||
|
|
||||||
display1 = {
|
|
||||||
input = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "DP-1";
|
|
||||||
};
|
|
||||||
|
|
||||||
resolution = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "3840x2160";
|
|
||||||
};
|
|
||||||
|
|
||||||
refreshRate = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "240.00000";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
display2 = {
|
|
||||||
input = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "DP-1";
|
|
||||||
};
|
|
||||||
|
|
||||||
resolution = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "3840x2160";
|
|
||||||
};
|
|
||||||
|
|
||||||
refreshRate = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "240.00000";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
wallpaper = mkOption {
|
|
||||||
type = with types; listOf str;
|
|
||||||
default = [];
|
|
||||||
description = "list of hyprland wallpaper configs";
|
|
||||||
};
|
|
||||||
|
|
||||||
monitor = mkOption {
|
|
||||||
type = with types; listOf str;
|
|
||||||
default = [];
|
|
||||||
description = "list of hyprland monitor configs";
|
|
||||||
};
|
|
||||||
|
|
||||||
monitorv2 = mkOption {
|
|
||||||
type = with types; listOf str;
|
|
||||||
default = [];
|
|
||||||
description = "list of hyprland monitorv2 configs";
|
|
||||||
};
|
|
||||||
|
|
||||||
workspace = mkOption {
|
|
||||||
type = with types; listOf str;
|
|
||||||
default = [];
|
|
||||||
description = "list of hyprland workspace definitions";
|
|
||||||
};
|
|
||||||
|
|
||||||
windowRule = mkOption {
|
|
||||||
type = with types; listOf str;
|
|
||||||
default = [];
|
|
||||||
description = "list of hyprland window rules";
|
|
||||||
};
|
|
||||||
|
|
||||||
extraConfig = mkOption {
|
|
||||||
type = with types; str;
|
|
||||||
default = '''';
|
|
||||||
description = "any extra options";
|
|
||||||
};
|
|
||||||
|
|
||||||
iconThemeName = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "Colloid-Dark";
|
|
||||||
};
|
|
||||||
|
|
||||||
gtkThemeName = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "Colloid-Dark";
|
|
||||||
};
|
|
||||||
|
|
||||||
defaultApps = mkOption {
|
|
||||||
type = types.submodule {
|
|
||||||
options = {
|
|
||||||
browser = mkOption { type = types.package; default = pkgs.firefox; };
|
|
||||||
editor = mkOption { type = types.package; default = pkgs.micro; };
|
|
||||||
fileExplorer = mkOption { type = types.package; default = pkgs.nemo; };
|
|
||||||
visual = mkOption { type = types.package; default = pkgs.vscodium; };
|
|
||||||
terminal = mkOption { type = types.package; default = pkgs.kitty; };
|
|
||||||
office = mkOption { type = types.package; default = pkgs.onlyoffice-bin_latest; };
|
|
||||||
video = mkOption { type = types.package; default = pkgs.vlc; };
|
|
||||||
imageViewer = mkOption { type = types.package; default = pkgs.nomacs; };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
description = "Default applications used across the system.";
|
|
||||||
};
|
|
||||||
|
|
||||||
hyprIdle = {
|
|
||||||
lockScreenTimer = mkOption {
|
|
||||||
type = with types; int;
|
|
||||||
default = 5;
|
|
||||||
};
|
|
||||||
screenOffTimer = mkOption {
|
|
||||||
type = with types; int;
|
|
||||||
default = 15;
|
|
||||||
};
|
|
||||||
suspendTimer = mkOption {
|
|
||||||
type = with types; int;
|
|
||||||
default = 30;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
cfg = config.mjallen.desktop.hyprland;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
home.packages = with pkgs; [
|
|
||||||
box64
|
|
||||||
brightnessctl
|
|
||||||
ddcutil
|
|
||||||
dunst
|
|
||||||
egl-wayland
|
|
||||||
file-roller
|
|
||||||
glib
|
|
||||||
gnome-calculator
|
|
||||||
gnome-calendar
|
|
||||||
gnome-disk-utility
|
|
||||||
gnome-firmware
|
|
||||||
gnome-firmware-updater
|
|
||||||
gnome-font-viewer
|
|
||||||
gnome-logs
|
|
||||||
gnome-photos
|
|
||||||
gnome-tweaks
|
|
||||||
gnome-weather
|
|
||||||
gsettings-desktop-schemas
|
|
||||||
hyprcursor
|
|
||||||
hyprland
|
|
||||||
hyprpaper
|
|
||||||
hyprshot
|
|
||||||
hyprsysteminfo
|
|
||||||
kdePackages.qtmultimedia
|
|
||||||
libnotify
|
|
||||||
libz
|
|
||||||
mako
|
|
||||||
meson
|
|
||||||
nautilus
|
|
||||||
networkmanagerapplet
|
|
||||||
nm-tray
|
|
||||||
nomacs
|
|
||||||
nwg-look
|
|
||||||
overskride
|
|
||||||
pamixer
|
|
||||||
pavucontrol
|
|
||||||
playerctl
|
|
||||||
polkit
|
|
||||||
polkit_gnome
|
|
||||||
qt5.qtwayland
|
|
||||||
qt6.qtwayland
|
|
||||||
rofi-wayland
|
|
||||||
waybar
|
|
||||||
wayland-protocols
|
|
||||||
wayland-utils
|
|
||||||
waypaper
|
|
||||||
wev
|
|
||||||
wl-clipboard
|
|
||||||
wlogout
|
|
||||||
wlroots
|
|
||||||
xdg-desktop-portal-hyprland
|
|
||||||
xdg-desktop-portal-gtk
|
|
||||||
xdg-desktop-portal-wlr
|
|
||||||
xorg.xhost
|
|
||||||
xsettingsd
|
|
||||||
xwayland
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
{ config, lib, namespace, ... }:
|
|
||||||
let
|
|
||||||
cfg = config.${namespace}.desktop.hyprland;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [ ../../options.nix ];
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.hypridle = {
|
|
||||||
enable = false;
|
|
||||||
settings = {
|
|
||||||
general = {
|
|
||||||
before_sleep_cmd = "loginctl lock-session"; # lock before suspend.
|
|
||||||
after_sleep_cmd = "hyprctl dispatch dpms on"; # to avoid having to press a key twice to turn on the display.
|
|
||||||
ignore_dbus_inhibit = false;
|
|
||||||
lock_cmd = "pidof hyprlock || hyprlock"; # avoid starting multiple hyprlock instances.
|
|
||||||
};
|
|
||||||
listener = [
|
|
||||||
# {
|
|
||||||
# timeout = 300; # 5min
|
|
||||||
# on-timeout = "brightnessctl -s set 10"; # set monitor backlight to minimum, avoid 0 on OLED monitor.
|
|
||||||
# on-resume = "brightnessctl -r"; # monitor backlight restore.
|
|
||||||
# }
|
|
||||||
{
|
|
||||||
timeout = cfg.hyprIdle.lockScreenTimer;
|
|
||||||
on-timeout = "loginctl lock-session"; # lock screen when timeout has passed
|
|
||||||
}
|
|
||||||
{
|
|
||||||
timeout = cfg.hyprIdle.screenOffTimer;
|
|
||||||
on-timeout = "hyprctl dispatch dpms off"; # screen off when timeout has passed
|
|
||||||
on-resume = "hyprctl dispatch dpms on"; # screen on when activity is detected after timeout has fired.
|
|
||||||
}
|
|
||||||
{
|
|
||||||
timeout = cfg.hyprIdle.suspendTimer;
|
|
||||||
on-timeout = "systemctl suspend"; # suspend pc
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
{ config, lib, namespace, ... }:
|
|
||||||
let
|
|
||||||
cfg = config.${namespace}.desktop.hyprland;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [ ../../options.nix ];
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
programs.hyprlock = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
background = [
|
|
||||||
{
|
|
||||||
monitor = "";
|
|
||||||
path = cfg.wallpaper; # supports png, jpg, webp (no animations, though)
|
|
||||||
color = "rgba(25, 20, 20, 1.0)";
|
|
||||||
|
|
||||||
# all these options are taken from hyprland, see https://wiki.hyprland.org/Configuring/Variables/#blur for explanations
|
|
||||||
blur_passes = "3"; # 0 disables blurring
|
|
||||||
blur_size = "7";
|
|
||||||
noise = "0.0117";
|
|
||||||
contrast = "0.8916";
|
|
||||||
brightness = "0.8172";
|
|
||||||
vibrancy = "0.1696";
|
|
||||||
vibrancy_darkness = "0.0";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
input-field = [
|
|
||||||
{
|
|
||||||
size = "200, 50";
|
|
||||||
position = "0, -80";
|
|
||||||
monitor = cfg.primaryDisplay;
|
|
||||||
dots_center = true;
|
|
||||||
fade_on_empty = true;
|
|
||||||
font_color = "rgb(202, 211, 245)";
|
|
||||||
inner_color = "rgb(91, 96, 120)";
|
|
||||||
outer_color = "rgb(24, 25, 38)";
|
|
||||||
bothlock_color = -1;
|
|
||||||
outline_thickness = 5;
|
|
||||||
placeholder_text = ''<span foreground="##cad3f5">Password...</span>'';
|
|
||||||
shadow_passes = 2;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{ config, lib, namespace, ... }:
|
|
||||||
let
|
|
||||||
cfg = config.${namespace}.desktop.hyprland;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
imports = [ ../../options.nix ];
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.hyprpaper = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
preload = [ "/run/wallpaper.jpg" ];
|
|
||||||
wallpaper = ",/run/wallpaper.jpg";
|
|
||||||
splash = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
cfg = config.mjallen.desktop.hyprland;
|
|
||||||
|
|
||||||
themeSize = "compact"; # [ "standard" "compact" ]
|
|
||||||
themeAccent = "all"; # [ "default" "purple" "pink" "red" "orange" "yellow" "green" "teal" "grey" "all" ]
|
|
||||||
themeVariant = "nord"; # [ "nord" "dracula" "gruvbox" "everforest" "catppuccin" "all" "black" "rimless" "normal" "float" ]
|
|
||||||
themeColor = "dark"; # [ "standard" "light" "dark" ]
|
|
||||||
iconThemeVariant = "all"; # [ "default" "purple" "pink" "red" "orange" "yellow" "green" "teal" "grey" "all" ]
|
|
||||||
iconScheme = "nord"; # [ "default" "nord" "dracula" "gruvbox" "everforest" "catppuccin" "all" ]
|
|
||||||
|
|
||||||
# Cursor
|
|
||||||
cursorTheme = "macOS";
|
|
||||||
cursorThemePkg = pkgs.apple-cursor;
|
|
||||||
cursorSize = 24;
|
|
||||||
|
|
||||||
# GTK
|
|
||||||
# gtkThemeSize = themeSize;
|
|
||||||
# gtkThemeAccent = themeAccent;
|
|
||||||
# gtkThemeVariant = themeVariant;
|
|
||||||
# gtkThemeColor = themeColor;
|
|
||||||
gtkTheme = "Colloid-Dark-Compact-Nord";
|
|
||||||
gtkThemePkg = pkgs.colloid-gtk-theme.override {
|
|
||||||
sizeVariants = [ themeSize ];
|
|
||||||
colorVariants = [ themeColor ];
|
|
||||||
themeVariants = [ themeAccent ];
|
|
||||||
tweaks = [ themeVariant ];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Icons
|
|
||||||
# iconThemeScheme = iconScheme;
|
|
||||||
iconTheme = "Colloid-Nord-Dark";
|
|
||||||
iconThemePkg = pkgs.colloid-icon-theme.override {
|
|
||||||
schemeVariants = [ iconScheme ];
|
|
||||||
colorVariants = [ iconThemeVariant ];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Fonts
|
|
||||||
fontName = "JetBrainsMono NFM";
|
|
||||||
fontPackage = pkgs.nerd-fonts.jetbrains-mono;
|
|
||||||
fontSize = 12;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
home = {
|
|
||||||
pointerCursor = {
|
|
||||||
gtk.enable = true;
|
|
||||||
package = cursorThemePkg;
|
|
||||||
name = cursorTheme;
|
|
||||||
size = cursorSize;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
dconf = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
"org/gnome/desktop/interface".color-scheme = "prefer-dark";
|
|
||||||
"org/gnome/desktop/interface".cursor-theme = cursorTheme;
|
|
||||||
"org/gnome/desktop/interface".gtk-theme = gtkTheme;
|
|
||||||
"org/gnome/desktop/interface".icon-theme = iconTheme;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
gtk = {
|
|
||||||
enable = true;
|
|
||||||
|
|
||||||
cursorTheme = {
|
|
||||||
name = cursorTheme;
|
|
||||||
package = cursorThemePkg;
|
|
||||||
};
|
|
||||||
|
|
||||||
theme = {
|
|
||||||
name = gtkTheme;
|
|
||||||
package = gtkThemePkg;
|
|
||||||
};
|
|
||||||
|
|
||||||
iconTheme = {
|
|
||||||
name = iconTheme;
|
|
||||||
package = iconThemePkg;
|
|
||||||
};
|
|
||||||
|
|
||||||
gtk3.extraConfig = {
|
|
||||||
gtk-application-prefer-dark-theme = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
gtk4.extraConfig = {
|
|
||||||
gtk-application-prefer-dark-theme = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
font = {
|
|
||||||
name = fontName;
|
|
||||||
package = fontPackage;
|
|
||||||
size = fontSize;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
{ config, lib, ... }:
|
|
||||||
with lib;
|
|
||||||
let
|
|
||||||
cfg = config.mjallen.desktop.hyprland;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
home.sessionVariables = {
|
|
||||||
BROWSER = "${cfg.defaultApps.browser.pname}";
|
|
||||||
CLUTTER_BACKEND = "wayland";
|
|
||||||
EDITOR = "${cfg.defaultApps.editor.pname}";
|
|
||||||
VISUAL = "${cfg.defaultApps.visual.pname}";
|
|
||||||
ICON_THEME = cfg.iconThemeName;
|
|
||||||
GTK_CSD = "0";
|
|
||||||
GTK_THEME = cfg.gtkThemeName;
|
|
||||||
GTK_USE_PORTAL = "1";
|
|
||||||
HYPRCURSOR_THEME = config.home.pointerCursor.name;
|
|
||||||
HYPRCURSOR_SIZE = config.home.pointerCursor.size;
|
|
||||||
MOZ_ENABLE_WAYLAND = "1";
|
|
||||||
NIXOS_OZONE_WL = "1";
|
|
||||||
NIXOS_XDG_OPEN_USE_PORTAL = "1";
|
|
||||||
QT_AUTO_SCREEN_SCALE_FACTOR = "1";
|
|
||||||
QT_QPA_PLATFORM = "wayland-egl";
|
|
||||||
QT_QPA_PLATFORMTHEME = "gtk3";
|
|
||||||
QT_SCALE_FACTOR = "1";
|
|
||||||
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
|
|
||||||
SDL_VIDEODRIVER = "wayland";
|
|
||||||
TERMINAL = "${cfg.defaultApps.terminal.pname}";
|
|
||||||
XCURSOR_THEME = config.home.pointerCursor.name;
|
|
||||||
XCURSOR_SIZE = config.home.pointerCursor.size;
|
|
||||||
XDG_CACHE_HOME = "\${HOME}/.cache";
|
|
||||||
XDG_CONFIG_HOME = "\${HOME}/.config";
|
|
||||||
XDG_CURRENT_DESKTOP = "Hyprland";
|
|
||||||
XDG_DATA_HOME = "\${HOME}/.local/share";
|
|
||||||
XDG_SESSION_DESKTOP = "Hyprland";
|
|
||||||
XDG_SESSION_TYPE = "wayland";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
{
|
|
||||||
# Nord colors
|
|
||||||
# Opacity Hex alpha
|
|
||||||
# 100% FF
|
|
||||||
# 75% BF
|
|
||||||
# 50% 80
|
|
||||||
# 25% 40
|
|
||||||
# 10% 1A
|
|
||||||
# 0% 00
|
|
||||||
polarNight = {
|
|
||||||
nord0 = "#2e3440";
|
|
||||||
nord1 = "#3b4252";
|
|
||||||
nord2 = "#434c5e";
|
|
||||||
nord3 = "#4c566a";
|
|
||||||
};
|
|
||||||
snowStorm = {
|
|
||||||
nord4 = "#d8dee9";
|
|
||||||
nord5 = "#e5e9f0";
|
|
||||||
nord6 = "#eceff4";
|
|
||||||
};
|
|
||||||
frost = {
|
|
||||||
nord7 = "#8fbcbb";
|
|
||||||
nord8 = "#88c0d0";
|
|
||||||
nord9 = "#81a1c1";
|
|
||||||
nord10 = "#5e81ac";
|
|
||||||
};
|
|
||||||
aurora = {
|
|
||||||
nord11 = "#bf616a";
|
|
||||||
nord12 = "#d08770";
|
|
||||||
nord13 = "#ebcb8b";
|
|
||||||
nord14 = "#a3be8c";
|
|
||||||
nord15 = "#b48ead";
|
|
||||||
};
|
|
||||||
|
|
||||||
defaultOpacity = "opacity: 0.85;";
|
|
||||||
defaultBorderRadius = "border-radius: 1rem;";
|
|
||||||
defaultCenterOptions = ''
|
|
||||||
padding-top: 0.2rem;
|
|
||||||
padding-bottom: 0.2rem;
|
|
||||||
padding-left: 0.5rem;
|
|
||||||
padding-right: 0.5rem;
|
|
||||||
margin: 3px 0;
|
|
||||||
'';
|
|
||||||
borderRight = ''
|
|
||||||
padding-top: 0.2rem;
|
|
||||||
padding-bottom: 0.2rem;
|
|
||||||
padding-left: 0.5rem;
|
|
||||||
padding-right: 0.5rem;
|
|
||||||
margin: 3px 0;
|
|
||||||
border-radius: 0rem 1rem 1rem 0rem;
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
'';
|
|
||||||
borderLeft = ''
|
|
||||||
padding-top: 0.2rem;
|
|
||||||
padding-bottom: 0.2rem;
|
|
||||||
padding-left: 0.5rem;
|
|
||||||
padding-right: 0.5rem;
|
|
||||||
margin: 3px 0;
|
|
||||||
border-radius: 1rem 0rem 0rem 1rem;
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
79
modules/home/gpg/default.nix
Normal file
79
modules/home/gpg/default.nix
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
programs = {
|
||||||
|
gpg = {
|
||||||
|
enable = true;
|
||||||
|
scdaemonSettings = {
|
||||||
|
disable-ccid = true;
|
||||||
|
pcsc-shared = true;
|
||||||
|
};
|
||||||
|
publicKeys = [
|
||||||
|
{
|
||||||
|
text = ''
|
||||||
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
|
mQINBGipyhUBEADCal3wKbTCJHZ7qBTxe2zrJPGV9vu6V4+x/MBQq07jd33RrdgI
|
||||||
|
5R/YSviZLyTjY84xk+XTpxWe6PNxcrNlPrJgqR48UNYiG7rH2VWg073KQZaAEeX4
|
||||||
|
DRmfANtds9m9N9CadMv1XcHvVkEz+UlD3yYGNwrd1ZnWVBpUobIyZvFrVjpGBtOg
|
||||||
|
jgW3NepPn9SfguF+PV4t3Tn2iAFsDa/U3RpkMvYtfxgtxJPvbaVNc3Zq7UDWaXta
|
||||||
|
zZ7y/o5figLUn3q/2JrbzeXmNpShkTixXJHJwSjoD/27I6fVFz4EfwkBfyo8B9yX
|
||||||
|
goekY00wym0oIT2Jb5ZLFh8b60mX/ezUJcMhDkqTG77caRDRxw76yVxc0Jp+r+xZ
|
||||||
|
3ckcrdm+/UtnnD3VO0ktvhb4pU93Pj0PJhrm7qVZS/SEJ67vUx8Aem3aMWgSRsl5
|
||||||
|
51h08US7yfPaMNqKX9d2KaLSTGnQ2BSoXJEmbIqvlvazUTqVk85TDWZEYXgc2S2K
|
||||||
|
phyDfJiVmmUWekgrYE/Fyx0QJkCA6z8cNQWwpRe7oJG1VrnRjhIcuL+EpJb9Ytd9
|
||||||
|
NT39/6/rBot2iGmn64vdyqirji2shuLwrp34A9KWY3XUC5zv0GlHCFsF8lraFzKz
|
||||||
|
AsYv2cLRRja4kyuzoSwoHgXYu1MsifZHgF2+Y0sFW+odRqlo0A9ziXkB9QARAQAB
|
||||||
|
tCNNYXR0aGV3IEphbGxlbiA8amFsbGUwMDhAcHJvdG9uLm1lPokCVwQTAQgAQRYh
|
||||||
|
BMvLmximuJMLC2q/0cy4y+swYzaEBQJoqcoVAhsDBQkSzAMABQsJCAcCAiICBhUK
|
||||||
|
CQgLAgQWAgMBAh4HAheAAAoJEMy4y+swYzaEsrkP/3c/kW0QNv79dEgEHhpJy7nP
|
||||||
|
XyB8fTGr804Gq0ffaPgmn0G8iNzg9pgjgrA8oHpoP0ZbmKaO7JkpHsS0+fpMNuFE
|
||||||
|
dhthWgsYLAnC6rZb4Ib/b+wbUH19CJJIt6Rj9uqH3vDCxeG5TfiJnVA+x3O6VaM1
|
||||||
|
K2oyrXaXDrUKxFlLlnMOsdfRZwXoyYPuJm8Lip5GawIakHGV17FdwdZOcfy0JtdH
|
||||||
|
CwI0K5D390lQ2WNjIJx0vI8E3QYubciOjDzS+KNB12q4sSY6O3fKTXsi80JZ/y4C
|
||||||
|
z1dwsRxMlndBbK1SBJFmczRy4dZC0WbNaxEF2qnM7RENDpB+73HQ1/mSsFaTu609
|
||||||
|
9clDDjwCAUu4UrbL5veWLB+b+xUNy6Sgkbal1Q+pgGSTF9H8plGN0ymijC9xNmvX
|
||||||
|
JeeSTvfnzAThiJubIpZYLkoMmlyEiGrc4CQDdfbsVR9xFGZcau5akcW3e45kiOZC
|
||||||
|
is1H55HsXlBpezanvJCnX7ZEQlRP8vdquHADvgERf3D/qlVAgD/lGE8bzBKJxt1P
|
||||||
|
kxXvGZFxF0BCN/GCoYib1w3WJeTyxGlf9wHkwa/COjasEBGzsnkLToET637WdmHr
|
||||||
|
hgnTVm6CQQW4EUw6gOznDNQvd1EipAwJB7iEm2PneEAwauWeQN38+hc7QVIEqXRk
|
||||||
|
wdfxlU/9WD+rh6FfQ7d3uQINBGipyhUBEADUGJQW/FUWo3R6X7+Quv3TqZfVXJB/
|
||||||
|
bjX9Uv8SKOomUBAjQK9TklaZJvNiaD4qYV93kPfpclGhxdGahXVBC7SdGenaFig4
|
||||||
|
4WwUe5vrKIGbbfcC+dBW/8eAqueKjCWe6wFqXbKat1/4Y1atsFZX5Lf/GEi1VNXu
|
||||||
|
0NkSPKAqTdXyXrTuC7D5wARGdavbxO3BcF1NqpIPHiROQoOyP10jx8xcMYGoVIIr
|
||||||
|
uscckoqhdbyEua9m9zFesYyqiCfJeSCK8O4w7BU3dgHUz53hfeuNuGBPb/dQ9Ent
|
||||||
|
qKwrMxsPWJC9qN19Wvvsgy89QLn0CWmcUsmc/f4mWnKoSH9AZCuVCSgoSjknXGj0
|
||||||
|
MPBI6jY1gaqZAuyMH24ekUAdUtNK5IuPPPxrlE1ljAWSxvFGG7Dj4p78ELJizlT7
|
||||||
|
XXOtAPggwCFfXauQD+v43ILg5Zxz6fjTd0TZ8iSypqiZIQgQoiUUGcDZmjHhRHNj
|
||||||
|
GHlqmRECyef6mZVhb3zlyzAcQycnZvHtXFMmyrvfFs21pX9WEF3lQFDapnMAwODE
|
||||||
|
2BLQWrh2ed++/An3DJOh/Iwv9WBatDagMObJi3lsUszJ0l5iwteJOfXMR72zV+m7
|
||||||
|
7QzaEdGFDlNRSMmtjni7FLWbDA/CkihRsUtqgrXgj91oqLga0GmjlNnIZGwhcDUx
|
||||||
|
Yuo+kIRRM4DSDwARAQABiQI8BBgBCAAmFiEEy8ubGKa4kwsLar/RzLjL6zBjNoQF
|
||||||
|
AmipyhUCGwwFCRLMAwAACgkQzLjL6zBjNoS5/Q//SPmdM26wUq50A8QTuQ3r8xpc
|
||||||
|
3oGCdBAP7QJk6+W1kJcGVP4r2bFylbWUGyHWuhKTs47r6fh3Sd9MtmGQgtEEbGFW
|
||||||
|
a4pxaYBRPYGHvJuVwb4IvOzDuVj8yabk0c688jz2Wv1DW3+z4623TI2JeOfEoOqg
|
||||||
|
u4DGySVZkXA/F01HShP0QsGEGRkklEvysD101GbJrQuQ6ssHiFVF1m+/w+I8fYzP
|
||||||
|
F9BC61DOEabm62YjELf/xvKQ6aT8rB0F2p9udOmIlw9lkAJMsEz4mB5f4Bq/1vGt
|
||||||
|
aZ7K0tytT3aeTFFgLwtBPcjWvHavEp4/CDXUL58v/X5R+E6Z03zsWwspsACacblq
|
||||||
|
RW15f3aKI2j7u/w6oJ/iJbEXtZq/Hv1XACyZ/kD9WcYIPsNikCS6vSsnj9Hk/o88
|
||||||
|
yG0rQ6v9L7s9gqWm1IajnDQD6g7n3H4pXGJsE4sBGg6FfE0OJDcd4VqZGJGMz9rr
|
||||||
|
+V+3zUxs/RIVWTCdoVPTLBWrtsKbwObgE7SdkaUt4/1uhtdkR++brhr2uz3il0Kt
|
||||||
|
2QZAXJDcK2xzcOEz41lhclgMxUzjYTggQvpD8lu70xlGqgm94NJCBctPx6xJAN9f
|
||||||
|
H6dELHDuLAwB+vKB9YJIvMVaPNKRam8wGnZ0EKHUFvmIqqSOE8GR1LmgslYRNidv
|
||||||
|
ywgEIPcOpJGzt3TQprM=
|
||||||
|
=i8do
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
|
'';
|
||||||
|
trust = "ultimate";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
gpg-agent = {
|
||||||
|
enable = true;
|
||||||
|
enableZshIntegration = true;
|
||||||
|
enableSshSupport = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,56 +1,96 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
hasDestopEnvironment ? true,
|
||||||
|
system,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib.${namespace}) enabled;
|
||||||
|
isArm = ("aarch64-linux" == system) || ("aarch64-darwin" == system);
|
||||||
|
in
|
||||||
{
|
{
|
||||||
home = {
|
home = {
|
||||||
enableNixpkgsReleaseCheck = lib.mkDefault false;
|
enableNixpkgsReleaseCheck = lib.mkDefault false;
|
||||||
homeDirectory = lib.mkDefault "/home/${config.home.username}";
|
homeDirectory = lib.mkDefault "/home/${config.home.username}";
|
||||||
packages = with pkgs; [
|
packages =
|
||||||
age
|
with pkgs;
|
||||||
chromium
|
[
|
||||||
clinfo
|
age
|
||||||
cpufetch
|
clinfo
|
||||||
deadnix
|
cpufetch
|
||||||
firefox
|
dbus
|
||||||
gamescope
|
deadnix
|
||||||
gamescope-wsi
|
lm_sensors
|
||||||
goverlay
|
nano
|
||||||
gparted
|
nebula
|
||||||
lm_sensors
|
nix-prefetch-scripts
|
||||||
mission-center
|
nixfmt
|
||||||
nano
|
pciutils
|
||||||
nixfmt-rfc-style
|
protonup-ng
|
||||||
pciutils
|
rsync
|
||||||
protonup
|
smartmontools
|
||||||
rsync
|
sops
|
||||||
smartmontools
|
tailscale
|
||||||
sops
|
tree
|
||||||
tailscale
|
usbutils
|
||||||
tree
|
vim
|
||||||
usbutils
|
vulkan-tools
|
||||||
vesktop
|
wget
|
||||||
vim
|
]
|
||||||
vulkan-tools
|
++ (
|
||||||
wget
|
if hasDestopEnvironment then
|
||||||
];
|
[
|
||||||
|
boxbuddy
|
||||||
|
stable.chromium
|
||||||
|
firefox
|
||||||
|
gamescope
|
||||||
|
gamescope-wsi
|
||||||
|
gparted
|
||||||
|
mission-center
|
||||||
|
parted
|
||||||
|
vesktop
|
||||||
|
] ++ (
|
||||||
|
if !isArm then
|
||||||
|
[
|
||||||
|
# goverlay
|
||||||
|
# winboat
|
||||||
|
]
|
||||||
|
else [ ]
|
||||||
|
)
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
);
|
||||||
|
|
||||||
stateVersion = lib.mkDefault "23.11";
|
stateVersion = lib.mkDefault "23.11";
|
||||||
};
|
};
|
||||||
|
|
||||||
programs = {
|
programs = {
|
||||||
btop.enable = lib.mkDefault true;
|
nix-index-database.comma = enabled;
|
||||||
fastfetch.enable = lib.mkDefault true;
|
btop = {
|
||||||
home-manager.enable = lib.mkDefault true;
|
enable = lib.mkDefault true;
|
||||||
|
package = pkgs.unstable.btop;
|
||||||
|
};
|
||||||
|
fastfetch = lib.mkDefault enabled;
|
||||||
|
home-manager = lib.mkDefault enabled;
|
||||||
java = {
|
java = {
|
||||||
enable = lib.mkDefault true;
|
enable = lib.mkDefault true;
|
||||||
};
|
};
|
||||||
mangohud.enable = lib.mkDefault true;
|
mangohud.enable = lib.mkDefault hasDestopEnvironment;
|
||||||
password-store.enable = true;
|
password-store = enabled;
|
||||||
nh = {
|
nh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
flake = "/etc/nixos";
|
flake = "/etc/nixos";
|
||||||
|
clean = {
|
||||||
|
enable = true;
|
||||||
|
extraArgs = "--keep 5";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
micro = {
|
micro = {
|
||||||
enable = true;
|
enable = lib.mkDefault true;
|
||||||
settings = {
|
settings = {
|
||||||
autoindent = true;
|
autoindent = true;
|
||||||
autosu = true;
|
autosu = true;
|
||||||
@@ -61,7 +101,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
tmux = {
|
tmux = {
|
||||||
enable = true;
|
enable = lib.mkDefault true;
|
||||||
terminal = "screen-256color";
|
terminal = "screen-256color";
|
||||||
sensibleOnTop = true;
|
sensibleOnTop = true;
|
||||||
focusEvents = true;
|
focusEvents = true;
|
||||||
@@ -101,11 +141,12 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
nextcloud-client.enable = lib.mkDefault true;
|
nextcloud-client.enable = false; # lib.mkDefault hasDestopEnvironment;
|
||||||
pass-secret-service.enable = lib.mkDefault true;
|
pass-secret-service = lib.mkDefault enabled;
|
||||||
kdeconnect = {
|
kdeconnect = {
|
||||||
enable = true;
|
enable = lib.mkDefault hasDestopEnvironment;
|
||||||
indicator = true;
|
indicator = lib.mkDefault hasDestopEnvironment;
|
||||||
|
package = pkgs.kdePackages.kdeconnect-kde;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
{ config, lib, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
cfg = config.mjallen.programs.btop;
|
cfg = config.${namespace}.programs.btop;
|
||||||
nord = import ../../desktop/theme/nord.nix;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [ ./options.nix ];
|
imports = [ ./options.nix ];
|
||||||
@@ -10,8 +14,6 @@ in
|
|||||||
programs.btop = {
|
programs.btop = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
color_theme = "nord"; # todo
|
|
||||||
theme_background = true;
|
|
||||||
truecolor = true;
|
truecolor = true;
|
||||||
force_tty = false;
|
force_tty = false;
|
||||||
presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty";
|
presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty";
|
||||||
@@ -75,52 +77,6 @@ in
|
|||||||
selected_battery = "Auto";
|
selected_battery = "Auto";
|
||||||
log_level = "WARNING";
|
log_level = "WARNING";
|
||||||
};
|
};
|
||||||
themes = {
|
|
||||||
nord = ''
|
|
||||||
theme[main_bg]="${nord.polarNight.nord0}"
|
|
||||||
theme[main_fg]="${nord.snowStorm.nord6}"
|
|
||||||
theme[title]="${nord.snowStorm.nord6}"
|
|
||||||
theme[hi_fg]="${nord.frost.nord7}"
|
|
||||||
theme[selected_bg]="${nord.polarNight.nord1}"
|
|
||||||
theme[selected_fg]="${nord.frost.nord7}"
|
|
||||||
theme[inactive_fg]="${nord.polarNight.nord2}"
|
|
||||||
theme[graph_text]="${nord.snowStorm.nord6}"
|
|
||||||
theme[meter_bg]="${nord.polarNight.nord1}"
|
|
||||||
theme[proc_misc]="${nord.snowStorm.nord6}"
|
|
||||||
theme[cpu_box]="${nord.aurora.nord15}"
|
|
||||||
theme[mem_box]="${nord.aurora.nord14}"
|
|
||||||
theme[net_box]="${nord.aurora.nord12}"
|
|
||||||
theme[proc_box]="${nord.aurora.nord11}"
|
|
||||||
theme[div_line]="${nord.polarNight.nord1}"
|
|
||||||
theme[temp_start]="${nord.aurora.nord14}"
|
|
||||||
theme[temp_mid]="${nord.aurora.nord13}"
|
|
||||||
theme[temp_end]="${nord.aurora.nord11}"
|
|
||||||
theme[cpu_start]="${nord.aurora.nord15}"
|
|
||||||
theme[cpu_mid]="${nord.aurora.nord12}"
|
|
||||||
theme[cpu_end]="${nord.aurora.nord11}"
|
|
||||||
theme[free_start]="${nord.aurora.nord14}"
|
|
||||||
theme[free_mid]="${nord.aurora.nord13}"
|
|
||||||
theme[free_end]="${nord.aurora.nord12}"
|
|
||||||
theme[cached_start]="${nord.aurora.nord14}"
|
|
||||||
theme[cached_mid]="${nord.aurora.nord13}"
|
|
||||||
theme[cached_end]="${nord.aurora.nord12}"
|
|
||||||
theme[available_start]="${nord.snowStorm.nord6}"
|
|
||||||
theme[available_mid]="${nord.aurora.nord11}"
|
|
||||||
theme[available_end]="${nord.aurora.nord11}"
|
|
||||||
theme[used_start]="${nord.aurora.nord14}"
|
|
||||||
theme[used_mid]="${nord.aurora.nord13}"
|
|
||||||
theme[used_end]="${nord.aurora.nord11}"
|
|
||||||
theme[download_start]="${nord.frost.nord8}"
|
|
||||||
theme[download_mid]="${nord.frost.nord8}"
|
|
||||||
theme[download_end]="${nord.aurora.nord12}"
|
|
||||||
theme[upload_start]="${nord.frost.nord7}"
|
|
||||||
theme[upload_mid]="${nord.frost.nord7}"
|
|
||||||
theme[upload_end]="${nord.aurora.nord12}"
|
|
||||||
theme[process_start]="${nord.aurora.nord15}"
|
|
||||||
theme[process_mid]="${nord.aurora.nord12}"
|
|
||||||
theme[process_end]="${nord.aurora.nord11}"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{ lib, ... }:
|
{ lib, namespace, ... }:
|
||||||
with lib;
|
with lib;
|
||||||
{
|
{
|
||||||
options.mjallen.programs.btop = {
|
options.${namespace}.programs.btop = {
|
||||||
enable = mkEnableOption "enable btop";
|
enable = mkEnableOption "enable btop";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,77 +1,83 @@
|
|||||||
{ config, lib, pkgs, system, ... }:
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
system,
|
||||||
|
namespace,
|
||||||
|
hasDestopEnvironment ? true,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
isArm = "aarch64-linux" == system;
|
isArm = ("aarch64-linux" == system) || ("aarch64-darwin" == system);
|
||||||
open-remote-ssh = pkgs.vscode-utils.buildVscodeExtension {
|
isDarwin = ("aarch64-darwin" == system);
|
||||||
pname = "open-remote-ssh";
|
|
||||||
version = "0.0.49";
|
|
||||||
vscodeExtPublisher = "jeanp413";
|
|
||||||
vscodeExtName = "open-remote-ssh";
|
|
||||||
vscodeExtUniqueId = "jeanp413.open-remote-ssh";
|
|
||||||
src = pkgs.fetchurl {
|
|
||||||
url = "https://open-vsx.org/api/jeanp413/open-remote-ssh/0.0.49/file/jeanp413.open-remote-ssh-0.0.49.vsix";
|
|
||||||
sha256 = "sha256-QfJnAAx+kO2iJ1EzWoO5HLogJKg3RiC3hg1/u2Jm6t4";
|
|
||||||
name = "open-remote-ssh.zip";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
x86_only = with pkgs; [
|
x86_only = with pkgs; [
|
||||||
vscode-extensions.redhat.vscode-xml
|
vscode-extensions.redhat.vscode-xml
|
||||||
];
|
];
|
||||||
|
open-remote-ssh = pkgs.${namespace}.open-remote-ssh;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
nodePackages.nodejs
|
||||||
|
uv
|
||||||
|
];
|
||||||
|
|
||||||
programs = {
|
programs = {
|
||||||
vscode = {
|
vscode = {
|
||||||
enable = true;
|
enable = hasDestopEnvironment;
|
||||||
package = pkgs.vscodium;
|
package = pkgs.vscodium;
|
||||||
mutableExtensionsDir = false;
|
mutableExtensionsDir = false;
|
||||||
profiles = {
|
profiles = {
|
||||||
default = {
|
default = {
|
||||||
enableUpdateCheck = false;
|
enableUpdateCheck = false;
|
||||||
enableExtensionUpdateCheck = false;
|
enableExtensionUpdateCheck = false;
|
||||||
extensions = with pkgs; [
|
extensions =
|
||||||
vscode-extensions.arrterian.nix-env-selector
|
with pkgs;
|
||||||
vscode-extensions.bbenoist.nix
|
[
|
||||||
vscode-extensions.brettm12345.nixfmt-vscode
|
vscode-extensions.arrterian.nix-env-selector
|
||||||
vscode-extensions.cweijan.vscode-database-client2
|
vscode-extensions.bbenoist.nix
|
||||||
vscode-extensions.dendron.dendron-markdown-preview-enhanced
|
vscode-extensions.brettm12345.nixfmt-vscode
|
||||||
vscode-extensions.jnoortheen.nix-ide
|
vscode-extensions.cweijan.vscode-database-client2
|
||||||
vscode-extensions.mkhl.direnv
|
# vscode-extensions.dendron.dendron-markdown-preview-enhanced
|
||||||
vscode-extensions.ms-python.debugpy
|
vscode-extensions.jnoortheen.nix-ide
|
||||||
vscode-extensions.ms-python.pylint
|
vscode-extensions.mkhl.direnv
|
||||||
vscode-extensions.ms-python.python
|
vscode-extensions.ms-python.debugpy
|
||||||
# vscode-extensions.ms-python.vscode-pylance
|
vscode-extensions.ms-python.pylint
|
||||||
vscode-extensions.redhat.vscode-yaml
|
vscode-extensions.ms-python.python
|
||||||
vscode-extensions.yy0931.vscode-sqlite3-editor
|
# vscode-extensions.ms-python.vscode-pylance
|
||||||
|
vscode-extensions.redhat.vscode-yaml
|
||||||
|
vscode-extensions.yy0931.vscode-sqlite3-editor
|
||||||
|
|
||||||
# open-remote-ssh
|
nix-vscode-extensions.open-vsx.jeanp413.open-remote-ssh
|
||||||
# nix-vscode-extensions.open-vsx.jeanp413.open-remote-ssh
|
]
|
||||||
# open-vsx.jeanp413.open-remote-ssh
|
++ (if !isArm then x86_only else [ ]);
|
||||||
] ++ ( if !isArm then x86_only else [ ] ) ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [
|
# ++ (if !isDarwin then [ open-remote-ssh ] else [ ]);
|
||||||
{
|
# ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [
|
||||||
name = "copilot-mcp";
|
# {
|
||||||
publisher = "automatalabs";
|
# name = "copilot-mcp";
|
||||||
version = "0.0.49";
|
# publisher = "automatalabs";
|
||||||
sha256 = "sha256-+G2OQl5SCN7bh7MzGdYiRclIZefBE7lWnGg1kNpCvnA=";
|
# version = "0.0.49";
|
||||||
}
|
# sha256 = "sha256-+G2OQl5SCN7bh7MzGdYiRclIZefBE7lWnGg1kNpCvnA=";
|
||||||
{
|
# }
|
||||||
name = "mcp-server-runner";
|
# {
|
||||||
publisher = "zebradev";
|
# name = "mcp-server-runner";
|
||||||
version = "0.1.0";
|
# publisher = "zebradev";
|
||||||
sha256 = "sha256-StydVt3VzQUSS/pYp76jnIwtZlEj8gWAGzOARs93J+E=";
|
# version = "0.1.0";
|
||||||
}
|
# sha256 = "sha256-StydVt3VzQUSS/pYp76jnIwtZlEj8gWAGzOARs93J+E=";
|
||||||
{
|
# }
|
||||||
name = "claude-dev";
|
# {
|
||||||
publisher = "saoudrizwan";
|
# name = "claude-dev";
|
||||||
version = "3.17.9";
|
# publisher = "saoudrizwan";
|
||||||
sha256 = "sha256-y3bFtMe5vZrO3DFb31KDvkzjD2jM76wK89mKhgJXC70=";
|
# version = "3.17.9";
|
||||||
}
|
# sha256 = "sha256-y3bFtMe5vZrO3DFb31KDvkzjD2jM76wK89mKhgJXC70=";
|
||||||
];
|
# }
|
||||||
|
# ];
|
||||||
|
|
||||||
userSettings = {
|
userSettings = {
|
||||||
|
|
||||||
|
"database-client.autoSync" = true;
|
||||||
|
|
||||||
"editor" = {
|
"editor" = {
|
||||||
"defaultFormatter" = "brettm12345.nixfmt-vscode";
|
"defaultFormatter" = "brettm12345.nixfmt-vscode";
|
||||||
"fontFamily" = "fira-code-nerd, FiraCode Nerd Font, Consolas, 'Courier New', monospace";
|
|
||||||
"fontLigatures" = true;
|
|
||||||
"renderWhitespace" = "all";
|
"renderWhitespace" = "all";
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,7 +85,11 @@ in
|
|||||||
"confirmDelete" = false;
|
"confirmDelete" = false;
|
||||||
"confirmDragAndDrop" = false;
|
"confirmDragAndDrop" = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
"extensions." = {
|
||||||
|
"autoCheckUpdates" = false;
|
||||||
|
};
|
||||||
|
|
||||||
"git" = {
|
"git" = {
|
||||||
"confirmSync" = false;
|
"confirmSync" = false;
|
||||||
"enableSmartCommit" = true;
|
"enableSmartCommit" = true;
|
||||||
@@ -110,10 +120,12 @@ in
|
|||||||
# You can write arbitary Nix expressions here, to produce valid "options" declaration result.
|
# You can write arbitary Nix expressions here, to produce valid "options" declaration result.
|
||||||
# Tip: for flake-based configuration, utilize `builtins.getFlake`
|
# Tip: for flake-based configuration, utilize `builtins.getFlake`
|
||||||
"nixos" = {
|
"nixos" = {
|
||||||
"expr" = "(builtins.getFlake \"${config.home.homeDirectory}/nix-config\").nixosConfigurations.<name>.options";
|
"expr" =
|
||||||
|
"(builtins.getFlake \"${config.home.homeDirectory}/nix-config\").nixosConfigurations.<name>.options";
|
||||||
};
|
};
|
||||||
"home-manager" = {
|
"home-manager" = {
|
||||||
"expr" = "(builtins.getFlake \"${config.home.homeDirectory}/nix-config\").homeConfigurations.<name>.options";
|
"expr" =
|
||||||
|
"(builtins.getFlake \"${config.home.homeDirectory}/nix-config\").homeConfigurations.<name>.options";
|
||||||
};
|
};
|
||||||
# # Tip: use ${workspaceFolder} variable to define path
|
# # Tip: use ${workspaceFolder} variable to define path
|
||||||
# "nix-darwin" = {
|
# "nix-darwin" = {
|
||||||
@@ -133,12 +145,16 @@ in
|
|||||||
|
|
||||||
"security.workspace.trust.untrustedFiles" = "open";
|
"security.workspace.trust.untrustedFiles" = "open";
|
||||||
|
|
||||||
|
"update.mode" = "none";
|
||||||
|
|
||||||
"workbench" = {
|
"workbench" = {
|
||||||
"colorCustomizations" = null;
|
"colorCustomizations" = null;
|
||||||
"editorAssociations" = {
|
"editorAssociations" = {
|
||||||
"*.db" = "default";
|
"*.db" = "default";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
"enable-proposed-api" = [ "jeanp413.open-remote-ssh" ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -149,4 +165,4 @@ in
|
|||||||
enableZshIntegration = true;
|
enableZshIntegration = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,12 @@ in
|
|||||||
{
|
{
|
||||||
programs.git = {
|
programs.git = {
|
||||||
enable = true;
|
enable = true;
|
||||||
userName = "mjallen18";
|
settings = {
|
||||||
userEmail = "matt.l.jallen@gmail.com";
|
user = {
|
||||||
aliases = gitAliases;
|
name = "mjallen18";
|
||||||
|
email = "matt.l.jallen@gmail.com";
|
||||||
|
};
|
||||||
|
alias = gitAliases;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
25
modules/home/programs/hyprland/avizo.nix
Normal file
25
modules/home/programs/hyprland/avizo.nix
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
namespace,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.${namespace}.programs.hyprland;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.avizo = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
default = {
|
||||||
|
time = 1.0;
|
||||||
|
y-offset = 0.5;
|
||||||
|
fade-in = 0.1;
|
||||||
|
fade-out = 0.2;
|
||||||
|
padding = 10;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
710
modules/home/programs/hyprland/default.nix
Normal file
710
modules/home/programs/hyprland/default.nix
Normal file
@@ -0,0 +1,710 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.${namespace}.programs.hyprland;
|
||||||
|
drawer = "nwg-drawer -fm nautilus -term kitty -mb 10 -mt 10 -ml 10 -mr 10 -pbuseicontheme -i ${config.stylix.icons.dark}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./avizo.nix
|
||||||
|
./options.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
# Home packages
|
||||||
|
home.packages =
|
||||||
|
with pkgs;
|
||||||
|
(
|
||||||
|
[
|
||||||
|
box64
|
||||||
|
brightnessctl
|
||||||
|
ddcutil
|
||||||
|
egl-wayland
|
||||||
|
file-roller
|
||||||
|
glib
|
||||||
|
gnome-calculator
|
||||||
|
gnome-calendar
|
||||||
|
gnome-disk-utility
|
||||||
|
gnome-firmware
|
||||||
|
gnome-font-viewer
|
||||||
|
gnome-logs
|
||||||
|
gnome-photos
|
||||||
|
gnome-tweaks
|
||||||
|
gnome-weather
|
||||||
|
gsettings-desktop-schemas
|
||||||
|
hyprcursor
|
||||||
|
hyprland
|
||||||
|
hyprpaper
|
||||||
|
hyprshot
|
||||||
|
hyprsysteminfo
|
||||||
|
kdePackages.qtmultimedia
|
||||||
|
libnotify
|
||||||
|
libz
|
||||||
|
meson
|
||||||
|
nautilus
|
||||||
|
nomacs
|
||||||
|
nwg-look
|
||||||
|
overskride
|
||||||
|
pamixer
|
||||||
|
pavucontrol
|
||||||
|
playerctl
|
||||||
|
qt5.qtwayland
|
||||||
|
qt6.qtwayland
|
||||||
|
waybar
|
||||||
|
wayland-protocols
|
||||||
|
wayland-utils
|
||||||
|
waypaper
|
||||||
|
wev
|
||||||
|
wl-clipboard
|
||||||
|
wlogout
|
||||||
|
wlroots
|
||||||
|
xhost
|
||||||
|
xsettingsd
|
||||||
|
xwayland
|
||||||
|
]
|
||||||
|
++ (if cfg.notificationDaemon == "mako" then [ mako ] else [ dunst ])
|
||||||
|
++ (if cfg.launcher == "wofi" then [ wofi ] else [ rofi ])
|
||||||
|
++ (with pkgs.${namespace}; [ pipewire-python ])
|
||||||
|
);
|
||||||
|
|
||||||
|
# Session variables
|
||||||
|
home.sessionVariables = {
|
||||||
|
BROWSER = "${cfg.defaultApps.browser.pname}";
|
||||||
|
CLUTTER_BACKEND = "wayland";
|
||||||
|
EDITOR = "${cfg.defaultApps.editor.pname}";
|
||||||
|
VISUAL = "${cfg.defaultApps.visual.pname}";
|
||||||
|
ICON_THEME = config.gtk.iconTheme.name;
|
||||||
|
GTK_CSD = "0";
|
||||||
|
GTK_THEME = config.gtk.theme.name;
|
||||||
|
GTK_USE_PORTAL = "1";
|
||||||
|
HYPRCURSOR_THEME = config.stylix.cursor.name;
|
||||||
|
HYPRCURSOR_SIZE = config.stylix.cursor.size;
|
||||||
|
MOZ_ENABLE_WAYLAND = "1";
|
||||||
|
NIXOS_OZONE_WL = "1";
|
||||||
|
NIXOS_XDG_OPEN_USE_PORTAL = "1";
|
||||||
|
QT_AUTO_SCREEN_SCALE_FACTOR = "1";
|
||||||
|
QT_QPA_PLATFORM = "wayland-egl";
|
||||||
|
QT_QPA_PLATFORMTHEME = lib.mkDefault "gtk3";
|
||||||
|
QT_SCALE_FACTOR = "1";
|
||||||
|
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
|
||||||
|
SDL_VIDEODRIVER = "wayland";
|
||||||
|
TERMINAL = "${cfg.defaultApps.terminal.pname}";
|
||||||
|
XCURSOR_THEME = config.stylix.cursor.name;
|
||||||
|
XCURSOR_SIZE = config.stylix.cursor.size;
|
||||||
|
XDG_CACHE_HOME = "\${HOME}/.cache";
|
||||||
|
XDG_CONFIG_HOME = "\${HOME}/.config";
|
||||||
|
XDG_CURRENT_DESKTOP = "Hyprland";
|
||||||
|
XDG_DATA_HOME = "\${HOME}/.local/share";
|
||||||
|
XDG_SESSION_DESKTOP = "Hyprland";
|
||||||
|
XDG_SESSION_TYPE = "wayland";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Services
|
||||||
|
services = {
|
||||||
|
hyprpolkitagent.enable = true;
|
||||||
|
hyprpaper = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
preload = [ cfg.hyprpaper.wallpaperPath ];
|
||||||
|
wallpaper = [
|
||||||
|
{
|
||||||
|
monitor = "";
|
||||||
|
path = cfg.hyprpaper.wallpaperPath;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
splash = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
hypridle = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
general = {
|
||||||
|
before_sleep_cmd = "loginctl lock-session"; # lock before suspend.
|
||||||
|
after_sleep_cmd = "hyprctl dispatch dpms on"; # to avoid having to press a key twice to turn on the display.
|
||||||
|
ignore_dbus_inhibit = false;
|
||||||
|
lock_cmd = "pidof hyprlock || hyprlock"; # avoid starting multiple hyprlock instances.
|
||||||
|
};
|
||||||
|
listener = [
|
||||||
|
# {
|
||||||
|
# timeout = 300; # 5min
|
||||||
|
# on-timeout = "brightnessctl -s set 10"; # set monitor backlight to minimum, avoid 0 on OLED monitor.
|
||||||
|
# on-resume = "brightnessctl -r"; # monitor backlight restore.
|
||||||
|
# }
|
||||||
|
{
|
||||||
|
timeout = cfg.hyprIdle.lockScreenTimer;
|
||||||
|
on-timeout = "loginctl lock-session"; # lock screen when timeout has passed
|
||||||
|
}
|
||||||
|
{
|
||||||
|
timeout = cfg.hyprIdle.screenOffTimer;
|
||||||
|
on-timeout = "hyprctl dispatch dpms off"; # screen off when timeout has passed
|
||||||
|
on-resume = "hyprctl dispatch dpms on"; # screen on when activity is detected after timeout has fired.
|
||||||
|
}
|
||||||
|
{
|
||||||
|
timeout = cfg.hyprIdle.suspendTimer;
|
||||||
|
on-timeout = "systemctl suspend"; # suspend pc
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Programs
|
||||||
|
programs = {
|
||||||
|
vscode.profiles.default.userSettings."window"."titleBarStyle" = "custom";
|
||||||
|
|
||||||
|
hyprlock = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
background = mkForce [
|
||||||
|
{
|
||||||
|
monitor = "";
|
||||||
|
path = "/run/wallpaper.jpg"; # supports png, jpg, webp (no animations, though)
|
||||||
|
color = mkDefault "rgba(25, 20, 20, 1.0";
|
||||||
|
|
||||||
|
# all these options are taken from hyprland, see https://wiki.hyprland.org/Configuring/Variables/#blur for explanations
|
||||||
|
blur_passes = mkDefault "3"; # 0 disables blurring
|
||||||
|
blur_size = mkDefault "7";
|
||||||
|
noise = "0.0117";
|
||||||
|
contrast = "0.8916";
|
||||||
|
brightness = mkDefault "0.8172";
|
||||||
|
vibrancy = "0.1696";
|
||||||
|
vibrancy_darkness = "0.0";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
label = [
|
||||||
|
# Date display
|
||||||
|
{
|
||||||
|
monitor = cfg.primaryDisplay;
|
||||||
|
text = "cmd[update:1000] echo -e \"$(LC_TIME=en_US.UTF-8 date +\"%A, %B %d\")\"";
|
||||||
|
color = config.lib.stylix.colors.base06;
|
||||||
|
font_size = "25";
|
||||||
|
font_family = lib.mkDefault config.stylix.fonts.monospace.name;
|
||||||
|
position = "0, 350";
|
||||||
|
halign = "center";
|
||||||
|
valign = "center";
|
||||||
|
}
|
||||||
|
# Time display
|
||||||
|
{
|
||||||
|
monitor = cfg.primaryDisplay;
|
||||||
|
text = "cmd[update:1000] echo \"<span>$(date +\"%I:%M\")</span>\"";
|
||||||
|
color = config.lib.stylix.colors.base06;
|
||||||
|
font_size = "120";
|
||||||
|
font_family = lib.mkDefault "${config.stylix.fonts.monospace.name} Bold";
|
||||||
|
position = "0, 230";
|
||||||
|
halign = "center";
|
||||||
|
valign = "center";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
monitor = cfg.primaryDisplay;
|
||||||
|
text = "$USER";
|
||||||
|
color = config.lib.stylix.colors.base06;
|
||||||
|
outline_thickness = 2;
|
||||||
|
dots_size = 0.2;
|
||||||
|
dots_spacing = 0.2;
|
||||||
|
dots_center = true;
|
||||||
|
font_size = 18;
|
||||||
|
font_family = lib.mkDefault "${config.stylix.fonts.monospace.name} Bold";
|
||||||
|
position = "0, 0";
|
||||||
|
halign = "center";
|
||||||
|
valign = "center";
|
||||||
|
}
|
||||||
|
# weather
|
||||||
|
{
|
||||||
|
monitor = cfg.primaryDisplay;
|
||||||
|
text = "cmd[update:30000] waybar-weather --hyprlock";
|
||||||
|
color = config.lib.stylix.colors.base06;
|
||||||
|
font_size = "25";
|
||||||
|
font_family = lib.mkDefault config.stylix.fonts.monospace.name;
|
||||||
|
position = "-100, 100";
|
||||||
|
halign = "right";
|
||||||
|
valign = "bottom";
|
||||||
|
}
|
||||||
|
# media
|
||||||
|
{
|
||||||
|
monitor = cfg.primaryDisplay;
|
||||||
|
text = "cmd[update:1000] waybar-media";
|
||||||
|
color = config.lib.stylix.colors.base06;
|
||||||
|
font_size = "15";
|
||||||
|
font_family = lib.mkDefault config.stylix.fonts.monospace.name;
|
||||||
|
position = "100, 100";
|
||||||
|
halign = "left";
|
||||||
|
valign = "bottom";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
# user box
|
||||||
|
shape = [
|
||||||
|
{
|
||||||
|
monitor = cfg.primaryDisplay;
|
||||||
|
size = "200, 50";
|
||||||
|
color = "rgba(46, 52, 64, .25";
|
||||||
|
rounding = -1;
|
||||||
|
border_size = "0";
|
||||||
|
position = "0, 0";
|
||||||
|
halign = "center";
|
||||||
|
valign = "center";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
input-field = [
|
||||||
|
{
|
||||||
|
size = "200, 50";
|
||||||
|
position = "0, -80";
|
||||||
|
font_family = lib.mkDefault config.stylix.fonts.monospace.name;
|
||||||
|
monitor = cfg.primaryDisplay;
|
||||||
|
dots_center = true;
|
||||||
|
fade_on_empty = true;
|
||||||
|
font_color = config.lib.stylix.colors.base06;
|
||||||
|
inner_color = config.lib.stylix.colors.base03;
|
||||||
|
outer_color = config.lib.stylix.colors.base00;
|
||||||
|
bothlock_color = -1;
|
||||||
|
outline_thickness = 5;
|
||||||
|
placeholder_text = ''<span foreground="#${config.lib.stylix.colors.base00}">Password...</span>'';
|
||||||
|
shadow_passes = 2;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
image = [
|
||||||
|
{
|
||||||
|
monitor = cfg.primaryDisplay;
|
||||||
|
# path = "/tmp/hyprlock-art";
|
||||||
|
reload_cmd = "waybar-media-art";
|
||||||
|
reload_time = 3;
|
||||||
|
size = 150;
|
||||||
|
rounding = 0;
|
||||||
|
position = "100, 150";
|
||||||
|
halign = "left";
|
||||||
|
valign = "bottom";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Wayland configuration
|
||||||
|
wayland.windowManager.hyprland = {
|
||||||
|
enable = true;
|
||||||
|
xwayland.enable = true;
|
||||||
|
systemd = {
|
||||||
|
enable = true;
|
||||||
|
enableXdgAutostart = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
plugins = with pkgs.hyprlandPlugins; [
|
||||||
|
# hyprgrass
|
||||||
|
];
|
||||||
|
|
||||||
|
settings =
|
||||||
|
let
|
||||||
|
useMonitorV2 = (lib.versionAtLeast pkgs.hyprland.version "0.40.0") && (cfg.monitorv2 != [ ]);
|
||||||
|
names =
|
||||||
|
if useMonitorV2 then
|
||||||
|
map (m: m.name) cfg.monitorv2
|
||||||
|
else
|
||||||
|
[
|
||||||
|
cfg.display1.input
|
||||||
|
cfg.display2.input
|
||||||
|
];
|
||||||
|
firstMonitor = builtins.elemAt names 0;
|
||||||
|
secondMonitor = if builtins.length names > 1 then builtins.elemAt names 1 else firstMonitor;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
"$mod" = cfg.modKey;
|
||||||
|
|
||||||
|
# Mouse
|
||||||
|
# mouse_[up|down] - scroll wheel
|
||||||
|
# middle_mouse - 274
|
||||||
|
# thumb_up - 276
|
||||||
|
# thumb_down - 275
|
||||||
|
|
||||||
|
# l -> locked, will also work when an input inhibitor (e.g. a lockscreen) is active.
|
||||||
|
# r -> release, will trigger on release of a key.
|
||||||
|
# e -> repeat, will repeat when held.
|
||||||
|
# n -> non-consuming, key/mouse events will be passed to the active window in addition to triggering the dispatcher.
|
||||||
|
# m -> mouse, see below.
|
||||||
|
# t -> transparent, cannot be shadowed by other binds.
|
||||||
|
# i -> ignore mods, will ignore modifiers.
|
||||||
|
# s -> separate, will arbitrarily combine keys between each mod/key, see [Keysym combos](#keysym-combos) above.
|
||||||
|
# d -> has description, will allow you to write a description for your bind.
|
||||||
|
# p -> bypasses the app's requests to inhibit keybinds.
|
||||||
|
|
||||||
|
# https://wiki.hyprland.org/Configuring/Binds/
|
||||||
|
# https://wiki.hyprland.org/Configuring/Binds/#mouse-buttons
|
||||||
|
|
||||||
|
bind = [
|
||||||
|
"$mod, Return, exec, ${cfg.defaultApps.terminal.pname}"
|
||||||
|
"$mod, SPACE, exec, ${if cfg.launcher == "wofi" then "wofi --show drun" else "rofi -show drun"}"
|
||||||
|
", xf86Search, exec, ${if cfg.launcher == "wofi" then "wofi --show drun" else "rofi -show drun"}"
|
||||||
|
"$mod, Q, killactive, "
|
||||||
|
"$mod, M, exec, wlogout --protocol layer-shell"
|
||||||
|
"$mod, E, exec, ${cfg.defaultApps.fileExplorer.pname}"
|
||||||
|
"$mod, V, togglefloating, "
|
||||||
|
"$mod, D, exec, ${drawer}"
|
||||||
|
"$mod, P, pseudo, " # dwindle
|
||||||
|
"$mod, S, togglesplit, " # dwindle
|
||||||
|
"$mod SHIFT, Q, exec, hyprlock"
|
||||||
|
"$mod SHIFT, 4, exec, hyprshot -m region --clipboard-only"
|
||||||
|
"$mod, F, fullscreen, 1"
|
||||||
|
"$mod SHIFT, F, fullscreen, 0"
|
||||||
|
"$mod SHIFT, E, exec, smile"
|
||||||
|
|
||||||
|
"$mod, mouse:276, movecurrentworkspacetomonitor, ${firstMonitor}"
|
||||||
|
"$mod, mouse:275, movecurrentworkspacetomonitor, ${secondMonitor}"
|
||||||
|
|
||||||
|
# alt-tab between workspaces on active monitor
|
||||||
|
"$mod, Tab, workspace, m+1"
|
||||||
|
"$mod SHIFT, Tab, workspace, m-1"
|
||||||
|
|
||||||
|
"$mod, h, movefocus, l"
|
||||||
|
"$mod, l, movefocus, r"
|
||||||
|
"$mod, k, movefocus, u"
|
||||||
|
"$mod, j, movefocus, d"
|
||||||
|
|
||||||
|
"$mod, 1, workspace, 1"
|
||||||
|
"$mod, 2, workspace, 2"
|
||||||
|
"$mod, 3, workspace, 3"
|
||||||
|
"$mod, 4, workspace, 4"
|
||||||
|
"$mod, 5, workspace, 5"
|
||||||
|
"$mod, 6, workspace, 6"
|
||||||
|
"$mod, 7, workspace, 7"
|
||||||
|
"$mod, 8, workspace, 8"
|
||||||
|
"$mod, 9, workspace, 9"
|
||||||
|
"$mod, 0, workspace, 10"
|
||||||
|
|
||||||
|
"$mod ALT, 1, movetoworkspace, 1"
|
||||||
|
"$mod ALT, 2, movetoworkspace, 2"
|
||||||
|
"$mod ALT, 3, movetoworkspace, 3"
|
||||||
|
"$mod ALT, 4, movetoworkspace, 4"
|
||||||
|
"$mod ALT, 5, movetoworkspace, 5"
|
||||||
|
"$mod ALT, 6, movetoworkspace, 6"
|
||||||
|
"$mod ALT, 7, movetoworkspace, 7"
|
||||||
|
"$mod ALT, 8, movetoworkspace, 8"
|
||||||
|
"$mod ALT, 9, movetoworkspace, 9"
|
||||||
|
"$mod ALT, 0, movetoworkspace, discord"
|
||||||
|
|
||||||
|
"$mod CTRL, l, resizeactive, 10 0"
|
||||||
|
"$mod CTRL, h, resizeactive, -10 0"
|
||||||
|
"$mod CTRL, k, resizeactive, 0 -10"
|
||||||
|
"$mod CTRL, j, resizeactive, 0 10"
|
||||||
|
|
||||||
|
"$mod SHIFT, l, movewindow, r"
|
||||||
|
"$mod SHIFT, h, movewindow, l"
|
||||||
|
"$mod SHIFT, k, movewindow, u"
|
||||||
|
"$mod SHIFT, j, movewindow, d"
|
||||||
|
|
||||||
|
"$mod, b, exec, ${cfg.defaultApps.browser.pname}"
|
||||||
|
]
|
||||||
|
++ cfg.keybinds.bind;
|
||||||
|
|
||||||
|
bindm = [
|
||||||
|
# Move/resize windows with mod + LMB/RMB and dragging
|
||||||
|
"$mod, mouse:272, movewindow"
|
||||||
|
"$mod, mouse:273, resizewindow"
|
||||||
|
# middle mouse will grab a window, mod + middle mouse will close it
|
||||||
|
"$mod SHIFT, mouse:274, movewindow"
|
||||||
|
]
|
||||||
|
++ cfg.keybinds.bindm;
|
||||||
|
|
||||||
|
bindel = [
|
||||||
|
", XF86AudioRaiseVolume, exec, volumectl -u up"
|
||||||
|
", XF86AudioLowerVolume, exec, volumectl -u down"
|
||||||
|
]
|
||||||
|
++ cfg.keybinds.bindel;
|
||||||
|
|
||||||
|
bindl = [
|
||||||
|
", XF86AudioMute, exec, volumectl toggle-mute"
|
||||||
|
", XF86AudioPlay, exec, playerctl play-pause"
|
||||||
|
", XF86AudioPrev, exec, playerctl previous"
|
||||||
|
", XF86AudioNext, exec, playerctl next"
|
||||||
|
", XF86AudioMicMute, exec, volumectl -m toggle-mute"
|
||||||
|
|
||||||
|
", XF86MonBrightnessUp, exec, lightctl up"
|
||||||
|
", XF86MonBrightnessDown, exec, lightctl down"
|
||||||
|
]
|
||||||
|
++ cfg.keybinds.bindl;
|
||||||
|
|
||||||
|
monitor =
|
||||||
|
cfg.monitor
|
||||||
|
++ map (
|
||||||
|
m:
|
||||||
|
if m.disabled then
|
||||||
|
"${m.name}, disable"
|
||||||
|
else if m.mirrorOf != null then
|
||||||
|
"${m.name}, mirror, ${m.mirrorOf}"
|
||||||
|
else
|
||||||
|
let
|
||||||
|
mode = if m.mode == null then "preferred" else m.mode;
|
||||||
|
position = if m.position == null then "0x0" else m.position;
|
||||||
|
scale = if m.scale == null then "1" else (toString m.scale);
|
||||||
|
parts = [
|
||||||
|
m.name
|
||||||
|
mode
|
||||||
|
position
|
||||||
|
scale
|
||||||
|
];
|
||||||
|
# Append transform only when set, as "transform, <value>"
|
||||||
|
transformTokens =
|
||||||
|
if m.transform == null then
|
||||||
|
[ ]
|
||||||
|
else
|
||||||
|
[
|
||||||
|
"transform"
|
||||||
|
m.transform
|
||||||
|
];
|
||||||
|
tokens = parts ++ transformTokens ++ m.extra;
|
||||||
|
in
|
||||||
|
builtins.concatStringsSep ", " tokens
|
||||||
|
) cfg.monitorv2;
|
||||||
|
|
||||||
|
render = {
|
||||||
|
cm_fs_passthrough = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
misc = {
|
||||||
|
vrr = if cfg.enableVRR then 1 else 0;
|
||||||
|
force_default_wallpaper = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
general = {
|
||||||
|
gaps_in = 5;
|
||||||
|
gaps_out = 10;
|
||||||
|
border_size = 1;
|
||||||
|
# "col.active_border" = "rgb(8aadf4) rgb(24273A) rgb(24273A) rgb(8aadf4) 45deg";
|
||||||
|
# "col.inactive_border" = "rgb(24273A) rgb(24273A) rgb(24273A) rgb(24273A) 45deg";
|
||||||
|
layout = "dwindle";
|
||||||
|
allow_tearing = cfg.allowTearing;
|
||||||
|
};
|
||||||
|
|
||||||
|
decoration = {
|
||||||
|
rounding = 10;
|
||||||
|
blur = {
|
||||||
|
enabled = true;
|
||||||
|
size = 2;
|
||||||
|
passes = 2;
|
||||||
|
new_optimizations = true;
|
||||||
|
xray = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
animations = {
|
||||||
|
enabled = "yes";
|
||||||
|
bezier = [
|
||||||
|
"overshot, 0.05, 0.9, 0.1, 1.05"
|
||||||
|
"smoothOut, 0.36, 0, 0.66, -0.56"
|
||||||
|
"smoothIn, 0.25, 1, 0.5, 1"
|
||||||
|
];
|
||||||
|
animation = [
|
||||||
|
"windows, 1, 5, overshot, slide"
|
||||||
|
"windowsOut, 1, 4, smoothOut, slide"
|
||||||
|
"windowsMove, 1, 4, default"
|
||||||
|
"border, 1, 10, default"
|
||||||
|
"fade, 1, 10, smoothIn"
|
||||||
|
"fadeDim, 1, 10, smoothIn"
|
||||||
|
"workspaces, 1, 6, default"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
dwindle = {
|
||||||
|
pseudotile = "yes";
|
||||||
|
preserve_split = "yes";
|
||||||
|
};
|
||||||
|
|
||||||
|
workspace = cfg.workspace;
|
||||||
|
|
||||||
|
windowrule = [
|
||||||
|
"match:title file_progress, float 1"
|
||||||
|
"match:title .*[Cc]onfirm.*, float 1"
|
||||||
|
"match:title .*[Dd]ialog.*, float 1"
|
||||||
|
"match:title .*[Dd]ownload.*, float 1"
|
||||||
|
"match:title .*[Nn]otification.*, float 1"
|
||||||
|
"match:title .*[Ee]rror.*, float 1"
|
||||||
|
"match:title .*[Ss]plash.*, float 1"
|
||||||
|
"match:title .*[Cc]onfirmreset.*, float 1"
|
||||||
|
"match:title .*[Ss]ign [Ii]n - .*, float 1"
|
||||||
|
"match:title .*[Oo]pen [Ff]ile.*, float 1"
|
||||||
|
"match:title .*branchdialog.*, float 1"
|
||||||
|
"match:class .*pavucontrol.*, float 1"
|
||||||
|
"match:class .*pavucontrol.*, move onscreen cursor 0% 0%"
|
||||||
|
"match:class .*[Oo]verskride.*, float 1"
|
||||||
|
"match:class .*FileRoller.*, float 1"
|
||||||
|
"match:class .*wlogout.*, float 1"
|
||||||
|
"match:title .*mpv.*, idle_inhibit stayfocused"
|
||||||
|
|
||||||
|
"match:class .*nm-connection-editor.*, float 1"
|
||||||
|
"match:class .*nm-connection-editor.*, move onscreen cursor 0% 0%"
|
||||||
|
|
||||||
|
"match:title Media viewer, float 1"
|
||||||
|
"match:class it.mijorus.smile),match:title Smile, float 1"
|
||||||
|
"match:class .blueman-manager-wrapped)$,match:title Bluetooth Devices, float 1"
|
||||||
|
# Picture in picture windows
|
||||||
|
"match:title .*Picture-in-Picture.*, float 1"
|
||||||
|
"match:title .*Picture-in-Picture.*, pin 1"
|
||||||
|
|
||||||
|
# discord/vesktop
|
||||||
|
# "workspace: name:discord, match:class .*vesktop"
|
||||||
|
# "match:class .*vesktop),match:title .*Discord Popout.*, float 1"
|
||||||
|
# "pin, match:class .*vesktop),match:title .*Discord Popout.*"
|
||||||
|
|
||||||
|
# Music
|
||||||
|
# "workspace: name:discord, match:class Apple Music.*"
|
||||||
|
|
||||||
|
# Steam
|
||||||
|
"match:class .*[Ss]team, match:title .*[Ss]team.*, float 1"
|
||||||
|
"match:class .*[Ss]team, match:title .*[Ss]team.*, workspace name:steam silent"
|
||||||
|
"match:class .*[Ss]team, match:title .*[Ss]team.*, tile 1"
|
||||||
|
"match:class .*steam,match:title .*Friends List.*, float 1"
|
||||||
|
|
||||||
|
# Code
|
||||||
|
"match:class .*codium.*, match:title Save As, pin 1"
|
||||||
|
"match:class .*codium.*, match:title Save As, float 1"
|
||||||
|
"match:class xdg-desktop-portal-gtk, match:title Open Workspace from File, float 1"
|
||||||
|
|
||||||
|
# Game Tearing??? https://wiki.hypr.land/Configuring/Tearing/
|
||||||
|
"match:class .*gamescope.*, idle_inhibit fullscreen, content game, immediate 1"
|
||||||
|
"match:xdg_tag proton-game, idle_inhibit fullscreen, content game, immediate 1"
|
||||||
|
"match:class steam_app_.*, idle_inhibit fullscreen, content game, immediate 1"
|
||||||
|
|
||||||
|
# vmware
|
||||||
|
# this tag will set the below options to the vdi window
|
||||||
|
# this will have it auto open as a 2160x7680 window
|
||||||
|
# and makes multi-monitor work
|
||||||
|
"match:class .*[Hh]orizon-client, match:title USPS Next VDI, tag +horizonrdp"
|
||||||
|
|
||||||
|
"match:tag horizonrdp, no_anim 1"
|
||||||
|
"match:tag horizonrdp, no_blur 1"
|
||||||
|
"match:tag horizonrdp, rounding 0"
|
||||||
|
"match:tag horizonrdp, no_shadow 1"
|
||||||
|
"match:tag horizonrdp, immediate 1"
|
||||||
|
"match:tag horizonrdp, allows_input 1"
|
||||||
|
"match:tag horizonrdp, border_size 0"
|
||||||
|
"match:tag horizonrdp, max_size 2160 7680"
|
||||||
|
"match:tag horizonrdp, min_size 1920 1080"
|
||||||
|
"match:tag horizonrdp, render_unfocused 1"
|
||||||
|
"match:tag horizonrdp, idle_inhibit 1"
|
||||||
|
"match:tag horizonrdp, float 1"
|
||||||
|
# float the vmware window cause its annoying to use in fullscreen
|
||||||
|
"match:class .*[Hh]orizon-client),match:title [Oo]mnissa [Hh]orizon [Cc]lient, float 1"
|
||||||
|
]
|
||||||
|
++ cfg.windowRule;
|
||||||
|
|
||||||
|
plugin = {
|
||||||
|
# touch_gestures = {
|
||||||
|
# # The default sensitivity is probably too low on tablet screens,
|
||||||
|
# # I recommend turning it up to 4.0
|
||||||
|
# sensitivity = "4.0";
|
||||||
|
|
||||||
|
# # must be >= 3
|
||||||
|
# workspace_swipe_fingers = "3";
|
||||||
|
|
||||||
|
# # switching workspaces by swiping from an edge, this is separate from workspace_swipe_fingers
|
||||||
|
# # and can be used at the same time
|
||||||
|
# # possible values: l, r, u, or d
|
||||||
|
# # to disable it set it to anything else
|
||||||
|
# workspace_swipe_edge = "d";
|
||||||
|
|
||||||
|
# # in milliseconds
|
||||||
|
# long_press_delay = "400";
|
||||||
|
|
||||||
|
# # resize windows by long-pressing on window borders and gaps.
|
||||||
|
# # If general:resize_on_border is enabled, general:extend_border_grab_area is used for floating
|
||||||
|
# # windows
|
||||||
|
# resize_on_border_long_press = true;
|
||||||
|
|
||||||
|
# # in pixels, the distance from the edge that is considered an edge
|
||||||
|
# edge_margin = "10";
|
||||||
|
|
||||||
|
# # emulates touchpad swipes when swiping in a direction that does not trigger workspace swipe.
|
||||||
|
# # ONLY triggers when finger count is equal to workspace_swipe_fingers
|
||||||
|
# #
|
||||||
|
# # might be removed in the future in favor of event hooks
|
||||||
|
# emulate_touchpad_swipe = false;
|
||||||
|
|
||||||
|
# experimental = {
|
||||||
|
# # send proper cancel events to windows instead of hacky touch_up events,
|
||||||
|
# # NOT recommended as it crashed a few times, once it's stabilized I'll make it the default
|
||||||
|
# send_cancel = "0";
|
||||||
|
# };
|
||||||
|
|
||||||
|
# hyprgrass-bind = [
|
||||||
|
# # swipe left from right edge
|
||||||
|
# ", edge:r:l, workspace, +1"
|
||||||
|
|
||||||
|
# # swipe up from bottom edge
|
||||||
|
# ", edge:d:u, exec, ${cfg.defaultApps.browser.pname}"
|
||||||
|
|
||||||
|
# # swipe down from left edge
|
||||||
|
# ", edge:l:d, exec, pactl set-sink-volume @DEFAULT_SINK@ -4%"
|
||||||
|
|
||||||
|
# # swipe down with 4 fingers
|
||||||
|
# ", swipe:4:d, killactive"
|
||||||
|
|
||||||
|
# # swipe diagonally left and down with 3 fingers
|
||||||
|
# # l (or r) must come before d and u
|
||||||
|
# ", swipe:3:ld, exec, foot"
|
||||||
|
|
||||||
|
# # tap with 3 fingers
|
||||||
|
# ", tap:3, exec, foot"
|
||||||
|
|
||||||
|
# # longpress can trigger mouse binds:
|
||||||
|
# ", longpress:2, movewindow"
|
||||||
|
# ", longpress:3, resizewindow"
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
|
};
|
||||||
|
|
||||||
|
gesture = [
|
||||||
|
"3, horizontal, scale: 0.75, workspace" # swipe 3 fingers to change workspace
|
||||||
|
"3, pinch, mod: SUPER, resize"
|
||||||
|
"4, pinch, fullscreen"
|
||||||
|
];
|
||||||
|
|
||||||
|
input = {
|
||||||
|
kb_layout = "us";
|
||||||
|
|
||||||
|
kb_variant = "";
|
||||||
|
kb_model = "";
|
||||||
|
kb_options = "";
|
||||||
|
kb_rules = "";
|
||||||
|
|
||||||
|
numlock_by_default = true;
|
||||||
|
|
||||||
|
follow_mouse = 1;
|
||||||
|
|
||||||
|
touchpad = {
|
||||||
|
clickfinger_behavior = 1;
|
||||||
|
natural_scroll = "yes";
|
||||||
|
};
|
||||||
|
|
||||||
|
sensitivity = 0; # -1.0 - 1.0, 0 means no modification.
|
||||||
|
};
|
||||||
|
|
||||||
|
# experimental = {
|
||||||
|
# xx_color_management_v4 = true;
|
||||||
|
# };
|
||||||
|
|
||||||
|
debug = {
|
||||||
|
# full_cm_proto = cfg.debug.fullCmProto;
|
||||||
|
disable_logs = cfg.debug.disableLogs;
|
||||||
|
disable_scale_checks = cfg.debug.disableScaleChecks;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig =
|
||||||
|
let
|
||||||
|
autostarts = builtins.concatStringsSep "\n" (map (cmd: "exec-once = ${cmd}") cfg.autostartCommands);
|
||||||
|
in
|
||||||
|
''
|
||||||
|
exec-once = dbus-update-activation-environment --systemd --all
|
||||||
|
exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
|
||||||
|
exec-once = xhost +SI:localuser:root
|
||||||
|
''
|
||||||
|
+ autostarts
|
||||||
|
+ "\n"
|
||||||
|
+ (cfg.extraConfig or "");
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
330
modules/home/programs/hyprland/options.nix
Normal file
330
modules/home/programs/hyprland/options.nix
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib;
|
||||||
|
{
|
||||||
|
options.${namespace}.programs.hyprland = {
|
||||||
|
enable = mkEnableOption "enable hyprland";
|
||||||
|
|
||||||
|
primaryDisplay = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "DP-1";
|
||||||
|
description = "Primary display identifier";
|
||||||
|
};
|
||||||
|
|
||||||
|
display1 = {
|
||||||
|
input = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "DP-1";
|
||||||
|
description = "First display identifier (Deprecated: prefer monitorv2)";
|
||||||
|
};
|
||||||
|
|
||||||
|
resolution = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "3840x2160";
|
||||||
|
description = "First display resolution (Deprecated: prefer monitorv2)";
|
||||||
|
};
|
||||||
|
|
||||||
|
refreshRate = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "240.00000";
|
||||||
|
description = "First display refresh rate (Deprecated: prefer monitorv2)";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
display2 = {
|
||||||
|
input = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "DP-1";
|
||||||
|
description = "Second display identifier (Deprecated: prefer monitorv2)";
|
||||||
|
};
|
||||||
|
|
||||||
|
resolution = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "3840x2160";
|
||||||
|
description = "Second display resolution (Deprecated: prefer monitorv2)";
|
||||||
|
};
|
||||||
|
|
||||||
|
refreshRate = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "240.00000";
|
||||||
|
description = "Second display refresh rate (Deprecated: prefer monitorv2)";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Deprecated: prefer hyprpaper.* options
|
||||||
|
wallpaper = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [ ];
|
||||||
|
description = "Deprecated: no longer used; prefer hyprpaper.wallpaperPath and hyprpaper.usePerMonitor.";
|
||||||
|
};
|
||||||
|
|
||||||
|
hyprpaper = mkOption {
|
||||||
|
type = types.submodule {
|
||||||
|
options = {
|
||||||
|
wallpaperPath = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "/run/wallpaper.jpg";
|
||||||
|
description = "Path to the wallpaper used by hyprpaper.";
|
||||||
|
};
|
||||||
|
usePerMonitor = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "If true, generate one wallpaper entry per monitor (monitorv2 preferred, falls back to display1/display2).";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
description = "Hyprpaper configuration.";
|
||||||
|
};
|
||||||
|
|
||||||
|
monitor = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [ ];
|
||||||
|
description = "List of Hyprland monitor configs (legacy). Example: [ \"eDP-1, 1920x1080@60, 0x0, 1\" ]";
|
||||||
|
};
|
||||||
|
|
||||||
|
monitorv2 = mkOption {
|
||||||
|
type =
|
||||||
|
with types;
|
||||||
|
listOf (
|
||||||
|
types.submodule {
|
||||||
|
options = {
|
||||||
|
name = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Monitor name (e.g., DP-1, eDP-1).";
|
||||||
|
};
|
||||||
|
mode = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = "Resolution@Hz or keyword (e.g., \"3840x2160@144\" or \"preferred\").";
|
||||||
|
};
|
||||||
|
position = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = "Position like \"0x0\" or \"auto\".";
|
||||||
|
};
|
||||||
|
scale = mkOption {
|
||||||
|
type = types.nullOr types.float;
|
||||||
|
default = null;
|
||||||
|
description = "Scale factor (e.g., 1.0).";
|
||||||
|
};
|
||||||
|
transform = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = "Rotation/transform (e.g., \"normal\", \"90\", \"180\", \"270\", \"flipped\").";
|
||||||
|
};
|
||||||
|
disabled = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Disable this monitor.";
|
||||||
|
};
|
||||||
|
mirrorOf = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = "Mirror another monitor by name.";
|
||||||
|
};
|
||||||
|
extra = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [ ];
|
||||||
|
description = "Additional monitorv2 flags appended as-is.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
default = [ ];
|
||||||
|
description = "Hyprland monitorv2 entries as structured options; rendered to lines like \"name, mode, position, scale, transform, ...\".";
|
||||||
|
};
|
||||||
|
|
||||||
|
workspace = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [ ];
|
||||||
|
description = "List of hyprland workspace definitions";
|
||||||
|
};
|
||||||
|
|
||||||
|
windowRule = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [ ];
|
||||||
|
description = "List of hyprland window rules";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = mkOption {
|
||||||
|
type = with types; str;
|
||||||
|
default = "";
|
||||||
|
description = "Any extra configuration options";
|
||||||
|
};
|
||||||
|
|
||||||
|
defaultApps = mkOption {
|
||||||
|
type = types.submodule {
|
||||||
|
options = {
|
||||||
|
browser = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.firefox;
|
||||||
|
description = "Default browser";
|
||||||
|
};
|
||||||
|
editor = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.micro;
|
||||||
|
description = "Default text editor";
|
||||||
|
};
|
||||||
|
fileExplorer = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.nautilus;
|
||||||
|
description = "Default file explorer";
|
||||||
|
};
|
||||||
|
visual = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.vscodium;
|
||||||
|
description = "Default visual editor";
|
||||||
|
};
|
||||||
|
terminal = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.kitty;
|
||||||
|
description = "Default terminal";
|
||||||
|
};
|
||||||
|
office = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.onlyoffice-desktopeditors;
|
||||||
|
description = "Default office suite";
|
||||||
|
};
|
||||||
|
video = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.vlc;
|
||||||
|
description = "Default video player";
|
||||||
|
};
|
||||||
|
imageViewer = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.nomacs;
|
||||||
|
description = "Default image viewer";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
description = "Default applications used across the system";
|
||||||
|
};
|
||||||
|
|
||||||
|
autostartCommands = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [
|
||||||
|
"nwg-look -a"
|
||||||
|
"nwg-dock-hyprland -x"
|
||||||
|
];
|
||||||
|
description = "Commands to run via Hyprland exec-once";
|
||||||
|
};
|
||||||
|
|
||||||
|
launcher = mkOption {
|
||||||
|
type = types.enum [
|
||||||
|
"wofi"
|
||||||
|
"rofi"
|
||||||
|
];
|
||||||
|
default = "wofi";
|
||||||
|
description = "Application launcher to use in keybinds and packages.";
|
||||||
|
};
|
||||||
|
|
||||||
|
notificationDaemon = mkOption {
|
||||||
|
type = types.enum [
|
||||||
|
"mako"
|
||||||
|
"dunst"
|
||||||
|
];
|
||||||
|
default = "mako";
|
||||||
|
description = "Notification daemon to install.";
|
||||||
|
};
|
||||||
|
|
||||||
|
modKey = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "SUPER";
|
||||||
|
description = "Modifier key used for Hyprland binds (e.g., SUPER, ALT).";
|
||||||
|
};
|
||||||
|
|
||||||
|
enableVRR = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Enable variable refresh rate (maps to Hyprland misc.vrr).";
|
||||||
|
};
|
||||||
|
|
||||||
|
allowTearing = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Allow tearing (maps to Hyprland general.allow_tearing).";
|
||||||
|
};
|
||||||
|
|
||||||
|
debug = mkOption {
|
||||||
|
type = types.submodule {
|
||||||
|
options = {
|
||||||
|
disableLogs = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Set Hyprland debug.disable_logs.";
|
||||||
|
};
|
||||||
|
fullCmProto = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Set Hyprland debug.full_cm_proto.";
|
||||||
|
};
|
||||||
|
disableScaleChecks = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Set Hyprland debug.disable_scale_checks.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
description = "Hyprland debug flags.";
|
||||||
|
};
|
||||||
|
|
||||||
|
keybinds = mkOption {
|
||||||
|
type = types.submodule {
|
||||||
|
options = {
|
||||||
|
bind = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [ ];
|
||||||
|
description = "Hyprland bind entries.";
|
||||||
|
};
|
||||||
|
bindm = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [ ];
|
||||||
|
description = "Hyprland bindm entries.";
|
||||||
|
};
|
||||||
|
bindel = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [ ];
|
||||||
|
description = "Hyprland bindel entries.";
|
||||||
|
};
|
||||||
|
bindl = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [ ];
|
||||||
|
description = "Hyprland bindl entries.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
description = "Keybinding lists for Hyprland; useful for host-level overrides.";
|
||||||
|
};
|
||||||
|
|
||||||
|
gestures = mkOption {
|
||||||
|
type = with types; listOf str;
|
||||||
|
default = [ ];
|
||||||
|
description = "Hyprland gesture entries.";
|
||||||
|
};
|
||||||
|
|
||||||
|
hyprIdle = {
|
||||||
|
lockScreenTimer = mkOption {
|
||||||
|
type = with types; int;
|
||||||
|
default = 300;
|
||||||
|
description = "Time in seconds before locking the screen";
|
||||||
|
};
|
||||||
|
screenOffTimer = mkOption {
|
||||||
|
type = with types; int;
|
||||||
|
default = 900;
|
||||||
|
description = "Time in seconds before turning off the screen";
|
||||||
|
};
|
||||||
|
suspendTimer = mkOption {
|
||||||
|
type = with types; int;
|
||||||
|
default = 1800;
|
||||||
|
description = "Time in seconds before suspending";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
{ lib, config, ... }:
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
cfg = config.mjallen.programs.kitty;
|
cfg = config.${namespace}.programs.kitty;
|
||||||
nord = import ../../desktop/theme/nord.nix;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [ ./options.nix ];
|
imports = [ ./options.nix ];
|
||||||
@@ -12,12 +16,6 @@ in
|
|||||||
enable = true;
|
enable = true;
|
||||||
shellIntegration.enableZshIntegration = true;
|
shellIntegration.enableZshIntegration = true;
|
||||||
|
|
||||||
font = {
|
|
||||||
name = cfg.font.name;
|
|
||||||
package = cfg.font.package;
|
|
||||||
size = cfg.font.size;
|
|
||||||
};
|
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
bold_font = "auto";
|
bold_font = "auto";
|
||||||
italic_font = "auto";
|
italic_font = "auto";
|
||||||
@@ -26,80 +24,6 @@ in
|
|||||||
cursor_shape = "block";
|
cursor_shape = "block";
|
||||||
url_style = "dotted";
|
url_style = "dotted";
|
||||||
confirm_os_window_close = "0";
|
confirm_os_window_close = "0";
|
||||||
background_opacity = "0.85";
|
|
||||||
|
|
||||||
# The basic colors
|
|
||||||
foreground = nord.snowStorm.nord6;
|
|
||||||
background = nord.polarNight.nord0;
|
|
||||||
selection_foreground = nord.polarNight.nord0;
|
|
||||||
selection_background = nord.aurora.nord15;
|
|
||||||
|
|
||||||
# Cursor colors
|
|
||||||
cursor = nord.aurora.nord15;
|
|
||||||
cursor_text_color = nord.polarNight.nord0;
|
|
||||||
|
|
||||||
# URL underline color when hovering with mouse
|
|
||||||
url_color = nord.aurora.nord15;
|
|
||||||
|
|
||||||
# Kitty window border colors
|
|
||||||
active_border_color = nord.frost.nord10;
|
|
||||||
inactive_border_color = nord.polarNight.nord1;
|
|
||||||
bell_border_color = nord.aurora.nord13;
|
|
||||||
|
|
||||||
# OS Window titlebar colors
|
|
||||||
wayland_titlebar_color = nord.polarNight.nord0;
|
|
||||||
macos_titlebar_color = nord.polarNight.nord0;
|
|
||||||
|
|
||||||
# Tab bar colors
|
|
||||||
active_tab_foreground = nord.polarNight.nord3;
|
|
||||||
active_tab_background = nord.aurora.nord15;
|
|
||||||
inactive_tab_foreground = nord.snowStorm.nord6;
|
|
||||||
inactive_tab_background = nord.polarNight.nord1;
|
|
||||||
tab_bar_background = nord.polarNight.nord3;
|
|
||||||
|
|
||||||
# Colors for marks (marked text in the terminal)
|
|
||||||
mark1_foreground = nord.polarNight.nord0;
|
|
||||||
mark1_background = nord.frost.nord10;
|
|
||||||
mark2_foreground = nord.polarNight.nord0;
|
|
||||||
mark2_background = nord.aurora.nord15;
|
|
||||||
mark3_foreground = nord.polarNight.nord0;
|
|
||||||
mark3_background = nord.frost.nord8;
|
|
||||||
|
|
||||||
# The 16 terminal colors
|
|
||||||
|
|
||||||
# black
|
|
||||||
color0 = nord.polarNight.nord0;
|
|
||||||
|
|
||||||
# Autosuggestion
|
|
||||||
color8 = nord.frost.nord10;
|
|
||||||
|
|
||||||
# red
|
|
||||||
color1 = nord.aurora.nord11;
|
|
||||||
color9 = nord.aurora.nord11;
|
|
||||||
|
|
||||||
# green
|
|
||||||
color2 = nord.aurora.nord14;
|
|
||||||
color10 = nord.aurora.nord14;
|
|
||||||
|
|
||||||
# yellow
|
|
||||||
color3 = nord.aurora.nord13;
|
|
||||||
color11 = nord.aurora.nord13;
|
|
||||||
|
|
||||||
# blue
|
|
||||||
color4 = nord.frost.nord10;
|
|
||||||
color12 = nord.frost.nord10;
|
|
||||||
|
|
||||||
# magenta
|
|
||||||
color5 = nord.aurora.nord15;
|
|
||||||
color13 = nord.aurora.nord15;
|
|
||||||
|
|
||||||
# cyan
|
|
||||||
color6 = nord.frost.nord8;
|
|
||||||
color14 = nord.frost.nord8;
|
|
||||||
|
|
||||||
# white
|
|
||||||
color7 = nord.snowStorm.nord5;
|
|
||||||
color15 = nord.snowStorm.nord4;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,27 +1,7 @@
|
|||||||
{ lib, ... }:
|
{ lib, namespace, ... }:
|
||||||
with lib;
|
with lib;
|
||||||
{
|
{
|
||||||
options.mjallen.programs.kitty = {
|
options.${namespace}.programs.kitty = {
|
||||||
enable = mkEnableOption "enable kitty terminal";
|
enable = mkEnableOption "enable kitty terminal";
|
||||||
|
|
||||||
font = {
|
|
||||||
name = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "DejaVu Sans";
|
|
||||||
};
|
|
||||||
package = mkOption {
|
|
||||||
type = types.package;
|
|
||||||
default = pkgs.dejavu_fonts;
|
|
||||||
};
|
|
||||||
size = mkOption {
|
|
||||||
type = with types; int;
|
|
||||||
default = 8;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
theme = mkOption {
|
|
||||||
type = types.attrs;
|
|
||||||
default = import ../../desktop/theme/nord.nix;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,8 @@
|
|||||||
"browser.newtabpage.activity-stream.topSitesRows" = 3; # Set number of rows for top sites on new tab page
|
"browser.newtabpage.activity-stream.topSitesRows" = 3; # Set number of rows for top sites on new tab page
|
||||||
"layout.css.light-dark.enabled" = true; # Enable light/dark theme support
|
"layout.css.light-dark.enabled" = true; # Enable light/dark theme support
|
||||||
"extensions.activeThemeID" = "default-theme@mozilla.org"; # Set active theme
|
"extensions.activeThemeID" = "default-theme@mozilla.org"; # Set active theme
|
||||||
"extensions.webextensions.uuids" = "{\"formautofill@mozilla.org\" =\"851c83b7-26d5-449c-8cc9-d8951a0ce78d\",\"pictureinpicture@mozilla.org\" =\"42fa2650-5134-4bef-bafa-b73f9ae51bad\",\"screenshots@mozilla.org\" =\"efd2b692-43c4-433a-aea5-0cb79f8312d4\",\"webcompat-reporter@mozilla.org\" =\"c43a6be2-fb56-4253-b384-ce8e09a89999\",\"webcompat@mozilla.org\" =\"e25fd1bb-7c53-413f-9528-bb922c322a56\",\"default-theme@mozilla.org\" =\"610b67c3-9145-46f7-814f-d8ee2cc8edff\",\"addons-search-detection@mozilla.com\:\"caedb3ca-5cf5-4e23-a251-d742f23e6fc8\",\"uBlock0@raymondhill.net\" =\"7e7d9fd9-12bf-42d3-9c7c-9ffd05420ec7\",\"78272b6fa58f4a1abaac99321d503a20@proton.me\" =\"7242a067-06d8-430b-94a3-00d264cdd57b\",\"addon@darkreader.org\" =\"2f02b112-6acd-4bdc-af2c-1432eb527339\",\"jid1-xUfzOsOFlzSOXg@jetpack\" =\"d0c72046-9903-4118-8160-a028840bf928\",\"chrome-gnome-shell@gnome.org\" =\"a1ab53e6-b765-4f25-8349-383cc04682a0\",\"user-agent-switcher@ninetailed.ninja\" =\"259d07cc-bb32-4ed5-b90f-6d73abdeb7bb\",\"firefoxdav@icloud.com\" =\"110e6e2c-18f8-461d-9f26-b8f04482b6f1\",\"ciscowebexstart1@cisco.com\" =\"a4062240-e73a-4353-bddb-d608d84881f7\",\"{a6c4a591-f1b2-4f03-b3ff-767e5bedf4e7}\" =\"9164e437-812b-4a07-8dfd-2fd73b39329b\",\"{036a55b4-5e72-4d05-a06c-cba2dfcc134a}\" =\"648fc678-a6fb-47cd-9792-fb9520678c17\",\"{446900e4-71c2-419f-a6a7-df9c091e268b}\" =\"f0b43422-070e-466e-85c9-6543f209f075\",\"jid1-MnnxcxisBPnSXQ@jetpack\" =\"4c448202-c843-4cae-b5c3-d11f2da58fa3\",\"soundfixer@unrelenting.technology\" =\"59b35eb8-1c85-4919-a905-80d120993ddc\",\"floccus@handmadeideas.org\" =\"8ad2956c-8091-41af-a689-7d2108f5958d\",\"{79b9dbcf-cc5a-4cda-89ef-c4ab097eb074}\" =\"c2a223a7-32e0-4726-9f20-17236702b1f5\",\"linkgopher@oooninja.com\" =\"a257858c-0dce-415b-b123-6222876cf843\"}";
|
"extensions.webextensions.uuids" =
|
||||||
|
"{\"formautofill@mozilla.org\" =\"851c83b7-26d5-449c-8cc9-d8951a0ce78d\",\"pictureinpicture@mozilla.org\" =\"42fa2650-5134-4bef-bafa-b73f9ae51bad\",\"screenshots@mozilla.org\" =\"efd2b692-43c4-433a-aea5-0cb79f8312d4\",\"webcompat-reporter@mozilla.org\" =\"c43a6be2-fb56-4253-b384-ce8e09a89999\",\"webcompat@mozilla.org\" =\"e25fd1bb-7c53-413f-9528-bb922c322a56\",\"default-theme@mozilla.org\" =\"610b67c3-9145-46f7-814f-d8ee2cc8edff\",\"addons-search-detection@mozilla.com\:\"caedb3ca-5cf5-4e23-a251-d742f23e6fc8\",\"uBlock0@raymondhill.net\" =\"7e7d9fd9-12bf-42d3-9c7c-9ffd05420ec7\",\"78272b6fa58f4a1abaac99321d503a20@proton.me\" =\"7242a067-06d8-430b-94a3-00d264cdd57b\",\"addon@darkreader.org\" =\"2f02b112-6acd-4bdc-af2c-1432eb527339\",\"jid1-xUfzOsOFlzSOXg@jetpack\" =\"d0c72046-9903-4118-8160-a028840bf928\",\"chrome-gnome-shell@gnome.org\" =\"a1ab53e6-b765-4f25-8349-383cc04682a0\",\"user-agent-switcher@ninetailed.ninja\" =\"259d07cc-bb32-4ed5-b90f-6d73abdeb7bb\",\"firefoxdav@icloud.com\" =\"110e6e2c-18f8-461d-9f26-b8f04482b6f1\",\"ciscowebexstart1@cisco.com\" =\"a4062240-e73a-4353-bddb-d608d84881f7\",\"{a6c4a591-f1b2-4f03-b3ff-767e5bedf4e7}\" =\"9164e437-812b-4a07-8dfd-2fd73b39329b\",\"{036a55b4-5e72-4d05-a06c-cba2dfcc134a}\" =\"648fc678-a6fb-47cd-9792-fb9520678c17\",\"{446900e4-71c2-419f-a6a7-df9c091e268b}\" =\"f0b43422-070e-466e-85c9-6543f209f075\",\"jid1-MnnxcxisBPnSXQ@jetpack\" =\"4c448202-c843-4cae-b5c3-d11f2da58fa3\",\"soundfixer@unrelenting.technology\" =\"59b35eb8-1c85-4919-a905-80d120993ddc\",\"floccus@handmadeideas.org\" =\"8ad2956c-8091-41af-a689-7d2108f5958d\",\"{79b9dbcf-cc5a-4cda-89ef-c4ab097eb074}\" =\"c2a223a7-32e0-4726-9f20-17236702b1f5\",\"linkgopher@oooninja.com\" =\"a257858c-0dce-415b-b123-6222876cf843\"}";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
{ config, lib, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
cfg = config.mjallen.programs.mako;
|
cfg = config.${namespace}.programs.mako;
|
||||||
nord = import ../../desktop/theme/nord.nix;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [ ./options.nix ];
|
imports = [ ./options.nix ];
|
||||||
@@ -10,7 +14,7 @@ in
|
|||||||
services.mako = {
|
services.mako = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
font = cfg.fontName;
|
font = mkDefault cfg.fontName;
|
||||||
icons = true;
|
icons = true;
|
||||||
ignore-timeout = true;
|
ignore-timeout = true;
|
||||||
sort = "-time";
|
sort = "-time";
|
||||||
@@ -22,10 +26,10 @@ in
|
|||||||
max-icon-size = 64;
|
max-icon-size = 64;
|
||||||
default-timeout = 5000;
|
default-timeout = 5000;
|
||||||
|
|
||||||
background-color = nord.polarNight.nord0;
|
# background-color = mkDefault config.lib.stylix.colors.base00;
|
||||||
text-color = nord.snowStorm.nord6;
|
# text-color = mkDefault config.lib.stylix.colors.base06;
|
||||||
border-color = nord.frost.nord10;
|
# border-color = mkDefault config.lib.stylix.colors.base0F;
|
||||||
progress-color = "over ${nord.frost.nord8}";
|
# progress-color = mkDefault "over ${config.lib.stylix.colors.base0C}";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{ lib, ... }:
|
{ lib, namespace, ... }:
|
||||||
with lib;
|
with lib;
|
||||||
{
|
{
|
||||||
options.mjallen.programs.mako = {
|
options.${namespace}.programs.mako = {
|
||||||
enable = mkEnableOption "enable mako";
|
enable = mkEnableOption "enable mako";
|
||||||
|
|
||||||
fontName = mkOption {
|
fontName = mkOption {
|
||||||
@@ -9,4 +9,4 @@ with lib;
|
|||||||
default = "DejaVu Sans";
|
default = "DejaVu Sans";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,56 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
cfg = config.mjallen.programs.nwg-dock;
|
cfg = config.${namespace}.programs.nwg-dock;
|
||||||
nord = import ../../desktop/theme/nord.nix;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [ ./options.nix ];
|
imports = [ ./options.nix ];
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
home.packages = with pkgs; [ nwg-dock-hyprland ];
|
home.packages = with pkgs; [ nwg-dock-hyprland ];
|
||||||
|
|
||||||
home.file = {
|
home.file = {
|
||||||
".config/nwg-dock-hyprland/drawer.css".text = ''
|
".config/nwg-dock-hyprland/config.json".text = ''
|
||||||
|
{
|
||||||
|
"position": "bottom",
|
||||||
|
"anchor": "center",
|
||||||
|
"margin": 12,
|
||||||
|
"icon_size": 48,
|
||||||
|
"icon_size_hover": 64,
|
||||||
|
"spacing": 6,
|
||||||
|
"padding": 8,
|
||||||
|
"autohide": false,
|
||||||
|
"autohide_timeout": 0.3,
|
||||||
|
"exclusive": true,
|
||||||
|
"layer": "top",
|
||||||
|
"height": 72,
|
||||||
|
"background_alpha": 0.55,
|
||||||
|
"rounded_corners": 16,
|
||||||
|
"show_labels": false,
|
||||||
|
"show_running": true,
|
||||||
|
"show_pinned": true,
|
||||||
|
"pinned": [
|
||||||
|
"firefox.desktop",
|
||||||
|
"org.wezfurlong.wezterm.desktop",
|
||||||
|
"codium.desktop",
|
||||||
|
"org.gnome.Nautilus.desktop"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
".config/nwg-dock-hyprland/style.css".text = ''
|
||||||
window {
|
window {
|
||||||
background: ${nord.polarNight.nord0};
|
background: #36364f;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
border-style: none;
|
border-style: none;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-color: ${nord.aurora.nord15}b0
|
border-color: rgba(156, 142, 122, 0.7)
|
||||||
}
|
}
|
||||||
|
|
||||||
#box {
|
#box {
|
||||||
@@ -25,17 +58,17 @@ in
|
|||||||
padding: 10px
|
padding: 10px
|
||||||
}
|
}
|
||||||
|
|
||||||
active {
|
#active {
|
||||||
/* This is to underline the button representing the currently active window */
|
/* This is to underline the button representing the currently active window */
|
||||||
border-bottom: solid 1px;
|
border-bottom: solid 1px;
|
||||||
border-color: ${nord.aurora.nord14}1a
|
border-color: rgba(255, 255, 255, 0.3)
|
||||||
}
|
}
|
||||||
|
|
||||||
button, image {
|
button, image {
|
||||||
background: none;
|
background: none;
|
||||||
border-style: none;
|
border-style: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
color: ${nord.frost.nord10}
|
color: #999
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@@ -47,7 +80,52 @@ in
|
|||||||
}
|
}
|
||||||
|
|
||||||
button:hover {
|
button:hover {
|
||||||
background-color: ${nord.polarNight.nord0}1a;
|
background-color: rgba(255, 255, 255, 0.15);
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:focus {
|
||||||
|
box-shadow: none
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
".config/nwg-dock-hyprland/drawer.css".text = ''
|
||||||
|
window {
|
||||||
|
background: ${config.lib.stylix.colors.base00};
|
||||||
|
border-radius: 10px;
|
||||||
|
border-style: none;
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: ${config.lib.stylix.colors.base0E}b0
|
||||||
|
}
|
||||||
|
|
||||||
|
#box {
|
||||||
|
/* Define attributes of the box surrounding icons here */
|
||||||
|
padding: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
active {
|
||||||
|
/* This is to underline the button representing the currently active window */
|
||||||
|
border-bottom: solid 1px;
|
||||||
|
border-color: ${config.lib.stylix.colors.base0B}1a
|
||||||
|
}
|
||||||
|
|
||||||
|
button, image {
|
||||||
|
background: none;
|
||||||
|
border-style: none;
|
||||||
|
box-shadow: none;
|
||||||
|
color: ${config.lib.stylix.colors.base0F}
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 4px;
|
||||||
|
margin-left: 4px;
|
||||||
|
margin-right: 4px;
|
||||||
|
color: #eee;
|
||||||
|
font-size: 12px
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: ${config.lib.stylix.colors.base00}1a;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{ lib, ... }:
|
{ lib, namespace, ... }:
|
||||||
with lib;
|
with lib;
|
||||||
{
|
{
|
||||||
options.mjallen.programs.nwg-dock = {
|
options.${namespace}.programs.nwg-dock = {
|
||||||
enable = mkEnableOption "enable nwg-dock";
|
enable = mkEnableOption "enable nwg-dock";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,52 +1,57 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
cfg = config.mjallen.programs.nwg-drawer;
|
cfg = config.${namespace}.programs.nwg-drawer;
|
||||||
nord = import ../../desktop/theme/nord.nix;
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [ ./options.nix ];
|
imports = [ ./options.nix ];
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
home.packages = with pkgs; [ nwg-drawer ];
|
home.packages = with pkgs; [ nwg-drawer ];
|
||||||
|
|
||||||
home.file = {
|
home.file = {
|
||||||
".config/nwg-drawer/drawer.css".text = ''
|
".config/nwg-drawer/drawer.css".text = ''
|
||||||
window {
|
window {
|
||||||
background-color: ${nord.polarNight.nord0}bf;
|
background-color: ${config.lib.stylix.colors.base00}bf;
|
||||||
color: ${nord.snowStorm.nord5}00
|
color: ${config.lib.stylix.colors.base05}00
|
||||||
}
|
}
|
||||||
|
|
||||||
/* search entry */
|
/* search entry */
|
||||||
entry {
|
entry {
|
||||||
background-color: ${nord.polarNight.nord1}0f
|
background-color: ${config.lib.stylix.colors.base01}0f
|
||||||
}
|
}
|
||||||
|
|
||||||
button, image {
|
button, image {
|
||||||
background: none;
|
background: none;
|
||||||
border: none
|
border: none
|
||||||
}
|
}
|
||||||
|
|
||||||
button:hover {
|
button:hover {
|
||||||
background-color: ${nord.frost.nord10}1a
|
background-color: ${config.lib.stylix.colors.base0F}1a
|
||||||
}
|
}
|
||||||
|
|
||||||
/* in case you wanted to give category buttons a different look */
|
/* in case you wanted to give category buttons a different look */
|
||||||
#category-button {
|
#category-button {
|
||||||
margin: 0 10px 0 10px
|
margin: 0 10px 0 10px
|
||||||
}
|
}
|
||||||
|
|
||||||
#pinned-box {
|
#pinned-box {
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
border-bottom: 1px dotted ${nord.polarNight.nord3}
|
border-bottom: 1px dotted ${config.lib.stylix.colors.base03}
|
||||||
}
|
}
|
||||||
|
|
||||||
#files-box {
|
#files-box {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border: 1px dotted ${nord.polarNight.nord3};
|
border: 1px dotted ${config.lib.stylix.colors.base03};
|
||||||
border-radius: 15px
|
border-radius: 15px
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{ lib, ... }:
|
{ lib, namespace, ... }:
|
||||||
with lib;
|
with lib;
|
||||||
{
|
{
|
||||||
options.mjallen.programs.nwg-drawer = {
|
options.${namespace}.programs.nwg-drawer = {
|
||||||
enable = mkEnableOption "enable nwg-drawer";
|
enable = mkEnableOption "enable nwg-drawer";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
{ config, lib, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
cfg = config.mjallen.programs.nwg-panel;
|
cfg = config.${namespace}.programs.nwg-panel;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [ ./options.nix ];
|
imports = [ ./options.nix ];
|
||||||
@@ -12,15 +17,15 @@ in
|
|||||||
|
|
||||||
'';
|
'';
|
||||||
".config/nwg-panel/preferred-apps.json".text = ''
|
".config/nwg-panel/preferred-apps.json".text = ''
|
||||||
{
|
{
|
||||||
"\\.pdf$": "${cfg.defaultApps.browser.pname}",
|
"\\.pdf$": "${cfg.defaultApps.browser.pname}",
|
||||||
"\\.svg$": "inkscape",
|
"\\.svg$": "inkscape",
|
||||||
"\\.(jpg|png|tiff|gif)$": "${cfg.defaultApps.imageViewer.pname}",
|
"\\.(jpg|png|tiff|gif)$": "${cfg.defaultApps.imageViewer.pname}",
|
||||||
"\\.(mp3|ogg|flac|wav|wma)$": "audacious",
|
"\\.(mp3|ogg|flac|wav|wma)$": "audacious",
|
||||||
"\\.(avi|mp4|mkv|mov|wav)$": "${cfg.defaultApps.video.pname}",
|
"\\.(avi|mp4|mkv|mov|wav)$": "${cfg.defaultApps.video.pname}",
|
||||||
"\\.(doc|docx|xls|xlsx)$": "${cfg.defaultApps.office.pname}"
|
"\\.(doc|docx|xls|xlsx)$": "${cfg.defaultApps.office.pname}"
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,52 @@
|
|||||||
{ lib, pkgs, ... }:
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
with lib;
|
with lib;
|
||||||
{
|
{
|
||||||
options.mjallen.programs.nwg-panel = {
|
options.${namespace}.programs.nwg-panel = {
|
||||||
enable = mkEnableOption "enable nwg-panel";
|
enable = mkEnableOption "enable nwg-panel";
|
||||||
|
|
||||||
defaultApps = mkOption {
|
defaultApps = mkOption {
|
||||||
type = types.submodule {
|
type = types.submodule {
|
||||||
options = {
|
options = {
|
||||||
browser = mkOption { type = types.package; default = pkgs.firefox; };
|
browser = mkOption {
|
||||||
editor = mkOption { type = types.package; default = pkgs.micro; };
|
type = types.package;
|
||||||
fileExplorer = mkOption { type = types.package; default = pkgs.nemo; };
|
default = pkgs.firefox;
|
||||||
visual = mkOption { type = types.package; default = pkgs.vscodium; };
|
};
|
||||||
terminal = mkOption { type = types.package; default = pkgs.kitty; };
|
editor = mkOption {
|
||||||
office = mkOption { type = types.package; default = pkgs.onlyoffice-bin_latest; };
|
type = types.package;
|
||||||
video = mkOption { type = types.package; default = pkgs.vlc; };
|
default = pkgs.micro;
|
||||||
imageViewer = mkOption { type = types.package; default = pkgs.gnome-photos; };
|
};
|
||||||
|
fileExplorer = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.nautilus;
|
||||||
|
};
|
||||||
|
visual = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.vscodium;
|
||||||
|
};
|
||||||
|
terminal = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.kitty;
|
||||||
|
};
|
||||||
|
office = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.onlyoffice-desktopeditors;
|
||||||
|
};
|
||||||
|
video = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.vlc;
|
||||||
|
};
|
||||||
|
imageViewer = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.gnome-photos;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
description = "Default applications used across the system.";
|
description = "Default applications used across the system.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
{ lib, system, ... }:
|
{
|
||||||
|
lib,
|
||||||
|
system,
|
||||||
|
hasDestopEnvironment ? true,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
isArm = builtins.match "aarch64*" system != null;
|
isArm = "aarch64-linux" == system;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
programs.onlyoffice = {
|
programs.onlyoffice = {
|
||||||
enable = lib.mkDefault (!isArm);
|
enable = lib.mkDefault (!isArm && hasDestopEnvironment);
|
||||||
settings = {
|
settings = {
|
||||||
UITheme = "theme-contrast-dark";
|
UITheme = "theme-contrast-dark";
|
||||||
forcedRtl = false;
|
forcedRtl = false;
|
||||||
maximized = true;
|
maximized = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
290
modules/home/programs/update-checker/default.nix
Normal file
290
modules/home/programs/update-checker/default.nix
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
namespace,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
git-token = config.sops.secrets."github-token".path;
|
||||||
|
|
||||||
|
update-checker = pkgs.writeScriptBin "update-checker" ''
|
||||||
|
#!/usr/bin/env nix-shell
|
||||||
|
#! nix-shell -i python3 --pure
|
||||||
|
#! nix-shell -p python3 python3Packages.pygithub python3Packages.feedparser python3Packages.requests nix-prefetch-scripts nix
|
||||||
|
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
from github import Github
|
||||||
|
from github import Auth
|
||||||
|
import feedparser
|
||||||
|
import requests
|
||||||
|
|
||||||
|
token = None
|
||||||
|
|
||||||
|
with open('${git-token}', 'r') as token_file:
|
||||||
|
token = token_file.readline()
|
||||||
|
|
||||||
|
auth = Auth.Token(token)
|
||||||
|
|
||||||
|
def check_github(owner, repo, version):
|
||||||
|
try:
|
||||||
|
release = None
|
||||||
|
result = None
|
||||||
|
prefetch = None
|
||||||
|
ghub = Github(auth=auth)
|
||||||
|
print(' getting repo ' + owner + '/' + repo)
|
||||||
|
repo = ghub.get_repo(owner + '/' + repo)
|
||||||
|
if '-b' in version:
|
||||||
|
release = repo.get_releases()[0]
|
||||||
|
latest_version = release.name
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
release = repo.get_latest_release()
|
||||||
|
latest_version = release.tag_name
|
||||||
|
except:
|
||||||
|
tags = repo.get_tags()
|
||||||
|
try:
|
||||||
|
if tags is not None:
|
||||||
|
latest_version = tags[0].name
|
||||||
|
except:
|
||||||
|
commits = repo.get_commits()
|
||||||
|
latest_version = commits[0].sha
|
||||||
|
|
||||||
|
if latest_version is not None:
|
||||||
|
|
||||||
|
if latest_version.replace('v',''\'') != version.replace('v',''\''):
|
||||||
|
print(' update found')
|
||||||
|
print(' Current version: ' + version)
|
||||||
|
print(' Latest version: ' + latest_version)
|
||||||
|
result = subprocess.check_output(['nix-prefetch-git', '--quiet', repo.clone_url, '--rev', latest_version])
|
||||||
|
prefetch = json.loads(result)
|
||||||
|
print(' New hash: ' + prefetch.get('hash'))
|
||||||
|
else:
|
||||||
|
print(' no update')
|
||||||
|
ghub.close()
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
def check_codeberg(owner, repo, version):
|
||||||
|
feed = feedparser.parse('https://codeberg.org/{0}/{1}/releases.rss'.format(owner, repo))
|
||||||
|
if feed.status == 200:
|
||||||
|
entry = feed.entries[0]
|
||||||
|
if entry.title.replace('v',''\'') != version.replace('v',''\''):
|
||||||
|
print(' update found')
|
||||||
|
print(' Current version: ' + version)
|
||||||
|
print(' Latest version: ' + entry.title)
|
||||||
|
sha256 = subprocess.check_output(['nix-prefetch-url', url.replace(''\'''\${version}', entry.title.replace('v', ''\''))])
|
||||||
|
prefetch = subprocess.check_output(['nix', 'hash', 'convert', '--hash-algo', 'sha256', str(sha256.decode('utf-8').strip())])
|
||||||
|
print(' New hash: ' + prefetch.decode('utf-8').strip())
|
||||||
|
else:
|
||||||
|
print(' no update')
|
||||||
|
|
||||||
|
def check_open_vsx(publisher, name, version):
|
||||||
|
open_vsx = requests.get('https://open-vsx.org/api/' + publisher + '/' + name)
|
||||||
|
if open_vsx.status_code == 200:
|
||||||
|
extension = open_vsx.json()
|
||||||
|
latest_version = extension.get('version')
|
||||||
|
url = extension.get('files').get('download')
|
||||||
|
if latest_version.replace('v',''\'') != version.replace('v',''\''):
|
||||||
|
print(' update found')
|
||||||
|
print(' Current version: ' + version)
|
||||||
|
print(' Latest version: ' + latest_version)
|
||||||
|
sha256 = subprocess.check_output(['nix-prefetch-url', url])
|
||||||
|
prefetch = subprocess.check_output(['nix', 'hash', 'convert', '--hash-algo', 'sha256', str(sha256.decode('utf-8').strip())])
|
||||||
|
print(' New hash: ' + prefetch.decode('utf-8').strip())
|
||||||
|
else:
|
||||||
|
print(' no update')
|
||||||
|
|
||||||
|
def parse_nix(package_spec):
|
||||||
|
version = None
|
||||||
|
url = None
|
||||||
|
current_hash = None
|
||||||
|
owner = None
|
||||||
|
repo = None
|
||||||
|
pname = None
|
||||||
|
name = None
|
||||||
|
publisher = None
|
||||||
|
for line in package_spec.readlines():
|
||||||
|
if 'owner = "' in line and owner is None:
|
||||||
|
owner = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
|
||||||
|
if 'repo = "' in line and repo is None:
|
||||||
|
repo = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
|
||||||
|
if 'version = "' in line and version is None:
|
||||||
|
version = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
|
||||||
|
if 'rev = "' in line and ''\'''\${version}' not in line:
|
||||||
|
version = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
|
||||||
|
if 'url = "' in line and url is None:
|
||||||
|
url = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
|
||||||
|
if 'sha256 = "' in line or ' hash = "' in line and current_hash is None:
|
||||||
|
current_hash = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
|
||||||
|
if 'pname = "' in line and pname is None:
|
||||||
|
pname = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
|
||||||
|
if ' name = "' in line and name is None:
|
||||||
|
name = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
|
||||||
|
if 'publisher = "' in line and publisher is None:
|
||||||
|
publisher = line.split(' = ')[-1].replace('"', ''\'').replace(';\n', ''\'')
|
||||||
|
|
||||||
|
if url is None and repo is not None:
|
||||||
|
if 'pname' in repo:
|
||||||
|
repo = repo.replace(''\'''\${pname}', pname)
|
||||||
|
url = 'https://github.com/{0}/{1}/releases/tag/{2}'.format(owner, repo, version)
|
||||||
|
|
||||||
|
if url is not None and repo is None and 'github' in url:
|
||||||
|
owner = url.split('github.com/')[-1].split('/')[0]
|
||||||
|
repo = url.split('github.com/')[-1].split('/')[1]
|
||||||
|
|
||||||
|
if url is not None and repo is None and 'codeberg' in url:
|
||||||
|
owner = url.split('codeberg.org/')[-1].split('/')[0]
|
||||||
|
repo = url.split('codeberg.org/')[-1].split('/')[1]
|
||||||
|
|
||||||
|
if url is not None and version is None:
|
||||||
|
version = url.split('/')[-1].replace('.tar.gz', ''\'')
|
||||||
|
|
||||||
|
if url is not None and publisher is not None:
|
||||||
|
url = url.replace(''\'''\${publisher}', publisher).replace(''\'''\${name}', name)
|
||||||
|
|
||||||
|
return url, current_hash, owner, repo, pname, name, publisher, version
|
||||||
|
|
||||||
|
def parse_json(json_versions, flavor=''\''):
|
||||||
|
versions = json.load(json_versions)
|
||||||
|
linux_versions = versions.get('linux')
|
||||||
|
config_versions = versions.get('config')
|
||||||
|
patch_versions = versions.get('patches')
|
||||||
|
zfs_versions = versions.get('zfs')
|
||||||
|
|
||||||
|
check_kernel(linux_versions, flavor)
|
||||||
|
check_cachy_config(config_versions, flavor)
|
||||||
|
check_patch_versions(patch_versions, flavor)
|
||||||
|
check_zfs_versions(zfs_versions, flavor)
|
||||||
|
|
||||||
|
def check_kernel(linux_versions, flavor=''\''):
|
||||||
|
srcinfo = requests.get('https://raw.githubusercontent.com/CachyOS/linux-cachyos/master/linux-cachyos' + flavor + '/.SRCINFO')
|
||||||
|
for line in srcinfo.text.split('\n'):
|
||||||
|
if 'pkgver = ' in line:
|
||||||
|
kernel_version = line.split('=')[-1].strip()
|
||||||
|
if kernel_version[-2:] == '.0':
|
||||||
|
kernel_version = kernel_version[:-2]
|
||||||
|
if flavor in [''\'', '-lts', '-server', '-gcc', '-hardened']:
|
||||||
|
release_src = 'https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-' + kernel_version + '.tar.xz'
|
||||||
|
if flavor == '-rc':
|
||||||
|
release_src = 'https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot/linux-' + kernel_version.replace('.rc', '-rc') + '.tar.gz'
|
||||||
|
sha256 = subprocess.check_output(['nix-prefetch-url', release_src])
|
||||||
|
prefetch = subprocess.check_output(['nix', 'hash', 'convert', '--hash-algo', 'sha256', str(sha256.decode('utf-8').strip())])
|
||||||
|
current_version = linux_versions.get('version')
|
||||||
|
current_hash = linux_versions.get('hash')
|
||||||
|
latest_hash = prefetch.decode('utf-8').strip()
|
||||||
|
print(' Checking linux versions...')
|
||||||
|
if current_hash != latest_hash:
|
||||||
|
print(' Current rev: ' + current_version)
|
||||||
|
print(' Current hash: ' + current_hash)
|
||||||
|
print(' New rev: ' + kernel_version)
|
||||||
|
print(' New hash: ' + latest_hash)
|
||||||
|
else:
|
||||||
|
print(' no update')
|
||||||
|
|
||||||
|
def check_cachy_config(config_versions, flavor=''\''):
|
||||||
|
result = subprocess.check_output(['nix-prefetch-git', '--quiet', 'https://github.com/CachyOS/linux-cachyos.git'])
|
||||||
|
prefetch = json.loads(result)
|
||||||
|
current_version = config_versions.get('rev')
|
||||||
|
latest_version = prefetch.get('rev')
|
||||||
|
print(' Checking config versions...')
|
||||||
|
if current_version != latest_version:
|
||||||
|
print(' Current rev: ' + current_version)
|
||||||
|
print(' New rev: ' + latest_version)
|
||||||
|
print(' New hash: ' + prefetch.get('hash'))
|
||||||
|
else:
|
||||||
|
print(' no update')
|
||||||
|
|
||||||
|
def check_patch_versions(patch_versions, flavor=''\''):
|
||||||
|
result = subprocess.check_output(['nix-prefetch-git', '--quiet', 'https://github.com/CachyOS/kernel-patches.git'])
|
||||||
|
prefetch = json.loads(result)
|
||||||
|
current_version = patch_versions.get('rev')
|
||||||
|
latest_version = prefetch.get('rev')
|
||||||
|
print(' Checking patch versions...')
|
||||||
|
if current_version != latest_version:
|
||||||
|
print(' Current rev: ' + current_version)
|
||||||
|
print(' New rev: ' + latest_version)
|
||||||
|
print(' New hash: ' + prefetch.get('hash'))
|
||||||
|
else:
|
||||||
|
print(' no update')
|
||||||
|
|
||||||
|
def kconfig_to_nix(flavor=''\''):
|
||||||
|
kconfig_result = subprocess.check_output(['nix', 'build', '.#nixosConfigurations.jallen-nas.pkgs.linuxPackages_cachyos' + flavor + '.kernel.kconfigToNix', '--no-link', '--print-out-paths'])
|
||||||
|
config_file = kconfig_result.decode('utf-8').strip()
|
||||||
|
if flavor == ''\'':
|
||||||
|
cachy_flavor = '-gcc'
|
||||||
|
result = subprocess.check_output(['cat', config_file])
|
||||||
|
with open('/etc/nixos/packages/linux-cachyos/config-nix/cachyos' + cachy_flavor + '.x86_64-linux.nix', 'w') as config:
|
||||||
|
config.write(result.decode('utf-8').strip())
|
||||||
|
|
||||||
|
def check_zfs_versions(zfs_versions, flavor=''\''):
|
||||||
|
result = requests.get('https://raw.githubusercontent.com/CachyOS/linux-cachyos/master/linux-cachyos' + flavor + '/PKGBUILD')
|
||||||
|
for line in result.text.split('\n'):
|
||||||
|
if 'git+https://github.com/cachyos/zfs.git#commit=' in line:
|
||||||
|
zfs_rev = line.split('zfs.git#commit=')[-1].replace('")', ''\'')
|
||||||
|
result = subprocess.check_output(['nix-prefetch-git', '--quiet', 'https://github.com/CachyOS/zfs.git', '--rev', zfs_rev])
|
||||||
|
prefetch = json.loads(result)
|
||||||
|
current_version = zfs_versions.get('rev')
|
||||||
|
latest_version = prefetch.get('rev')
|
||||||
|
print(' Checking zfs versions...')
|
||||||
|
if current_version != latest_version:
|
||||||
|
print(' Current rev: ' + current_version)
|
||||||
|
print(' New rev: ' + latest_version)
|
||||||
|
print(' New hash: ' + prefetch.get('hash'))
|
||||||
|
else:
|
||||||
|
print(' no update')
|
||||||
|
|
||||||
|
for (root,dirs,files) in os.walk('/etc/nixos/packages',topdown=True):
|
||||||
|
if 'default.nix' in files and 'versions.json' not in files:
|
||||||
|
print(root.split('/')[-1])
|
||||||
|
with open(root + '/default.nix', 'r') as package_spec:
|
||||||
|
url, current_hash, owner, repo, pname, name, publisher, version = parse_nix(package_spec)
|
||||||
|
|
||||||
|
if owner is not None and repo is not None and 'codeberg' in url:
|
||||||
|
check_codeberg(owner, repo, version)
|
||||||
|
|
||||||
|
elif owner is not None and repo is not None and 'github' in url:
|
||||||
|
check_github(owner, repo, version)
|
||||||
|
|
||||||
|
elif publisher is not None and 'open-vsx' in url:
|
||||||
|
check_open_vsx(publisher, name, version)
|
||||||
|
|
||||||
|
else:
|
||||||
|
if url is not None:
|
||||||
|
print(url)
|
||||||
|
|
||||||
|
if 'default.nix' in files and 'versions.json' in files:
|
||||||
|
with open(root + '/versions.json', 'r') as json_versions:
|
||||||
|
print('Checking Linux CachyOS')
|
||||||
|
parse_json(json_versions)
|
||||||
|
with open(root + '/versions-rc.json', 'r') as json_versions:
|
||||||
|
print('Checking Linux CachyOS RC')
|
||||||
|
parse_json(json_versions, '-rc')
|
||||||
|
with open(root + '/versions-lts.json', 'r') as json_versions:
|
||||||
|
print('Checking Linux CachyOS LTS')
|
||||||
|
parse_json(json_versions, '-lts')
|
||||||
|
with open(root + '/versions-hardened.json', 'r') as json_versions:
|
||||||
|
print('Checking Linux CachyOS Hardened')
|
||||||
|
parse_json(json_versions, '-hardened')
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config = {
|
||||||
|
|
||||||
|
sops = {
|
||||||
|
age.keyFile = "/home/${config.${namespace}.user.name}/.config/sops/age/keys.txt";
|
||||||
|
defaultSopsFile = "/etc/nixos/secrets/secrets.yaml";
|
||||||
|
validateSopsFiles = false;
|
||||||
|
secrets = {
|
||||||
|
"github-token" = { };
|
||||||
|
};
|
||||||
|
templates = {
|
||||||
|
".env".content = ''
|
||||||
|
GITHUB_TOKEN = "${config.sops.placeholder.github-token}"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
home.packages = [ update-checker ];
|
||||||
|
};
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,32 +1,333 @@
|
|||||||
{ lib, ... }:
|
{ lib, namespace, ... }:
|
||||||
with lib;
|
with lib;
|
||||||
|
let
|
||||||
|
inherit (types)
|
||||||
|
str
|
||||||
|
int
|
||||||
|
bool
|
||||||
|
listOf
|
||||||
|
attrs
|
||||||
|
path
|
||||||
|
nullOr
|
||||||
|
submodule
|
||||||
|
;
|
||||||
|
in
|
||||||
{
|
{
|
||||||
options.mjallen.programs.waybar = {
|
options.${namespace}.programs.waybar = {
|
||||||
enable = mkEnableOption "enable waybar";
|
enable = mkEnableOption "Waybar status bar";
|
||||||
|
|
||||||
|
# Legacy/compat options (kept for backwards compatibility)
|
||||||
layer = mkOption {
|
layer = mkOption {
|
||||||
type = types.str;
|
type = str;
|
||||||
default = "top";
|
default = "top";
|
||||||
};
|
description = "Waybar layer (compat). Prefer layout + feature flags.";
|
||||||
|
|
||||||
modules-right = mkOption {
|
|
||||||
type = with types; listOf str;
|
|
||||||
default = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
networkInterface = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "wlan0";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extraModules = mkOption {
|
extraModules = mkOption {
|
||||||
type = types.attrs;
|
type = attrs;
|
||||||
default = { };
|
default = { };
|
||||||
|
description = "Extra settings bars at top-level (compat with older module).";
|
||||||
};
|
};
|
||||||
|
|
||||||
extraModulesStyle = mkOption {
|
extraModulesStyle = mkOption {
|
||||||
type = types.str;
|
type = str;
|
||||||
default = "";
|
default = "";
|
||||||
|
description = "Extra CSS appended (compat). Prefer extra.style.";
|
||||||
|
};
|
||||||
|
|
||||||
|
windowOffset = mkOption {
|
||||||
|
type = int;
|
||||||
|
default = 4;
|
||||||
|
description = "Right margin offset for the hyprland/window module (in rem).";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Layout
|
||||||
|
layout = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
left = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
default = [ "hyprland/workspaces" ];
|
||||||
|
description = "Modules shown on the left.";
|
||||||
|
};
|
||||||
|
center = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
default = [ "hyprland/window" ];
|
||||||
|
description = "Modules shown in the center.";
|
||||||
|
};
|
||||||
|
right = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
default = [
|
||||||
|
"tray"
|
||||||
|
"custom/left-end"
|
||||||
|
"temperature"
|
||||||
|
"temperature#gpu"
|
||||||
|
"keyboard-state#capslock"
|
||||||
|
"keyboard-state#numlock"
|
||||||
|
"wireplumber#sink"
|
||||||
|
"bluetooth"
|
||||||
|
"network"
|
||||||
|
"idle_inhibitor"
|
||||||
|
"custom/right-end"
|
||||||
|
"custom/left-end"
|
||||||
|
"clock"
|
||||||
|
"battery"
|
||||||
|
"custom/notifications"
|
||||||
|
"custom/weather"
|
||||||
|
"custom/power"
|
||||||
|
"custom/right-end"
|
||||||
|
];
|
||||||
|
description = "Modules shown on the right.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
description = "Waybar module layout.";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Network
|
||||||
|
network = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
interface = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "wlan0";
|
||||||
|
description = "Primary network interface name.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
description = "Network configuration.";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Temperatures
|
||||||
|
temperature = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
cpu = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
description = "Enable CPU temperature module.";
|
||||||
|
};
|
||||||
|
hwmonPath = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "/sys/devices/pci0000:00/0000:00:18.3/hwmon";
|
||||||
|
description = "CPU temperature hwmon path.";
|
||||||
|
};
|
||||||
|
hwmonFile = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "temp1_input";
|
||||||
|
description = "CPU temperature hwmon file.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
gpu = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
description = "Enable GPU temperature module.";
|
||||||
|
};
|
||||||
|
hwmonPath = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "/sys/devices/pci0000:00/0000:00:01.1/0000:01:00.0/0000:02:00.0/0000:03:00.0/hwmon";
|
||||||
|
description = "GPU temperature hwmon path.";
|
||||||
|
};
|
||||||
|
hwmonFile = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "temp1_input";
|
||||||
|
description = "GPU temperature hwmon file.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
description = "Temperature module configuration.";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Features
|
||||||
|
features = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
tray = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
bluetooth = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
idleInhibitor = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
keyboardIndicators = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
audio = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
sink = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
source = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
weather = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
hass = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
clock = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
battery = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
description = "Toggle optional Waybar features.";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Styling
|
||||||
|
style = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
file = mkOption {
|
||||||
|
type = nullOr path;
|
||||||
|
default = null;
|
||||||
|
description = "Optional external CSS file to use instead of the inline style.";
|
||||||
|
};
|
||||||
|
fragmentsDir = mkOption {
|
||||||
|
type = nullOr path;
|
||||||
|
default = null;
|
||||||
|
description = "Optional directory of CSS fragments to append.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
description = "Styling configuration.";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Extra overrides
|
||||||
|
extra = mkOption {
|
||||||
|
type = submodule {
|
||||||
|
options = {
|
||||||
|
settings = mkOption {
|
||||||
|
type = attrs;
|
||||||
|
default = { };
|
||||||
|
description = "Extra settings merged into settings.mainBar.";
|
||||||
|
};
|
||||||
|
style = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "";
|
||||||
|
description = "Extra CSS appended to the computed style.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
description = "Extra settings/style hooks.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
40
modules/home/programs/waybar/scripts/audio-control.nix
Normal file
40
modules/home/programs/waybar/scripts/audio-control.nix
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.${namespace}.programs.waybar;
|
||||||
|
|
||||||
|
waybar-audio = pkgs.writeScriptBin "waybar-audio" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Extract sink entries: "ID Description"
|
||||||
|
choices=$(pw-dump | jq -r '
|
||||||
|
.. | objects
|
||||||
|
| select(.["media.class"] == "Audio/Sink")
|
||||||
|
| "\(.["object.id"]) \(.["node.description"])"
|
||||||
|
'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Show wofi menu
|
||||||
|
selected=$(printf "%s\n" "$choices" | wofi --dmenu --prompt "Audio Output")
|
||||||
|
|
||||||
|
# Extract ID
|
||||||
|
id=$(echo "$selected" | awk '{print $1}')
|
||||||
|
|
||||||
|
# Switch to the selected device
|
||||||
|
if [ -n "$id" ]; then
|
||||||
|
wpctl set-default "$id"
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [ ../options.nix ];
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
home.packages = [ waybar-audio ];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,10 +1,18 @@
|
|||||||
{ config, lib, namespace, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
cfg = config.mjallen.programs.waybar;
|
cfg = config.${namespace}.programs.waybar;
|
||||||
|
|
||||||
pythonEnv = pkgs.python3.withPackages (ps: [
|
pythonEnv = pkgs.python3.withPackages (
|
||||||
pkgs.${namespace}.homeassistant-api
|
_ps: with pkgs.${namespace}; [
|
||||||
]);
|
homeassistant-api
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
waybar-hass = pkgs.writeScriptBin "waybar-hass" ''
|
waybar-hass = pkgs.writeScriptBin "waybar-hass" ''
|
||||||
#!${pythonEnv}/bin/python
|
#!${pythonEnv}/bin/python
|
||||||
|
|||||||
61
modules/home/programs/waybar/scripts/media.nix
Normal file
61
modules/home/programs/waybar/scripts/media.nix
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.${namespace}.programs.waybar;
|
||||||
|
|
||||||
|
waybar-media = pkgs.writeScriptBin "waybar-media" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Get current playing song from playerctl
|
||||||
|
if command -v playerctl &> /dev/null; then
|
||||||
|
# Check if any player is running
|
||||||
|
if playerctl status &> /dev/null; then
|
||||||
|
artist=$(playerctl metadata xesam:artist 2>/dev/null)
|
||||||
|
title=$(playerctl metadata xesam:title 2>/dev/null)
|
||||||
|
|
||||||
|
if [[ -n "$artist" && -n "$title" ]]; then
|
||||||
|
echo "♪ $artist - $title"
|
||||||
|
elif [[ -n "$title" ]]; then
|
||||||
|
echo "♪ ''\${title//&/&}"
|
||||||
|
else
|
||||||
|
echo "♪ Music Playing"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
|
waybar-media-art = pkgs.writeScriptBin "waybar-media-art" ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Get current playing song from playerctl
|
||||||
|
if command -v playerctl &> /dev/null; then
|
||||||
|
# Check if any player is running
|
||||||
|
if playerctl status &> /dev/null; then
|
||||||
|
art=$(playerctl metadata mpris:artUrl 2>/dev/null)
|
||||||
|
|
||||||
|
if [[ -n "$art" ]]; then
|
||||||
|
echo ''\${art#file://}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [ ../options.nix ];
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
home.packages = [
|
||||||
|
waybar-media
|
||||||
|
waybar-media-art
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
95
modules/home/programs/waybar/scripts/notifications.nix
Normal file
95
modules/home/programs/waybar/scripts/notifications.nix
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
namespace,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cfg = config.${namespace}.programs.waybar;
|
||||||
|
|
||||||
|
waybar-notifications = pkgs.writeScriptBin "waybar-notifications" ''
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import json
|
||||||
|
import codecs
|
||||||
|
import re
|
||||||
|
|
||||||
|
def check_notifications(args = "history"):
|
||||||
|
notifications = []
|
||||||
|
number = None
|
||||||
|
content = None
|
||||||
|
appname = None
|
||||||
|
urgency = None
|
||||||
|
cmd = "makoctl"
|
||||||
|
temp = subprocess.Popen([cmd, args], stdout = subprocess.PIPE)
|
||||||
|
output = str(temp.communicate()).replace("(b\'", "").replace("\', None)", "")
|
||||||
|
lines = output.split("\\n")
|
||||||
|
for line in lines:
|
||||||
|
if "Notification" in line:
|
||||||
|
number = line.split(":")[0].replace("Notification ", "")
|
||||||
|
content = re.sub(r"[\u2066\u2067\u2068\u2069, \u00e2\u0081\u00a8]", "", codecs.decode(line.split(": ")[-1].encode("latin1").decode("utf-8"), "unicode_escape"))
|
||||||
|
content = re.sub(r"[\u00a9]", " ", content)
|
||||||
|
|
||||||
|
if "App name" in line:
|
||||||
|
appname = line.split(": ")[-1]
|
||||||
|
if "Urgency" in line:
|
||||||
|
urgency = line.split(": ")[-1]
|
||||||
|
|
||||||
|
if number is not None and content is not None and appname is not None and urgency is not None:
|
||||||
|
notifications.append((number, content, appname, urgency))
|
||||||
|
number = None
|
||||||
|
content = None
|
||||||
|
appname = None
|
||||||
|
urgency = None
|
||||||
|
|
||||||
|
return notifications
|
||||||
|
|
||||||
|
def get_icon(notifications):
|
||||||
|
status = ""
|
||||||
|
icon = ""
|
||||||
|
|
||||||
|
for number, content, appname, urgency in notifications:
|
||||||
|
status = "notify"
|
||||||
|
if urgency != "normal":
|
||||||
|
status = "alert"
|
||||||
|
break
|
||||||
|
|
||||||
|
if status == "notify":
|
||||||
|
icon = ""
|
||||||
|
if status == "alert":
|
||||||
|
icon = ""
|
||||||
|
|
||||||
|
return icon, status
|
||||||
|
|
||||||
|
def build_tooltip(notifications):
|
||||||
|
tooltip = ""
|
||||||
|
for number, content, appname, urgency in notifications:
|
||||||
|
tooltip += "{0}: {1}\n".format(appname, content)
|
||||||
|
|
||||||
|
return tooltip
|
||||||
|
|
||||||
|
def main():
|
||||||
|
notifications = check_notifications()
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
icon, status = get_icon(notifications)
|
||||||
|
|
||||||
|
data["text"] = icon
|
||||||
|
data["tooltip"] = build_tooltip(notifications)
|
||||||
|
data["class"] = status
|
||||||
|
|
||||||
|
print(json.dumps(data, ensure_ascii=False))
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [ ../options.nix ];
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
home.packages = [ waybar-notifications ];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,20 +1,34 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
namespace,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
cfg = config.mjallen.programs.waybar;
|
cfg = config.${namespace}.programs.waybar;
|
||||||
|
|
||||||
waybar-weather = pkgs.writeScriptBin "waybar-weather" ''
|
waybar-weather = pkgs.writeScriptBin "waybar-weather" ''
|
||||||
#!/usr/bin/env nix-shell
|
#!/usr/bin/env nix-shell
|
||||||
#! nix-shell -i python3 --pure
|
#! nix-shell -i python3 --pure
|
||||||
#! nix-shell -p python3 python3Packages.requests
|
#! nix-shell -p python3 python3Packages.requests
|
||||||
|
|
||||||
"""get waybar weather"""
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import shutil
|
import shutil
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
import argparse
|
||||||
|
import math
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(prog='waybar-weather')
|
||||||
|
parser.add_argument('--waybar', action='store_true')
|
||||||
|
parser.add_argument('--hyprlock', action='store_true')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# --- MAPPINGS ---
|
||||||
|
|
||||||
WWO_CODE = {
|
WWO_CODE = {
|
||||||
"113": "Sunny",
|
"113": "Sunny",
|
||||||
"116": "PartlyCloudy",
|
"116": "PartlyCloudy",
|
||||||
@@ -66,6 +80,38 @@ let
|
|||||||
"395": "HeavySnowShowers",
|
"395": "HeavySnowShowers",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Maps WMO codes (OpenMeteo) to WWO codes (wttr.in)
|
||||||
|
WMO_TO_WWO = {
|
||||||
|
0: "113", # Clear sky -> Sunny
|
||||||
|
1: "113", # Mainly clear -> Sunny
|
||||||
|
2: "116", # Partly cloudy
|
||||||
|
3: "122", # Overcast -> VeryCloudy
|
||||||
|
45: "143", # Fog
|
||||||
|
48: "248", # Depositing rime fog
|
||||||
|
51: "266", # Drizzle: Light
|
||||||
|
53: "266", # Drizzle: Moderate (mapped to LightRain)
|
||||||
|
55: "296", # Drizzle: Dense intensity (LightRain usually suits better than heavy)
|
||||||
|
56: "281", # Freezing Drizzle: Light
|
||||||
|
57: "284", # Freezing Drizzle: Dense
|
||||||
|
61: "296", # Rain: Slight
|
||||||
|
63: "302", # Rain: Moderate
|
||||||
|
65: "308", # Rain: Heavy
|
||||||
|
66: "311", # Freezing Rain: Light
|
||||||
|
67: "314", # Freezing Rain: Heavy
|
||||||
|
71: "326", # Snow fall: Slight
|
||||||
|
73: "332", # Snow fall: Moderate
|
||||||
|
75: "338", # Snow fall: Heavy
|
||||||
|
77: "350", # Snow grains
|
||||||
|
80: "353", # Rain showers: Slight
|
||||||
|
81: "356", # Rain showers: Moderate
|
||||||
|
82: "359", # Rain showers: Violent
|
||||||
|
85: "368", # Snow showers: Slight
|
||||||
|
86: "371", # Snow showers: Heavy
|
||||||
|
95: "386", # Thunderstorm: Slight or moderate
|
||||||
|
96: "389", # Thunderstorm with slight hail
|
||||||
|
99: "395", # Thunderstorm with heavy hail
|
||||||
|
}
|
||||||
|
|
||||||
WEATHER_SYMBOL = {
|
WEATHER_SYMBOL = {
|
||||||
"Unknown": "",
|
"Unknown": "",
|
||||||
"Cloudy": "",
|
"Cloudy": "",
|
||||||
@@ -93,18 +139,18 @@ let
|
|||||||
WIND_DIRECTION = {
|
WIND_DIRECTION = {
|
||||||
"S": "↓",
|
"S": "↓",
|
||||||
"SW": "↙",
|
"SW": "↙",
|
||||||
|
"SSW": "↙",
|
||||||
"W": "←",
|
"W": "←",
|
||||||
"NW": "↖",
|
"NW": "↖",
|
||||||
|
"NNW": "↖",
|
||||||
"N": "↑",
|
"N": "↑",
|
||||||
"NE": "↗",
|
"NE": "↗",
|
||||||
|
"NNE": "↗",
|
||||||
"E": "→",
|
"E": "→",
|
||||||
"SE": "↘",
|
"SE": "↘",
|
||||||
|
"SSE": "↘",
|
||||||
}
|
}
|
||||||
|
|
||||||
MOON_PHASES = (
|
|
||||||
"", "", "", "", "", "", "", ""
|
|
||||||
)
|
|
||||||
|
|
||||||
WEATHER_SYMBOL_WI_DAY = {
|
WEATHER_SYMBOL_WI_DAY = {
|
||||||
"Unknown": "",
|
"Unknown": "",
|
||||||
"Cloudy": "",
|
"Cloudy": "",
|
||||||
@@ -181,117 +227,117 @@ let
|
|||||||
' '],
|
' '],
|
||||||
"VeryCloudy": [
|
"VeryCloudy": [
|
||||||
' ',
|
' ',
|
||||||
'<span foreground=\"#585858\"; font-weight: bold;"> .--. </span>',
|
'<span foreground=\"#585858\" font-weight="bold"> .--. </span>',
|
||||||
'<span foreground=\"#585858\"; font-weight: bold;"> .-( ). </span>',
|
'<span foreground=\"#585858\" font-weight="bold"> .-( ). </span>',
|
||||||
'<span foreground=\"#585858\"; font-weight: bold;"> (___.__)__) </span>',
|
'<span foreground=\"#585858\" font-weight="bold"> (___.__)__) </span>',
|
||||||
' '],
|
' '],
|
||||||
"LightShowers": [
|
"LightShowers": [
|
||||||
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#BBBBBB\">.-. </span>',
|
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#BBBBBB\">.-. </span>',
|
||||||
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#BBBBBB\">( ). </span>',
|
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#BBBBBB\">( ). </span>',
|
||||||
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#BBBBBB\">(___(__) </span>',
|
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#BBBBBB\">(___(__) </span>',
|
||||||
'<span foreground=\"#87afff\";"> ‘ ‘ ‘ ‘ </span>',
|
'<span foreground=\"#87afff\"> ‘ ‘ ‘ ‘ </span>',
|
||||||
'<span foreground=\"#87afff\";"> ‘ ‘ ‘ ‘ </span>'],
|
'<span foreground=\"#87afff\"> ‘ ‘ ‘ ‘ </span>'],
|
||||||
"HeavyShowers": [
|
"HeavyShowers": [
|
||||||
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#585858\"; font-weight: bold;">.-. </span>',
|
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#585858\" font-weight="bold">.-. </span>',
|
||||||
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#585858\"; font-weight: bold;">( ). </span>',
|
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#585858\" font-weight="bold">( ). </span>',
|
||||||
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#585858\"; font-weight: bold;">(___(__) </span>',
|
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#585858\" font-weight="bold">(___(__) </span>',
|
||||||
'<span foreground=\"#0000ff\"; font-weight: bold;"> ‚‘‚‘‚‘‚‘ </span>',
|
'<span foreground=\"#0000ff\" font-weight="bold"> ‚‘‚‘‚‘‚‘ </span>',
|
||||||
'<span foreground=\"#0000ff\"; font-weight: bold;"> ‚’‚’‚’‚’ </span>'],
|
'<span foreground=\"#0000ff\" font-weight="bold"> ‚’‚’‚’‚’ </span>'],
|
||||||
"LightSnowShowers": [
|
"LightSnowShowers": [
|
||||||
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#BBBBBB\">.-. </span>',
|
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#BBBBBB\">.-. </span>',
|
||||||
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#BBBBBB\">( ). </span>',
|
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#BBBBBB\">( ). </span>',
|
||||||
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#BBBBBB\">(___(__) </span>',
|
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#BBBBBB\">(___(__) </span>',
|
||||||
'<span foreground=\"#eeeeee\";"> * * * </span>',
|
'<span foreground=\"#eeeeee\"> * * * </span>',
|
||||||
'<span foreground=\"#eeeeee\";"> * * * </span>'],
|
'<span foreground=\"#eeeeee\"> * * * </span>'],
|
||||||
"HeavySnowShowers": [
|
"HeavySnowShowers": [
|
||||||
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#585858\"; font-weight: bold;">.-. </span>',
|
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#585858\" font-weight="bold">.-. </span>',
|
||||||
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#585858\"; font-weight: bold;">( ). </span>',
|
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#585858\" font-weight="bold">( ). </span>',
|
||||||
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#585858\"; font-weight: bold;">(___(__) </span>',
|
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#585858\" font-weight="bold">(___(__) </span>',
|
||||||
'<span foreground=\"#eeeeee\"; font-weight: bold;"> * * * * </span>',
|
'<span foreground=\"#eeeeee\" font-weight="bold"> * * * * </span>',
|
||||||
'<span foreground=\"#eeeeee\"; font-weight: bold;"> * * * * </span>'],
|
'<span foreground=\"#eeeeee\" font-weight="bold"> * * * * </span>'],
|
||||||
"LightSleetShowers": [
|
"LightSleetShowers": [
|
||||||
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#BBBBBB\">.-. </span>',
|
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#BBBBBB\">.-. </span>',
|
||||||
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#BBBBBB\">( ). </span>',
|
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#BBBBBB\">( ). </span>',
|
||||||
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#BBBBBB\">(___(__) </span>',
|
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#BBBBBB\">(___(__) </span>',
|
||||||
'<span foreground=\"#87afff\";"> ‘ </span>"<span foreground=\"#eeeeee\";">*</span>"<span foreground=\"#87afff\";"> ‘ </span>"<span foreground=\"#eeeeee\";">* </span>',
|
'<span foreground=\"#87afff\"> ‘ </span>"<span foreground=\"#eeeeee\">*</span>"<span foreground=\"#87afff\"> ‘ </span>"<span foreground=\"#eeeeee\">* </span>',
|
||||||
'<span foreground=\"#eeeeee\";"> *</span>"<span foreground=\"#87afff\";"> ‘ </span>"<span foreground=\"#eeeeee\";">*</span>"<span foreground=\"#87afff\";"> ‘ </span>'],
|
'<span foreground=\"#eeeeee\"> *</span>"<span foreground=\"#87afff\"> ‘ </span>"<span foreground=\"#eeeeee\">*</span>"<span foreground=\"#87afff\"> ‘ </span>'],
|
||||||
"ThunderyShowers": [
|
"ThunderyShowers": [
|
||||||
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#BBBBBB\">.-. </span>',
|
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#BBBBBB\">.-. </span>',
|
||||||
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#BBBBBB\">( ). </span>',
|
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#BBBBBB\">( ). </span>',
|
||||||
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#BBBBBB\">(___(__) </span>',
|
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#BBBBBB\">(___(__) </span>',
|
||||||
'<span foreground=\"#ffff87\";"> ⚡\\</span>"<span foreground=\"#87afff\";">‘ ‘</span>"<span foreground=\"#ffff87\";">⚡\\</span>"<span foreground=\"#87afff\";">‘ ‘ </span>',
|
'<span foreground=\"#ffff87\"> ⚡\\</span>"<span foreground=\"#87afff\">‘ ‘</span>"<span foreground=\"#ffff87\">⚡\\</span>"<span foreground=\"#87afff\">‘ ‘ </span>',
|
||||||
'<span foreground=\"#87afff\";"> ‘ ‘ ‘ ‘ </span>'],
|
'<span foreground=\"#87afff\"> ‘ ‘ ‘ ‘ </span>'],
|
||||||
"ThunderyHeavyRain": [
|
"ThunderyHeavyRain": [
|
||||||
'<span foreground=\"#585858\"; font-weight: bold;"> .-. </span>',
|
'<span foreground=\"#585858\" font-weight="bold"> .-. </span>',
|
||||||
'<span foreground=\"#585858\"; font-weight: bold;"> ( ). </span>',
|
'<span foreground=\"#585858\" font-weight="bold"> ( ). </span>',
|
||||||
'<span foreground=\"#585858\"; font-weight: bold;"> (___(__) </span>',
|
'<span foreground=\"#585858\" font-weight="bold"> (___(__) </span>',
|
||||||
'<span foreground=\"#0000ff\"; font-weight: bold;"> ‚‘</span>"<span foreground=\"#ffff87\";">⚡\\</span>"<span foreground=\"#0000ff\";">‘‚</span>"<span foreground=\"#ffff87\";">⚡\\</span>"<span foreground=\"#0000ff\";">‚‘ </span>',
|
'<span foreground=\"#0000ff\" font-weight="bold"> ‚‘</span>"<span foreground=\"#ffff87\">⚡\\</span>"<span foreground=\"#0000ff\">‘‚</span>"<span foreground=\"#ffff87\">⚡\\</span>"<span foreground=\"#0000ff\">‚‘ </span>',
|
||||||
'<span foreground=\"#0000ff\"; font-weight: bold;"> ‚’‚’</span>"<span foreground=\"#ffff87\";">⚡\\</span>"<span foreground=\"#0000ff\";">’‚’ </span>'],
|
'<span foreground=\"#0000ff\" font-weight="bold"> ‚’‚’</span>"<span foreground=\"#ffff87\">⚡\\</span>"<span foreground=\"#0000ff\">’‚’ </span>'],
|
||||||
"ThunderySnowShowers": [
|
"ThunderySnowShowers": [
|
||||||
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#BBBBBB\">.-. </span>',
|
'<span foreground=\"#FFFF00\"> _`/\'\'</span>"<span foreground=\"#BBBBBB\">.-. </span>',
|
||||||
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#BBBBBB\">( ). </span>',
|
'<span foreground=\"#FFFF00\"> ,\\_</span>"<span foreground=\"#BBBBBB\">( ). </span>',
|
||||||
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#BBBBBB\">(___(__) </span>',
|
'<span foreground=\"#FFFF00\"> /</span>"<span foreground=\"#BBBBBB\">(___(__) </span>',
|
||||||
'<span foreground=\"#eeeeee\";"> *</span>"<span foreground=\"#ffff87\";">⚡\\</span>"<span foreground=\"#eeeeee\";">*</span>"<span foreground=\"#ffff87\";">⚡\\</span>"<span foreground=\"#eeeeee\";">* </span>',
|
'<span foreground=\"#eeeeee\"> *</span>"<span foreground=\"#ffff87\">⚡\\</span>"<span foreground=\"#eeeeee\">*</span>"<span foreground=\"#ffff87\">⚡\\</span>"<span foreground=\"#eeeeee\">* </span>',
|
||||||
'<span foreground=\"#eeeeee\";"> * * * </span>'],
|
'<span foreground=\"#eeeeee\"> * * * </span>'],
|
||||||
"LightRain": [
|
"LightRain": [
|
||||||
'<span foreground=\"#BBBBBB\"> .-. </span>',
|
'<span foreground=\"#BBBBBB\"> .-. </span>',
|
||||||
'<span foreground=\"#BBBBBB\"> ( ). </span>',
|
'<span foreground=\"#BBBBBB\"> ( ). </span>',
|
||||||
'<span foreground=\"#BBBBBB\"> (___(__) </span>',
|
'<span foreground=\"#BBBBBB\"> (___(__) </span>',
|
||||||
'<span foreground=\"#87afff\";"> ‘ ‘ ‘ ‘ </span>',
|
'<span foreground=\"#87afff\"> ‘ ‘ ‘ ‘ </span>',
|
||||||
'<span foreground=\"#87afff\";"> ‘ ‘ ‘ ‘ </span>'],
|
'<span foreground=\"#87afff\"> ‘ ‘ ‘ ‘ </span>'],
|
||||||
"HeavyRain": [
|
"HeavyRain": [
|
||||||
'<span foreground=\"#585858\"; font-weight: bold;"> .-. </span>',
|
'<span foreground=\"#585858\" font-weight="bold"> .-. </span>',
|
||||||
'<span foreground=\"#585858\"; font-weight: bold;"> ( ). </span>',
|
'<span foreground=\"#585858\" font-weight="bold"> ( ). </span>',
|
||||||
'<span foreground=\"#585858\"; font-weight: bold;"> (___(__) </span>',
|
'<span foreground=\"#585858\" font-weight="bold"> (___(__) </span>',
|
||||||
'<span foreground=\"#0000ff\"; font-weight: bold;"> ‚‘‚‘‚‘‚‘ </span>',
|
'<span foreground=\"#0000ff\" font-weight="bold"> ‚‘‚‘‚‘‚‘ </span>',
|
||||||
'<span foreground=\"#0000ff\"; font-weight: bold;"> ‚’‚’‚’‚’ </span>'],
|
'<span foreground=\"#0000ff\" font-weight="bold"> ‚’‚’‚’‚’ </span>'],
|
||||||
"LightSnow": [
|
"LightSnow": [
|
||||||
'<span foreground=\"#BBBBBB\"> .-. </span>',
|
'<span foreground=\"#BBBBBB\"> .-. </span>',
|
||||||
'<span foreground=\"#BBBBBB\"> ( ). </span>',
|
'<span foreground=\"#BBBBBB\"> ( ). </span>',
|
||||||
'<span foreground=\"#BBBBBB\"> (___(__) </span>',
|
'<span foreground=\"#BBBBBB\"> (___(__) </span>',
|
||||||
'<span foreground=\"#eeeeee\";"> * * * </span>',
|
'<span foreground=\"#eeeeee\"> * * * </span>',
|
||||||
'<span foreground=\"#eeeeee\";"> * * * </span>'],
|
'<span foreground=\"#eeeeee\"> * * * </span>'],
|
||||||
"HeavySnow": [
|
"HeavySnow": [
|
||||||
'<span foreground=\"#585858\"; font-weight: bold;"> .-. </span>',
|
'<span foreground=\"#585858\" font-weight="bold"> .-. </span>',
|
||||||
'<span foreground=\"#585858\"; font-weight: bold;"> ( ). </span>',
|
'<span foreground=\"#585858\" font-weight="bold"> ( ). </span>',
|
||||||
'<span foreground=\"#585858\"; font-weight: bold;"> (___(__) </span>',
|
'<span foreground=\"#585858\" font-weight="bold"> (___(__) </span>',
|
||||||
'<span foreground=\"#eeeeee\"; font-weight: bold;"> * * * * </span>',
|
'<span foreground=\"#eeeeee\" font-weight="bold"> * * * * </span>',
|
||||||
'<span foreground=\"#eeeeee\"; font-weight: bold;"> * * * * </span>'],
|
'<span foreground=\"#eeeeee\" font-weight="bold"> * * * * </span>'],
|
||||||
"LightSleet": [
|
"LightSleet": [
|
||||||
'<span foreground=\"#BBBBBB\"> .-. </span>',
|
'<span foreground=\"#BBBBBB\"> .-. </span>',
|
||||||
'<span foreground=\"#BBBBBB\"> ( ). </span>',
|
'<span foreground=\"#BBBBBB\"> ( ). </span>',
|
||||||
'<span foreground=\"#BBBBBB\"> (___(__) </span>',
|
'<span foreground=\"#BBBBBB\"> (___(__) </span>',
|
||||||
'<span foreground=\"#87afff\";"> ‘ </span>"<span foreground=\"#eeeeee\";">*</span>"<span foreground=\"#87afff\";"> ‘ </span>"<span foreground=\"#eeeeee\";">* </span>',
|
'<span foreground=\"#87afff\"> ‘ </span>"<span foreground=\"#eeeeee\">*</span>"<span foreground=\"#87afff\"> ‘ </span>"<span foreground=\"#eeeeee\">* </span>',
|
||||||
'<span foreground=\"#eeeeee\";"> *</span>"<span foreground=\"#87afff\";"> ‘ </span>"<span foreground=\"#eeeeee\";">*</span>"<span foreground=\"#87afff\";"> ‘ </span>'],
|
'<span foreground=\"#eeeeee\"> *</span>"<span foreground=\"#87afff\"> ‘ </span>"<span foreground=\"#eeeeee\">*</span>"<span foreground=\"#87afff\"> ‘ </span>'],
|
||||||
"Fog": [
|
"Fog": [
|
||||||
' ',
|
' ',
|
||||||
'<span foreground=\"#c0c0c0\";"> _ - _ - _ - </span>',
|
'<span foreground=\"#c0c0c0\"> _ - _ - _ - </span>',
|
||||||
'<span foreground=\"#c0c0c0\";"> _ - _ - _ </span>',
|
'<span foreground=\"#c0c0c0\"> _ - _ - _ </span>',
|
||||||
'<span foreground=\"#c0c0c0\";"> _ - _ - _ - </span>',
|
'<span foreground=\"#c0c0c0\"> _ - _ - _ - </span>',
|
||||||
' '],
|
' '],
|
||||||
}
|
}
|
||||||
|
|
||||||
WEATHER_CODES_WEGO = {key: WEATHER_SYMBOL_WEGO[value] for key, value in WWO_CODE.items()}
|
WEATHER_CODES_WEGO = {key: WEATHER_SYMBOL_WEGO[value] for key, value in WWO_CODE.items()}
|
||||||
|
|
||||||
data = {}
|
CACHE_DIR = os.path.join(os.environ.get("XDG_CACHE_HOME", os.path.expanduser("~/.cache")), "waybar-weather")
|
||||||
|
CACHE_FILE = os.path.join(CACHE_DIR, "wttr.json")
|
||||||
|
CACHE_MOON_FILE = os.path.join(CACHE_DIR, "moon.json")
|
||||||
|
CACHE_MOON_ICON_FILE = os.path.join(CACHE_DIR, "moon-icon")
|
||||||
|
CACHE_TTL = timedelta(minutes=10)
|
||||||
|
|
||||||
|
data = {}
|
||||||
|
data["text"] = ""
|
||||||
|
|
||||||
def format_time(time):
|
def format_time(time):
|
||||||
"""get the time formatted"""
|
|
||||||
return datetime.strptime(format_24_time(time), "%H").strftime("%I %p")
|
return datetime.strptime(format_24_time(time), "%H").strftime("%I %p")
|
||||||
|
|
||||||
def format_24_time(time):
|
def format_24_time(time):
|
||||||
"""get the time formatted"""
|
|
||||||
return time.replace("00", "").zfill(2)
|
return time.replace("00", "").zfill(2)
|
||||||
|
|
||||||
|
|
||||||
def format_temp(temp):
|
def format_temp(temp):
|
||||||
"""get the temp formatted"""
|
return (str(temp) + "°").ljust(3)
|
||||||
return (temp + "°").ljust(3)
|
|
||||||
|
|
||||||
|
|
||||||
def format_chances(hour):
|
def format_chances(hour):
|
||||||
"""get the chances formatted"""
|
|
||||||
chances = {
|
chances = {
|
||||||
"chanceoffog": "Fog",
|
"chanceoffog": "Fog",
|
||||||
"chanceoffrost": "Frost",
|
"chanceoffrost": "Frost",
|
||||||
@@ -302,60 +348,67 @@ let
|
|||||||
"chanceofthunder": "Thunder",
|
"chanceofthunder": "Thunder",
|
||||||
"chanceofwindy": "Wind",
|
"chanceofwindy": "Wind",
|
||||||
}
|
}
|
||||||
|
|
||||||
conditions = []
|
conditions = []
|
||||||
for chance, event in chances.items():
|
for chance, event in chances.items():
|
||||||
if int(hour[chance]) > 0:
|
if int(hour.get(chance, 0)) > 0:
|
||||||
conditions.append(event + " " + hour[chance] + "%")
|
conditions.append(event + " " + str(hour[chance]) + "%")
|
||||||
return ", ".join(conditions)
|
return ", ".join(conditions)
|
||||||
|
|
||||||
|
def deg_to_compass(num):
|
||||||
|
val = int((num / 22.5) + 0.5)
|
||||||
|
arr = ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"]
|
||||||
|
return arr[(val % 16)]
|
||||||
|
|
||||||
def build_text(current_condition):
|
def build_text(current_condition):
|
||||||
"""build the text string"""
|
|
||||||
feels_like_f = current_condition["FeelsLikeF"]
|
feels_like_f = current_condition["FeelsLikeF"]
|
||||||
weather_code = current_condition["weatherCode"]
|
weather_code = current_condition["weatherCode"]
|
||||||
|
# Check if we have a mapped format; if not, fallback to Unknown
|
||||||
|
if weather_code not in WEATHER_CODES:
|
||||||
|
weather_code = "113" # Fallback to sunny/default to prevent crash
|
||||||
|
|
||||||
tempint = int(feels_like_f)
|
tempint = int(float(feels_like_f)) # float cast just in case
|
||||||
extrachar = ""
|
extrachar = ""
|
||||||
if 0 < tempint < 10:
|
if 0 < tempint < 10:
|
||||||
extrachar = "+"
|
extrachar = "+"
|
||||||
|
|
||||||
current_weather = f"{WEATHER_CODES[weather_code]} {extrachar} {feels_like_f}°F"
|
current_weather = f"{WEATHER_CODES[weather_code]} {extrachar} {int(feels_like_f)}°F"
|
||||||
|
|
||||||
return current_weather
|
return current_weather
|
||||||
|
|
||||||
def build_tooltip(current_condition, astronomy, moon_icon):
|
def build_tooltip(current_condition, astronomy, moon_icon):
|
||||||
"""build the tooltip text"""
|
|
||||||
weather_description = current_condition['weatherDesc'][0]['value']
|
weather_description = current_condition['weatherDesc'][0]['value']
|
||||||
feels_like_f = current_condition["FeelsLikeF"]
|
feels_like_f = current_condition["FeelsLikeF"]
|
||||||
temp_f = current_condition['temp_F']
|
temp_f = current_condition['temp_F']
|
||||||
humidity = current_condition['humidity']
|
humidity = current_condition['humidity']
|
||||||
wind_speed = current_condition['windspeedMiles']
|
wind_speed = current_condition['windspeedMiles']
|
||||||
wind_dir = current_condition['winddir16Point']
|
wind_dir = current_condition['winddir16Point']
|
||||||
moon_phase = astronomy['moon_phase']
|
moon_phase = astronomy.get('moon_phase', 'Unknown')
|
||||||
wego = WEATHER_CODES_WEGO[current_condition['weatherCode']]
|
|
||||||
|
weather_code = current_condition['weatherCode']
|
||||||
|
if weather_code not in WEATHER_CODES_WEGO:
|
||||||
|
weather_code = "113"
|
||||||
|
|
||||||
tooltip = f"{wego[0]}{weather_description} {temp_f}°\n"
|
wego = WEATHER_CODES_WEGO[weather_code]
|
||||||
tooltip += f"{wego[1]}Feels like: {feels_like_f}°\n"
|
|
||||||
tooltip += f"{wego[2]}Wind: {wind_speed}mph {WIND_DIRECTION[wind_dir]}\n"
|
|
||||||
tooltip += f"{wego[3]}Humidity: {humidity}%\n"
|
|
||||||
tooltip += f"{wego[4]}Moon phase: {moon_phase} " + moon_icon + "\n"
|
|
||||||
|
|
||||||
|
current = f"{wego[0]}{weather_description} {temp_f}°\n"
|
||||||
|
feels = f"{wego[1]}Feels like: {feels_like_f}°\n"
|
||||||
|
wind = f"{wego[2]}Wind: {wind_speed}mph {WIND_DIRECTION.get(wind_dir, ''\'')}\n" # Safe get for direction
|
||||||
|
humidityl = f"{wego[3]}Humidity: {humidity}%\n"
|
||||||
|
moon = f"{wego[4]}Moon phase: {moon_phase} " + moon_icon + "\n"
|
||||||
|
|
||||||
|
tooltip = current + feels + wind + humidityl + moon
|
||||||
return tooltip
|
return tooltip
|
||||||
|
|
||||||
def build_forecast(weather):
|
def build_forecast(weather):
|
||||||
"""build a 3 day forecast"""
|
|
||||||
tooltip = "\n"
|
tooltip = "\n"
|
||||||
|
|
||||||
for i, day in enumerate(weather):
|
for i, day in enumerate(weather):
|
||||||
# determine day
|
|
||||||
if i == 0:
|
if i == 0:
|
||||||
tooltip += "Today, "
|
tooltip += "Today, "
|
||||||
if i == 1:
|
if i == 1:
|
||||||
tooltip += "Tomorrow, "
|
tooltip += "Tomorrow, "
|
||||||
# format the date
|
|
||||||
date = datetime.strptime(day['date'], "%Y-%m-%d").strftime("%a %b %d %Y")
|
date = datetime.strptime(day['date'], "%Y-%m-%d").strftime("%a %b %d %Y")
|
||||||
tooltip += f"<b>{date}</b>\n"
|
tooltip += f"<b>{date}</b>\n"
|
||||||
# set the high and low
|
|
||||||
max_temp = day['maxtempF']
|
max_temp = day['maxtempF']
|
||||||
min_temp = day['mintempF']
|
min_temp = day['mintempF']
|
||||||
tooltip += f" {max_temp}°F {min_temp}°F"
|
tooltip += f" {max_temp}°F {min_temp}°F"
|
||||||
@@ -367,29 +420,34 @@ let
|
|||||||
tooltip += build_hourly_forecast(i, day['hourly'], sunrise, sunset)
|
tooltip += build_hourly_forecast(i, day['hourly'], sunrise, sunset)
|
||||||
return tooltip
|
return tooltip
|
||||||
|
|
||||||
|
|
||||||
def build_hourly_forecast(day_num, hourly, sunrise, sunset):
|
def build_hourly_forecast(day_num, hourly, sunrise, sunset):
|
||||||
"""build an hourly forecast"""
|
try:
|
||||||
sunrise_hour = datetime.strptime(sunrise, "%I:%M %p").hour
|
sunrise_hour = datetime.strptime(sunrise, "%I:%M %p").hour
|
||||||
sunset_hour = datetime.strptime(sunset, "%I:%M %p").hour
|
sunset_hour = datetime.strptime(sunset, "%I:%M %p").hour
|
||||||
|
except ValueError:
|
||||||
|
# Fallback if time format is different (OpenMeteo might send 24h)
|
||||||
|
sunrise_hour = int(sunrise.split(':')[0])
|
||||||
|
sunset_hour = int(sunset.split(':')[0])
|
||||||
|
|
||||||
current_hour = datetime.now().hour
|
current_hour = datetime.now().hour
|
||||||
tooltip = ""
|
tooltip = ""
|
||||||
|
|
||||||
for hour in hourly:
|
for hour in hourly:
|
||||||
time_24_hr = int(format_24_time(hour["time"]))
|
time_24_hr = int(format_24_time(hour["time"]))
|
||||||
|
|
||||||
if day_num == 0:
|
if day_num == 0:
|
||||||
if time_24_hr < current_hour - 2:
|
if time_24_hr < current_hour - 2:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# determine which code to use
|
|
||||||
if is_night_hour(time_24_hr, sunrise_hour, sunset_hour):
|
if is_night_hour(time_24_hr, sunrise_hour, sunset_hour):
|
||||||
codes = WEATHER_CODES_WI_NIGHT
|
codes = WEATHER_CODES_WI_NIGHT
|
||||||
else:
|
else:
|
||||||
codes = WEATHER_CODES_WI_DAY
|
codes = WEATHER_CODES_WI_DAY
|
||||||
|
|
||||||
current_time = format_time(hour['time'])
|
current_time = format_time(hour['time'])
|
||||||
current_weather_code = codes[hour['weatherCode']]
|
wcode = hour['weatherCode']
|
||||||
|
if wcode not in codes: wcode = "113" # Fallback
|
||||||
|
|
||||||
|
current_weather_code = codes[wcode]
|
||||||
feels_like = format_temp(hour['FeelsLikeF'])
|
feels_like = format_temp(hour['FeelsLikeF'])
|
||||||
weather_desc = hour['weatherDesc'][0]['value']
|
weather_desc = hour['weatherDesc'][0]['value']
|
||||||
current_chances = format_chances(hour)
|
current_chances = format_chances(hour)
|
||||||
@@ -400,34 +458,188 @@ let
|
|||||||
return tooltip
|
return tooltip
|
||||||
|
|
||||||
def is_night_hour(time_24_hr, sunrise_hour, sunset_hour):
|
def is_night_hour(time_24_hr, sunrise_hour, sunset_hour):
|
||||||
"""returns true if the hour is night"""
|
|
||||||
before_sunrise = time_24_hr < sunrise_hour
|
before_sunrise = time_24_hr < sunrise_hour
|
||||||
after_sunset = time_24_hr > sunset_hour
|
after_sunset = time_24_hr > sunset_hour
|
||||||
return after_sunset or before_sunrise
|
return after_sunset or before_sunrise
|
||||||
|
|
||||||
def get_wttr_json():
|
def load_cache(path, ttl):
|
||||||
"""get the weather json"""
|
try:
|
||||||
weather = requests.get("https://wttr.in/?u&format=j1", timeout=30).json()
|
if not os.path.exists(path):
|
||||||
moon = requests.get("https://wttr.in/?format=%m", timeout=30)
|
return None
|
||||||
moon_icon = moon.text
|
mtime = datetime.fromtimestamp(os.path.getmtime(path))
|
||||||
|
if datetime.now() - mtime > ttl:
|
||||||
|
return None
|
||||||
|
with open(path, "r") as f:
|
||||||
|
if path.endswith(".json"):
|
||||||
|
return json.load(f)
|
||||||
|
return f.read().strip()
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
current_condition = weather["current_condition"][0]
|
def save_cache(path, data):
|
||||||
astronomy = weather["weather"][0]['astronomy'][0]
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||||
|
tmp = path + ".tmp"
|
||||||
|
try:
|
||||||
|
with open(tmp, "w") as f:
|
||||||
|
if isinstance(data, dict):
|
||||||
|
json.dump(data, f)
|
||||||
|
else:
|
||||||
|
f.write(str(data))
|
||||||
|
shutil.move(tmp, path)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
data["text"] = build_text(current_condition)
|
# --- OPEN-METEO INTEGRATION HELPER FUNCTIONS ---
|
||||||
data["tooltip"] = build_tooltip(current_condition, astronomy, moon_icon)
|
|
||||||
data["tooltip"] += build_forecast(weather["weather"])
|
|
||||||
|
|
||||||
return json.dumps(data)
|
def get_lat_lon():
|
||||||
|
"""Attempt to get location via IP if using OpenMeteo"""
|
||||||
|
try:
|
||||||
|
resp = requests.get("http://ip-api.com/json/", timeout=5).json()
|
||||||
|
return resp.get('lat'), resp.get('lon')
|
||||||
|
except:
|
||||||
|
# Default to a generic location if IP fetch fails (NYC)
|
||||||
|
return 40.71, -74.00
|
||||||
|
|
||||||
|
def fetch_open_meteo():
|
||||||
|
"""Fetch and Transform OpenMeteo data to match Wttr.in JSON structure"""
|
||||||
|
lat, lon = get_lat_lon()
|
||||||
|
url = "https://api.open-meteo.com/v1/forecast"
|
||||||
|
params = {
|
||||||
|
"latitude": lat,
|
||||||
|
"longitude": lon,
|
||||||
|
"current": "temperature_2m,apparent_temperature,precipitation,weather_code,wind_speed_10m,wind_direction_10m,relative_humidity_2m",
|
||||||
|
"daily": "weather_code,temperature_2m_max,temperature_2m_min,sunrise,sunset,precipitation_probability_max",
|
||||||
|
"hourly": "temperature_2m,apparent_temperature,precipitation_probability,weather_code",
|
||||||
|
"temperature_unit": "fahrenheit",
|
||||||
|
"wind_speed_unit": "mph",
|
||||||
|
"precipitation_unit": "inch",
|
||||||
|
"timezone": "auto"
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.get(url, params=params, timeout=10)
|
||||||
|
om_data = response.json()
|
||||||
|
|
||||||
|
# Transform Current Condition
|
||||||
|
current = om_data["current"]
|
||||||
|
wmo_code = current["weather_code"]
|
||||||
|
wwo_code = WMO_TO_WWO.get(wmo_code, "113")
|
||||||
|
|
||||||
|
wttr_current = {
|
||||||
|
"temp_F": str(int(current["temperature_2m"])),
|
||||||
|
"FeelsLikeF": str(int(current["apparent_temperature"])),
|
||||||
|
"weatherCode": wwo_code,
|
||||||
|
"weatherDesc": [{"value": WWO_CODE.get(wwo_code, "Unknown")}],
|
||||||
|
"humidity": str(current["relative_humidity_2m"]),
|
||||||
|
"windspeedMiles": str(int(current["wind_speed_10m"])),
|
||||||
|
"winddir16Point": deg_to_compass(current["wind_direction_10m"]),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Transform Daily Forecast (OpenMeteo gives 7 days, we need 3)
|
||||||
|
wttr_weather = []
|
||||||
|
daily = om_data["daily"]
|
||||||
|
hourly = om_data["hourly"]
|
||||||
|
|
||||||
|
for i in range(3):
|
||||||
|
date_str = daily["time"][i]
|
||||||
|
|
||||||
|
# Build Hourly for this day (wttr uses 3-hour intervals: 0, 300, 600...)
|
||||||
|
# OpenMeteo gives 0, 1, 2...
|
||||||
|
wttr_hourly = []
|
||||||
|
for h in range(0, 24, 3): # Step by 3 hours to mimic wttr
|
||||||
|
idx = (i * 24) + h
|
||||||
|
h_code = hourly["weather_code"][idx]
|
||||||
|
h_wwo = WMO_TO_WWO.get(h_code, "113")
|
||||||
|
|
||||||
|
wttr_hourly.append({
|
||||||
|
"time": str(h * 100), # 0, 300, 600
|
||||||
|
"weatherCode": h_wwo,
|
||||||
|
"weatherDesc": [{"value": WWO_CODE.get(h_wwo, "Unknown")}],
|
||||||
|
"FeelsLikeF": str(int(hourly["apparent_temperature"][idx])),
|
||||||
|
"chanceofrain": str(hourly["precipitation_probability"][idx]),
|
||||||
|
# Fill other chances with 0 as API doesn't provide them easily
|
||||||
|
"chanceoffog": "0", "chanceofsnow": "0", "chanceofthunder": "0",
|
||||||
|
"chanceofwindy": "0", "chanceofsunshine": "0"
|
||||||
|
})
|
||||||
|
|
||||||
|
# Astronomy
|
||||||
|
sunrise = datetime.fromisoformat(daily["sunrise"][i]).strftime("%I:%M %p")
|
||||||
|
sunset = datetime.fromisoformat(daily["sunset"][i]).strftime("%I:%M %p")
|
||||||
|
|
||||||
|
wttr_weather.append({
|
||||||
|
"date": date_str,
|
||||||
|
"maxtempF": str(int(daily["temperature_2m_max"][i])),
|
||||||
|
"mintempF": str(int(daily["temperature_2m_min"][i])),
|
||||||
|
"astronomy": [{"sunrise": sunrise, "sunset": sunset, "moon_phase": "Unknown"}],
|
||||||
|
"hourly": wttr_hourly
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
"current_condition": [wttr_current],
|
||||||
|
"weather": wttr_weather
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_wttr_json(hyprlock=False):
|
||||||
|
# Try loading cached JSON
|
||||||
|
cached = load_cache(CACHE_FILE, CACHE_TTL)
|
||||||
|
cached_moon = load_cache(CACHE_MOON_FILE, CACHE_TTL)
|
||||||
|
cached_moon_icon = load_cache(CACHE_MOON_ICON_FILE, CACHE_TTL)
|
||||||
|
|
||||||
|
if cached and cached_moon and cached_moon_icon:
|
||||||
|
weather = cached
|
||||||
|
current_condition = weather["current_condition"][0]
|
||||||
|
astronomy = cached_moon
|
||||||
|
moon_icon = cached_moon_icon
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
# Primary Source: wttr.in
|
||||||
|
weather = requests.get("https://wttr.in/?u&format=j1", timeout=5).json()
|
||||||
|
moon = requests.get("https://wttr.in/?format=%m", timeout=5)
|
||||||
|
moon_icon = moon.text
|
||||||
|
|
||||||
|
current_condition = weather["current_condition"][0]
|
||||||
|
astronomy = weather["weather"][0]['astronomy'][0]
|
||||||
|
except Exception:
|
||||||
|
# Fallback Source: Open-Meteo
|
||||||
|
try:
|
||||||
|
print("open_mateo fallback")
|
||||||
|
weather = fetch_open_meteo()
|
||||||
|
current_condition = weather["current_condition"][0]
|
||||||
|
astronomy = weather["weather"][0]['astronomy'][0]
|
||||||
|
moon_icon = "" # Generic moon icon for fallback
|
||||||
|
except Exception as e:
|
||||||
|
# If both fail
|
||||||
|
raise e
|
||||||
|
|
||||||
|
# Save cache (works for both sources since we transformed OM data)
|
||||||
|
save_cache(CACHE_FILE, weather)
|
||||||
|
save_cache(CACHE_MOON_FILE, astronomy)
|
||||||
|
save_cache(CACHE_MOON_ICON_FILE, moon_icon)
|
||||||
|
|
||||||
|
if hyprlock:
|
||||||
|
return build_tooltip(current_condition, astronomy, moon_icon)
|
||||||
|
else:
|
||||||
|
text = build_text(current_condition)
|
||||||
|
tooltip = build_tooltip(current_condition, astronomy, moon_icon) + build_forecast(weather["weather"])
|
||||||
|
data["text"] = text
|
||||||
|
data["tooltip"] = tooltip
|
||||||
|
return json.dumps(data)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""main"""
|
if args.hyprlock:
|
||||||
try:
|
try:
|
||||||
print(get_wttr_json())
|
print(get_wttr_json(hyprlock=True))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print("error")
|
||||||
|
# print(e) # Uncomment for debug
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
print(get_wttr_json())
|
||||||
|
except Exception as e:
|
||||||
|
print(json.dumps({"text": "Err", "tooltip": str(e)}))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
main()
|
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user