Compare commits
734 Commits
dd896748ab
...
trunk
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f4494d333 | |||
| 85255adb2c | |||
| f251a6f5c7 | |||
| 1f84cf19c7 | |||
| 0e49c1b9ee | |||
| 3ff5251b15 | |||
| 007c66c007 | |||
| d37a0ce652 | |||
| 5ab6c9e4c8 | |||
| fccec4d504 | |||
| 8feda54866 | |||
| 7179e6f047 | |||
| 1da9d994de | |||
| e213c64481 | |||
| 49ac3c2bf5 | |||
| 8acebb13cc | |||
| ff08538bae | |||
| 494ac6cf57 | |||
| 4cfddd2c7e | |||
| 60509f93f0 | |||
| 96d8fd1129 | |||
| 39264279e0 | |||
| 07c9533255 | |||
| 015f416169 | |||
| 35d8c83423 | |||
| b488af297a | |||
| dbb5560793 | |||
| 7bcfef3ccf | |||
| a1fd3b3af2 | |||
| a45d9014dd | |||
| 80451e9430 | |||
| df1a77f73e | |||
| 6f51671dbb | |||
| a238d2b61c | |||
|
62dd3f5d7c
|
|||
| 8b8dc8cde8 | |||
| 3047ff97b4 | |||
| 1c963f5563 | |||
| c02f2853c1 | |||
| d73a561b9d | |||
| 7d97acfdfb | |||
| cfb55f980d | |||
| 1a67b02d7c | |||
| 0196b1d8b2 | |||
| d7a6a85841 | |||
| cc7aca0fce | |||
| 6b393c7e4f | |||
| c9bcda6043 | |||
| 7ce43bf8e7 | |||
| 5a451bcaa1 | |||
| b4bba876ae | |||
| 005d0451f5 | |||
| d20a1787c2 | |||
| 6bb1a13741 | |||
| b21060e78d | |||
| 8caa3b6fe7 | |||
| 6fb6dc7abb | |||
| 4a6eb5059c | |||
| d92a192a7f | |||
| 51c3ae6d1e | |||
| 2ea0b96230 | |||
| f7ece5059d | |||
| b84a2d7628 | |||
| b78a43d40a | |||
| f5ff1a6639 | |||
| 0534a04108 | |||
| 4af26da42f | |||
| d014733441 | |||
| 38c0191ad2 | |||
| 2bbbd49a07 | |||
| 38a22b5255 | |||
| a787a7dfc5 | |||
| 4349ccb132 | |||
| 96920b6b3d | |||
| b97d7e4cb1 | |||
| 59927a4e3d | |||
| 076653fd15 | |||
| 63dcc450b6 | |||
| c15704eb22 | |||
| 85f7a2889c | |||
| 6bfea61ffe | |||
| 4e0cc2a322 | |||
| 7ef99c8dd1 | |||
| 1655c0a867 | |||
| 724c63f9ff | |||
| 5813db8160 | |||
| cdf8403991 | |||
| 10488b90c9 | |||
| bcb1b88861 | |||
| e27be65861 | |||
| 0e0e58b909 | |||
| 4e3a31cf87 | |||
| 58e68a003a | |||
| 82d61d54eb | |||
| fa981032d4 | |||
| 5090fa9cd4 | |||
| 125d639f9f | |||
| 9ad80827ee | |||
| f0fa2540b5 | |||
| 0bfe74abb7 | |||
| 766e20ffc4 | |||
| 178fba9c84 | |||
| eef41bbca8 | |||
| a0c728f147 | |||
| 35645a3e9c | |||
| 67002a94dd | |||
| 6beb28477f | |||
| dc03836ac0 | |||
| 646ba6d63f | |||
| e34b5161d4 | |||
| 81c59857e5 | |||
| 7576364d43 | |||
| f31eefe6eb | |||
| 788155194f | |||
| 777c4f3192 | |||
| e7ed3e584d | |||
| af9d2553d5 | |||
| 14c67a8bb3 | |||
| 97d2610240 | |||
| 2e36efa1c3 | |||
| 8a781d6b2a | |||
| c8a036edc2 | |||
| f0a8d8f0fb | |||
| 303c759bb4 | |||
| c243c4393f | |||
| de4822bc68 | |||
| ed3046e18a | |||
| e3546caeb5 | |||
| cc083128a3 | |||
| 9faad0e16c | |||
| e50f503270 | |||
| 8a502bdf15 | |||
| 32d737f011 | |||
| 7f84ae360c | |||
| bce6234c10 | |||
| 7572b52d6f | |||
| 68ca7ff5f8 | |||
| 51d9300990 | |||
| 183eb27980 | |||
| 3f689d46f4 | |||
| 2a576d8d39 | |||
| e92206ae43 | |||
| 733145692f | |||
| ad8b20fd0c | |||
| d9c20efa16 | |||
| 3bbe306485 | |||
| f9ac7944b3 | |||
| eff39f2218 | |||
| cdbb5f913d | |||
| e329c17546 | |||
| 85c8b9ec1c | |||
| 96fd9d96c1 | |||
| 090889dff2 | |||
| 8c4a82a73f | |||
| f448ce43ec | |||
| 2fb0dc4c50 | |||
| 2ed9add88e | |||
| 881d4dd78a | |||
| ad487e6715 | |||
| f107cf19c7 | |||
| f5bc0400ae | |||
| 96ca6c6ea0 | |||
| 610513edb7 | |||
| f49978d587 | |||
| cb4234630b | |||
| 992616c1ca | |||
| 7b39e418c9 | |||
| adf9d1ee4a | |||
| 0c4aed6591 | |||
| 1f8fe59423 | |||
| 0fc620e7da | |||
| 245f06fd3a | |||
| d39fb7af39 | |||
| 6ddebc86d7 | |||
| e2047cba7b | |||
| d7ae540ebf | |||
| 0fae0e72d3 | |||
| 3304d04d9d | |||
| e54f91bcd9 | |||
| 4d38c79dfa | |||
| 946413ada0 | |||
| 4c9b1651bf | |||
| 0fc3f1f501 | |||
| 9b758fdd96 | |||
| 225d102cea | |||
| 38b298fcd6 | |||
| a9579a7bf9 | |||
| 1192cef3ed | |||
| 8eae778b23 | |||
| 61fb81abef | |||
| 03c0b51343 | |||
| 647c94bd6e | |||
| e21db6c245 | |||
| 97b66bbb33 | |||
| edafa28c3e | |||
| 400ac5212f | |||
| c1182d8521 | |||
| b0bcc1040e | |||
| b08cb2ea82 | |||
| 021c4a9172 | |||
| dcf958c0a8 | |||
| 037a9b08e3 | |||
| 11f247bac8 | |||
| dd34c532d0 | |||
| 8b2dd3829a | |||
| 0b6e0b7577 | |||
| 0038a61fff | |||
| 5c1e292f60 | |||
| fc0f270c34 | |||
| 9f22aef6af | |||
| f04911def2 | |||
| 329f156f87 | |||
| f43f3b1749 | |||
| d4bcd95d52 | |||
| f1e9914ea1 | |||
| 419d86342d | |||
| b5b9633c3c | |||
| 93e1150a56 | |||
| ba40661f5e | |||
| a6d2c0030d | |||
| 458090e795 | |||
| 4078ed0d21 | |||
| 4a995d51c3 | |||
| 84b7477cff | |||
| ba2bcba53b | |||
| ec252348fd | |||
| 5a20416be1 | |||
| 83bdbd296f | |||
| b48bd36fd7 | |||
| 728425868c | |||
| 69d748c3ff | |||
| 4e59f2d8ca | |||
| 817f2b29a3 | |||
| c1ae4d7060 | |||
| fd4119a579 | |||
| fb64e3406b | |||
| 1268291250 | |||
| 5e3155b465 | |||
| de0117edff | |||
| 700943ab97 | |||
| 6fa11eea8f | |||
| 2d1d85ddc6 | |||
| 7a371f3b1e | |||
| bf8c4d050d | |||
| 1832c5ac83 | |||
| 6f1c74d243 | |||
| d1dde74c4f | |||
| 05607c2b48 | |||
| eea735134d | |||
| d9f06234fd | |||
| f4b505d1d1 | |||
| 24ac2aca51 | |||
| 4881ac5808 | |||
| b7fb67f939 | |||
| 32f37c7c2e | |||
| 0a31b25d83 | |||
| acc28d9278 | |||
| ae04500e63 | |||
| f463b76253 | |||
| 5298430415 | |||
| 14f790e67a | |||
| 6ca265e97b | |||
| 7b11dbdcfa | |||
| 652f005769 | |||
| 2149a58293 | |||
| 62a813eb81 | |||
| f11dbc52bc | |||
| 3e216701e0 | |||
| f72e067a4e | |||
| 39336740e1 | |||
| c8e7d0ac7f | |||
| 4991af44c3 | |||
| 7fd8610476 | |||
| 3eb9c9b402 | |||
| f2c320d9ee | |||
| 76d3410702 | |||
| 256b532938 | |||
| 27fb031175 | |||
| eef0c8cf27 | |||
| 643ab0958c | |||
| f597616843 | |||
| e4378fc6fe | |||
| bb65d89c39 | |||
| 93a3b83127 | |||
| 2f77f3b3a3 | |||
| 13a5def7d7 | |||
| 40f047eb1e | |||
| 3cba1640e0 | |||
| 3b12bf7081 | |||
| 06ec73de0b | |||
| 6d3ae434a5 | |||
| 1cc6abb89a | |||
| 25122a4c9c | |||
| d4f55ea042 | |||
| 52d96b7b2d | |||
| 598abd3c51 | |||
| f5f1ad4580 | |||
| 26d060e672 | |||
| a3424c1158 | |||
| 1083c6c3e4 | |||
| 0f2750b644 | |||
| 32a6d09113 | |||
| 0fd7319de6 | |||
| 8438c58c19 | |||
| 18679fc6ca | |||
| 2ad827e5fd | |||
| 311ac16dfc | |||
| 270f3cc9ee | |||
| 3f0ae38007 | |||
| 137ee537a8 | |||
| 1118071813 | |||
| 0450772e62 | |||
| 89b6380859 | |||
| 26401360d8 | |||
| f72a26d827 | |||
| 9fabb9143e | |||
| cc23884880 | |||
| 989ae8a432 | |||
| 9d38741068 | |||
| aebc51cc2e | |||
| b868f691d8 | |||
| 40077f3c6c | |||
| dd5c53a979 | |||
| dbf4ce2834 | |||
| c55e813b52 | |||
| 9934e12985 | |||
| d2cbb8dc81 | |||
| da7c4fe652 | |||
| ce3b8bf27a | |||
| cee4da2a1d | |||
| a1118ba84f | |||
| f25c552f76 | |||
| 09991e9684 | |||
| 9347a392f1 | |||
| 7a8a9e1c03 | |||
| c84b11c4c4 | |||
| 835782ff53 | |||
| 7925577fe4 | |||
| 65fdac2492 | |||
| 0c4008b544 | |||
| 4d3935527b | |||
| e32bdff7a8 | |||
| 8321e6fe2c | |||
| 69a671559a | |||
| e8a54ec95c | |||
| 7a211acea3 | |||
| 1e8b341977 | |||
| a92f00a2ac | |||
| 86d3855734 | |||
| 0057e3f757 | |||
| 28856a1328 | |||
| 1782467549 | |||
| 9c4f5716a2 | |||
| d75853b9ee | |||
| b688978b54 | |||
| acadff6243 | |||
| c01b0d8a99 | |||
| 9f6d24f885 | |||
| 8c19c9a228 | |||
| 06587673c0 | |||
| a960e1a018 | |||
| 5b83fe0f1d | |||
| a3e8019878 | |||
| 182cab6bf3 | |||
| 782ebcf4e3 | |||
| ea2be0de28 | |||
| 977d97fc0d | |||
| 8ec44dab44 | |||
| 962f44f05e | |||
| 6682df4338 | |||
| 3fa91f0670 | |||
| 9f7a97c6d9 | |||
| 7da8407475 | |||
| d4eefb864e | |||
| c02dafd0d1 | |||
| 9128bf3d66 | |||
| 042787770e | |||
| afb451d3cc | |||
| 1d1a13d9ce | |||
| ba38794ef4 | |||
| 30302af17b | |||
| 2f627902f3 | |||
| 3b2460f97a | |||
| c73adbe26f | |||
| 59476285df | |||
| 68ee7894a0 | |||
| dc5c5038b9 | |||
| 61e8436dd9 | |||
| cae85ef2e6 | |||
| 6226177c08 | |||
| 593449d0c3 | |||
| c1e56790c5 | |||
| 3acd59d938 | |||
| 758ab5beb1 | |||
| 39c108b3ee | |||
| cd55d1d7cf | |||
| f76c6862ba | |||
| abcad5c9f2 | |||
| b89c6a14cc | |||
| 86582c0dcc | |||
| 460d79c107 | |||
| 394d12a7b2 | |||
| 2cc42a5800 | |||
| 4c6f6ee68d | |||
| 15d82a44fb | |||
| 5168f5fc3e | |||
| d58262a043 | |||
| 2db7081bfc | |||
| bad309eb60 | |||
| 6ca3f8fedc | |||
| cd4cd68e96 | |||
| f6379435b8 | |||
| 36213c47c9 | |||
| ff096a520a | |||
| 00ab2ae68c | |||
| b4bf817c5e | |||
| 2b3b12b6a1 | |||
| 87ed8a6337 | |||
| c2a543f83b | |||
| fcbf908b15 | |||
| 1657efcae7 | |||
| ee51577189 | |||
| 6609922170 | |||
| 35be9990ba | |||
| cacb342117 | |||
| 23384e35ed | |||
| 0897deae29 | |||
| 63bd01d083 | |||
| 5ed18c1110 | |||
| f948a521c1 | |||
| 01982724ab | |||
| 4e22635c6a | |||
| f53c815437 | |||
| 74ec8a9bd6 | |||
| 953994d724 | |||
| 066d5ef4b6 | |||
| 406dafcd48 | |||
| d40192598f | |||
| d416a2f495 | |||
| 135cf3101f | |||
| 2f8046a022 | |||
| c7e81bdc6a | |||
| ddeef85822 | |||
| 0059e6637c | |||
| 1814824239 | |||
| e161686a73 | |||
| ba73f3163e | |||
| 09b23d71f5 | |||
| 4e183acd6f | |||
| 339d04c8fe | |||
| 60206f942e | |||
| 1ba1a158c7 | |||
| cdad146bd3 | |||
| 7803ab838e | |||
| abc79b3ab1 | |||
| 527c1d705f | |||
| 8903f8ac0e | |||
| e488f23b4c | |||
| 88a7316d99 | |||
| 04ebc668ce | |||
| 24afedc523 | |||
| 5c7659a5e9 | |||
| e663e247e5 | |||
| 62f00a06b8 | |||
| 6829124a9f | |||
| 95fb611c01 | |||
| 9e24635731 | |||
| c9840ed29e | |||
| 9bfae91d90 | |||
| 094678a2b1 | |||
| 2fc940a186 | |||
| 601a6d0d4e | |||
| 7b925a2eb8 | |||
| 34eaca1383 | |||
| c5f55f359b | |||
| 0c8d7af971 | |||
| 728176d27b | |||
| 384b18b575 | |||
| 21ecf083d2 | |||
| cb340e679c | |||
| 476a2106e1 | |||
| 03cff3b3e0 | |||
| d759a3e747 | |||
| 9fca78ed4c | |||
| 634e450ba1 | |||
| bcfdcad1b2 | |||
| cbaa2b9eb9 | |||
| 3f0900ed10 | |||
| 7326275c09 | |||
| 0ede6674dd | |||
| 5c53a81353 | |||
| e4bdf3af43 | |||
| 82dbb34bd0 | |||
| ada2bf81db | |||
| a17626a9cb | |||
| dbca751466 | |||
| 91f82d7dc3 | |||
| c637b6802b | |||
| f0ec85cc03 | |||
| 47ab6fa142 | |||
| 11028080bb | |||
| 49528805a5 | |||
| bbda7104ba | |||
| 32904bd35e | |||
| b5bbb6fd8e | |||
| 6819b00e6b | |||
| 1911315178 | |||
| 79b903403b | |||
| 634b09fc42 | |||
| 01fe78bffe | |||
| 790e358869 | |||
| 895b5d1add | |||
| de6b452d78 | |||
| 09603e8e30 | |||
| eec5b89396 | |||
| 4ba44f7248 | |||
| c749475fa9 | |||
| 6347aeab13 | |||
| f9f598827a | |||
| 0335d89b2f | |||
| b69c92e6db | |||
| 0077c9028a | |||
| c0e581ff08 | |||
| 5ecb7775ae | |||
| 3d7cad4fea | |||
| 952b0cc69a | |||
| 2f86551967 | |||
| 43e489ff52 | |||
| 3470cb1bbc | |||
| d46d270ad0 | |||
| 7205a6b00e | |||
| d49ed2acc3 | |||
| 89c1be5186 | |||
| 7d02cf9b19 | |||
| d7aabfaa4b | |||
| 2eafe082ba | |||
| efda5e5598 | |||
| 1eb60294cb | |||
| 2031aa443f | |||
| 7f56e043e7 | |||
| 0d78ee24a0 | |||
| fec6c6c146 | |||
| 7bd47ff538 | |||
| 0f0f838c1b | |||
| 247ab094d5 | |||
| 6508ed6159 | |||
| d924c98656 | |||
| 8c33edf4dd | |||
| d4200497a7 | |||
| d4b38ba1e7 | |||
| fa62f88352 | |||
| c818ac0e34 | |||
| a96471232e | |||
| fe35a1ef86 | |||
| e211775905 | |||
| 1055e10921 | |||
| ee7745f83f | |||
| 3e2ada161a | |||
| 51934f6577 | |||
| a27f922c5b | |||
| 7c5d2df922 | |||
| a3b3441b64 | |||
| ea5501723a | |||
| 347b4e9f74 | |||
| fd553ec4ca | |||
| 65af57f6d9 | |||
| 53a3bd0261 | |||
| 4206dbbb35 | |||
| 4f62d2746d | |||
| 6b01510afb | |||
| 3b4d0e3152 | |||
| f51570624b | |||
| 0cb49c0c42 | |||
| f3127697ca | |||
| 846d531ad3 | |||
| 58007d7743 | |||
| d258d95057 | |||
| 8d5743c0bc | |||
| f4b71070ce | |||
| badcab048c | |||
| 730bf26b93 | |||
| d333b3186b | |||
| 12936f35e2 | |||
| f50139dfca | |||
| f5625cc963 | |||
| 2854340455 | |||
| 1533db75f4 | |||
| 6fe75b1221 | |||
| 50e70d1cd1 | |||
| 83e60189b6 | |||
| 6a92cae6f7 | |||
| 9e30589699 | |||
| e6039316db | |||
| 0f5b1d83b5 | |||
| 0fb8657c2e | |||
| 59dd4bbe70 | |||
| 9e00aeca04 | |||
| 0c6c2562f3 | |||
| 4bac164d92 | |||
| afccaa5886 | |||
| 6a60ce6b85 | |||
| bf908ac917 | |||
| 7ceb225b06 | |||
| 6b291ecd40 | |||
| 64d7b799be | |||
| 33bfd2ed4f | |||
| 5ad52957fa | |||
| b3aa8fe80a | |||
| d43f12cdd2 | |||
| ff90df08d0 | |||
| 3fd4bb375e | |||
| a2ebf1dd31 | |||
| 1bab984f02 | |||
| 9fc91817fd | |||
| 4be5721730 | |||
| d45e598a2f | |||
| b2e4ee7e6b | |||
| 1f2d75d848 | |||
| b51aca18c7 | |||
| d7e1708f65 | |||
| a04fa13800 | |||
| 48c6d04db3 | |||
| ff4f6904fd | |||
| d377cda9a9 | |||
| 88bdb0b48c | |||
| e9b193afc2 | |||
| 463250c092 | |||
| 0485e78610 | |||
| ce6847fd36 | |||
| 502e53377f | |||
| f54922caf7 | |||
| fc6b0e9390 | |||
| dc4948063e | |||
| 4abe7423c8 | |||
| 1d7ac94c5d | |||
| 7d5c027da6 | |||
| 180d78430b | |||
| 26eac1e2a7 | |||
| 793ffda17a | |||
| 3e37b91846 | |||
| 5258bd62d8 | |||
| 39e44c0ade | |||
| cc673dde8e | |||
| e3c9bd23ee | |||
| 2fccc66805 | |||
| b78ba63ab5 | |||
| d6260546ca | |||
| 477d0bea34 | |||
| aed29a27de | |||
| d0c59fa764 | |||
| 42f5eb9c1a | |||
| b677b2f547 | |||
| 0632c3735e | |||
| 6b919051d9 | |||
| b6a56848b0 | |||
| 848a8ec406 | |||
| 00992dd0a2 | |||
| a4b0c2b91c | |||
| 7eda531e01 | |||
| a8fecf2c26 | |||
| f2f1b9cba5 | |||
| b5fc9b38e4 | |||
| 4332cbf69b | |||
| 4bc74cf035 | |||
| 622974ad88 | |||
| fa229e997d | |||
| 0e4786a464 | |||
| 83612a7f87 | |||
| 4cf4edff26 | |||
| 9a589ab24a | |||
| 53bf7fd64e | |||
| d61beb3f7b | |||
| 09991aa67d | |||
| a8f2cd7331 | |||
| b9a8012a48 | |||
| bc76eb71c3 | |||
| 7ff5c40f32 | |||
| fd5ef2c7e0 | |||
| fe54d9896b | |||
| 4f4341165e | |||
| a59b331bbe | |||
| 699c0d1f29 | |||
| 6b70ab5f69 | |||
| 15bf851f33 | |||
| 6cf3e58600 | |||
| e564e632b3 | |||
| fec251a4c3 | |||
| aa29d58e9d | |||
| e8fb6f383f | |||
| 3064a404e0 | |||
| 65a8654165 | |||
| 1876238748 | |||
| 13cfe73b65 | |||
| 56d7504a79 | |||
| 23170eb4fc | |||
| 7eb729d29a | |||
| 015045c56f | |||
| fa1d1310c9 | |||
| 0d9679ae0a | |||
| 11b7545928 | |||
| afbef1bf7d | |||
| 0fe813201a | |||
| 0bcf16b127 | |||
| 3a7f4de155 | |||
| 10f2b436f0 | |||
| 4bc8f56956 | |||
| 08a3d16a83 | |||
| a8dddf8cbb | |||
| 16d62f5ed2 | |||
| f754badc78 | |||
| ac642a20b1 | |||
| f9ed9ab55f | |||
| 9fb05656cc | |||
| 910b2125ae | |||
| 743858c6d1 | |||
| f9764fb3a6 | |||
| 73d57f7441 | |||
| f28c9ea93d | |||
| 85e6635bb7 | |||
| 8ce6cf9f89 | |||
| 208a21efd5 | |||
| d0065f8053 | |||
| 877e70cd48 | |||
| 576c83eabd | |||
| 2df106c25f | |||
| 52d12ceb26 | |||
| c080e647cc | |||
| 4ddb17b6d3 | |||
| 96e173ee29 | |||
| 13fb00dd10 | |||
| d607de1418 | |||
| 8181a339ae | |||
| adc334eab5 | |||
| 9f03fa499d |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@
|
||||
.keyring/
|
||||
.nixos-switch-log
|
||||
users/blake/dotfiles/zsh/zplug
|
||||
users/blake/dots/zsh/zplug
|
||||
users/blake/dotfiles/zsh/.zsh_history
|
||||
users/blake/dotfiles/zsh/.zcompdump
|
||||
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# --- SUDO CHECK ---
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "This script requires root privileges. Re-running with sudo..."
|
||||
exec sudo "$0" "$@"
|
||||
fi
|
||||
|
||||
# --- HANDLE OPTIONS ---
|
||||
BORG_PASSPHRASE=""
|
||||
SHOW_FOLDERS_ONLY=false
|
||||
SHOW_FILES=false # Default to showing files and directories
|
||||
|
||||
while getopts "k:fp" opt; do
|
||||
case "$opt" in
|
||||
k)
|
||||
BORG_PASSPHRASE=$(<"$OPTARG")
|
||||
if [ -z "$BORG_PASSPHRASE" ]; then
|
||||
echo "Error: The key file is empty."
|
||||
exit 1
|
||||
fi
|
||||
echo "Using passphrase from key file: $OPTARG"
|
||||
;;
|
||||
f)
|
||||
SHOW_FOLDERS_ONLY=true
|
||||
echo "Only directories will be shown in fzf by default."
|
||||
SHOW_FILES=false
|
||||
;;
|
||||
p)
|
||||
SHOW_FILES=true
|
||||
echo "Both files and directories will be shown in fzf."
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [-k passphrase_file] [-f] [-p] <repo>"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
# --- FALLBACK TO /run/secrets/borg_passwd IF NO KEY FILE ---
|
||||
if [ -z "$BORG_PASSPHRASE" ]; then
|
||||
if [ $# -eq 0 ]; then
|
||||
BORG_PASSPHRASE=$(<"/run/secrets/borg_passwd")
|
||||
echo "Using passphrase from /run/secrets/borg_passwd"
|
||||
else
|
||||
# Prompt user for passphrase if neither -k nor /run/secrets/borg_passwd is available
|
||||
read -s -p "Enter Borg repository passphrase: " BORG_PASSPHRASE
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
|
||||
export BORG_PASSPHRASE
|
||||
|
||||
# --- DEFAULT REPO ---
|
||||
REPO="${1:-/holocron/backups}"
|
||||
|
||||
# --- CHECK REQUIRED COMMANDS ---
|
||||
for cmd in borg fzf find tree cp mkdir; do
|
||||
command -v "$cmd" >/dev/null || { echo "Error: '$cmd' is required but not installed."; exit 1; }
|
||||
done
|
||||
|
||||
# --- LIST ARCHIVES (sorted, newest last) ---
|
||||
mapfile -t archives < <(borg list --format="{archive}{NL}" "$REPO" | sort -r)
|
||||
if [ ${#archives[@]} -eq 0 ]; then
|
||||
echo "No archives found in $REPO"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- FZF ARCHIVE SELECT ---
|
||||
selected=$(printf '%s\n' "${archives[@]}" | fzf --prompt="Select archive: " --height=40% --border)
|
||||
if [ -z "$selected" ]; then
|
||||
echo "No archive selected."
|
||||
exit 1
|
||||
fi
|
||||
echo "Selected archive: $selected"
|
||||
|
||||
# --- GENERATE A UNIQUE, SHORTER MOUNT POINT ---
|
||||
MOUNT_POINT="/tmp/$(uuidgen | sha256sum | head -c 2)-restore-${selected}"
|
||||
mkdir -p "$MOUNT_POINT"
|
||||
|
||||
# --- MOUNT ARCHIVE ---
|
||||
echo "Mounting '$selected' to $MOUNT_POINT..."
|
||||
borg mount "$REPO::$selected" "$MOUNT_POINT"
|
||||
|
||||
if [ ! -d "$MOUNT_POINT" ]; then
|
||||
echo "Error: mount failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- LIST FILES AND DIRECTORIES ---
|
||||
echo "Scanning files and directories..."
|
||||
if command -v fd >/dev/null 2>&1; then
|
||||
# List both files and directories with fd
|
||||
if [ "$SHOW_FILES" = true ]; then
|
||||
files=$(fd . "$MOUNT_POINT" | sort) # Show both files and directories
|
||||
else
|
||||
files=$(fd --type d . "$MOUNT_POINT" | sort) # Only directories
|
||||
fi
|
||||
else
|
||||
# Fall back to find if fd is not available
|
||||
if [ "$SHOW_FILES" = true ]; then
|
||||
files=$(find "$MOUNT_POINT" | sort) # Show both files and directories
|
||||
else
|
||||
files=$(find "$MOUNT_POINT" -type d | sort) # Only directories
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$files" ]; then
|
||||
echo "No files or directories found in archive."
|
||||
borg umount "$MOUNT_POINT"
|
||||
rm -rf "$MOUNT_POINT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- FZF FILE/DIRECTORY SELECTION ---
|
||||
if [ "$SHOW_FILES" = true ]; then
|
||||
# If showing files and directories, we pass everything to fzf
|
||||
selected_items=$(printf '%s\n' "$files" | sed "s|$MOUNT_POINT/||" | tac | fzf \
|
||||
--multi \
|
||||
--height=50% \
|
||||
--border \
|
||||
--prompt="Select files or directories to restore: " \
|
||||
--preview "tree -C -L 5 $MOUNT_POINT/$(dirname {})" \
|
||||
--preview-window=right:50% \
|
||||
--delimiter='/' \
|
||||
--with-nth=1..)
|
||||
else
|
||||
# If only showing directories, pass directories to fzf
|
||||
selected_items=$(printf '%s\n' "$files" | sed "s|$MOUNT_POINT/||" | tac | fzf \
|
||||
--multi \
|
||||
--height=50% \
|
||||
--border \
|
||||
--prompt="Select directories to restore: " \
|
||||
--preview "tree -C -d -L 3 $MOUNT_POINT/$(dirname {})" \
|
||||
--preview-window=right:50% \
|
||||
--delimiter='/' \
|
||||
--with-nth=1..)
|
||||
fi
|
||||
|
||||
if [ -z "$selected_items" ]; then
|
||||
echo "No items selected. Exiting."
|
||||
borg umount "$MOUNT_POINT"
|
||||
rm -rf "$MOUNT_POINT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- SUMMARY OF SELECTED ITEMS ---
|
||||
echo "Selected items:"
|
||||
for item in $selected_items; do
|
||||
echo " $item"
|
||||
done
|
||||
|
||||
# --- OPTIONS MENU (concise) ---
|
||||
# Default to option 1 if no input is given
|
||||
echo "Select restore destination: 1) Restore to ./${selected}_restore 2) Restore to original dirs 3) Quit"
|
||||
read -p "Enter your choice (1/2/3) [default: 1]: " choice
|
||||
# Default to option 1 if user presses Enter without providing input
|
||||
choice="${choice:-1}"
|
||||
|
||||
# --- SET RESTORE DESTINATION BASED ON USER CHOICE ---
|
||||
case "$choice" in
|
||||
1)
|
||||
DEST="./${selected}_restore"
|
||||
;;
|
||||
2)
|
||||
DEST="$MOUNT_POINT"
|
||||
;;
|
||||
3)
|
||||
echo "Quitting. No items restored."
|
||||
borg umount "$MOUNT_POINT"
|
||||
rm -rf "$MOUNT_POINT"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Invalid choice. Exiting."
|
||||
borg umount "$MOUNT_POINT"
|
||||
rm -rf "$MOUNT_POINT"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p "$DEST"
|
||||
|
||||
# --- RESTORE SELECTED ITEMS (FILES OR DIRECTORIES) ---
|
||||
echo "Restoring selected items..."
|
||||
while IFS= read -r item; do
|
||||
dest_path="$DEST/$item"
|
||||
mkdir -p "$(dirname "$dest_path")"
|
||||
if [ -d "$MOUNT_POINT/$item" ]; then
|
||||
cp -r "$MOUNT_POINT/$item" "$dest_path"
|
||||
else
|
||||
cp -a "$MOUNT_POINT/$item" "$dest_path"
|
||||
fi
|
||||
echo "Restored: $item"
|
||||
done <<< "$selected_items"
|
||||
|
||||
# --- CLEANUP ---
|
||||
borg umount "$MOUNT_POINT"
|
||||
rm -rf "$MOUNT_POINT"
|
||||
echo "Restore complete."
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# --- SUDO CHECK ---
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "This script requires root privileges. Re-running with sudo..."
|
||||
exec sudo "$0" "$@"
|
||||
fi
|
||||
|
||||
# --- HANDLE -k OPTION FOR KEY FILE ---
|
||||
BORG_PASSPHRASE=""
|
||||
|
||||
while getopts "k:" opt; do
|
||||
case "$opt" in
|
||||
k)
|
||||
BORG_PASSPHRASE=$(<"$OPTARG")
|
||||
if [ -z "$BORG_PASSPHRASE" ]; then
|
||||
echo "Error: The key file is empty."
|
||||
exit 1
|
||||
fi
|
||||
echo "Using passphrase from key file: $OPTARG"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [-k passphrase_file] <repo>"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
# --- FALLBACK TO /run/secrets/borg_passwd IF NO KEY FILE ---
|
||||
if [ -z "$BORG_PASSPHRASE" ]; then
|
||||
if [ -f "/run/secrets/borg_passwd" ]; then
|
||||
BORG_PASSPHRASE=$(<"/run/secrets/borg_passwd")
|
||||
echo "Using passphrase from /run/secrets/borg_passwd"
|
||||
else
|
||||
# Prompt user for passphrase if neither -k nor /run/secrets/borg_passwd is available
|
||||
read -s -p "Enter Borg repository passphrase: " BORG_PASSPHRASE
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
|
||||
export BORG_PASSPHRASE
|
||||
|
||||
# --- DEFAULT REPO ---
|
||||
REPO="${1:-/holocron/backups}"
|
||||
|
||||
# --- CHECK REQUIRED COMMANDS ---
|
||||
for cmd in borg fzf find tree cp mkdir; do
|
||||
command -v "$cmd" >/dev/null || { echo "Error: '$cmd' is required but not installed."; exit 1; }
|
||||
done
|
||||
|
||||
# --- LIST ARCHIVES (sorted, newest last) ---
|
||||
mapfile -t archives < <(borg list --format="{archive}{NL}" "$REPO" | sort)
|
||||
if [ ${#archives[@]} -eq 0 ]; then
|
||||
echo "No archives found in $REPO"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- FZF ARCHIVE SELECT ---
|
||||
selected=$(printf '%s\n' "${archives[@]}" | fzf --prompt="Select archive: " --height=40% --border --reverse)
|
||||
if [ -z "$selected" ]; then
|
||||
echo "No archive selected."
|
||||
exit 1
|
||||
fi
|
||||
echo "Selected archive: $selected"
|
||||
|
||||
# --- GENERATE A UNIQUE, SHORTER MOUNT POINT ---
|
||||
MOUNT_POINT="/tmp/borg-mount-${selected}-$(uuidgen | sha256sum | head -c 6)"
|
||||
mkdir -p "$MOUNT_POINT"
|
||||
|
||||
# --- MOUNT ARCHIVE ---
|
||||
echo "Mounting '$selected' to $MOUNT_POINT..."
|
||||
borg mount "$REPO::$selected" "$MOUNT_POINT"
|
||||
|
||||
if [ ! -d "$MOUNT_POINT" ]; then
|
||||
echo "Error: mount failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- LIST FILES AND DIRECTORIES ---
|
||||
echo "Scanning files and directories..."
|
||||
if command -v fd >/dev/null 2>&1; then
|
||||
# List files and directories using fd (can handle both files and dirs)
|
||||
files=$(fd --type f --type d . "$MOUNT_POINT" | sort)
|
||||
else
|
||||
# Fall back to find if fd is not available
|
||||
files=$(find "$MOUNT_POINT" -type f -o -type d | sort)
|
||||
fi
|
||||
|
||||
if [ -z "$files" ]; then
|
||||
echo "No files or directories found in archive."
|
||||
borg umount "$MOUNT_POINT"
|
||||
rm -rf "$MOUNT_POINT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- HIERARCHICAL FZF FILE/DIRECTORY SELECTION (REVERSED) ---
|
||||
# We reverse the order of files to display the latest (newest) files/folders at the top.
|
||||
selected_files=$(printf '%s\n' "$files" | sed "s|$MOUNT_POINT/||" | tac | fzf \
|
||||
--multi \
|
||||
--height=50% \
|
||||
--border \
|
||||
--prompt="Select files or directories to restore: " \
|
||||
--preview "tree -C -L 5 $MOUNT_POINT/$(dirname {})" \
|
||||
--preview-window=right:50% \
|
||||
--delimiter='/' \
|
||||
--with-nth=1..)
|
||||
|
||||
if [ -z "$selected_files" ]; then
|
||||
echo "No files or directories selected. Exiting."
|
||||
borg umount "$MOUNT_POINT"
|
||||
rm -rf "$MOUNT_POINT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- SUMMARY OF SELECTED FILES/DIRECTORIES ---
|
||||
echo "Selected files and directories:"
|
||||
for file in $selected_files; do
|
||||
echo " $file"
|
||||
done
|
||||
|
||||
# --- OPTIONS MENU (concise) ---
|
||||
# Default to option 1 if no input is given
|
||||
echo "Select restore destination: 1) Restore to ./${selected}_restore 2) Restore to original dirs 3) Quit"
|
||||
read -p "Enter your choice (1/2/3) [default: 1]: " choice
|
||||
# Default to option 1 if user presses Enter without providing input
|
||||
choice="${choice:-1}"
|
||||
|
||||
# --- SET RESTORE DESTINATION BASED ON USER CHOICE ---
|
||||
case "$choice" in
|
||||
1)
|
||||
DEST="./${selected}_restore"
|
||||
;;
|
||||
2)
|
||||
DEST="$MOUNT_POINT"
|
||||
;;
|
||||
3)
|
||||
echo "Quitting. No files restored."
|
||||
borg umount "$MOUNT_POINT"
|
||||
rm -rf "$MOUNT_POINT"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Invalid choice. Exiting."
|
||||
borg umount "$MOUNT_POINT"
|
||||
rm -rf "$MOUNT_POINT"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p "$DEST"
|
||||
|
||||
# --- RESTORE FILES AND DIRECTORIES ---
|
||||
echo "Restoring selected files and directories..."
|
||||
while IFS= read -r file; do
|
||||
# Path is already stripped of /tmp, so no need for further modification
|
||||
dest_path="$DEST/$file"
|
||||
mkdir -p "$(dirname "$dest_path")"
|
||||
# If it's a directory, we use cp -r to ensure the directory structure is restored
|
||||
if [ -d "$MOUNT_POINT/$file" ]; then
|
||||
cp -r "$MOUNT_POINT/$file" "$dest_path"
|
||||
else
|
||||
cp -a "$MOUNT_POINT/$file" "$dest_path"
|
||||
fi
|
||||
echo "Restored: $file"
|
||||
done <<< "$selected_files"
|
||||
|
||||
# --- CLEANUP ---
|
||||
borg umount "$MOUNT_POINT"
|
||||
rm -rf "$MOUNT_POINT"
|
||||
echo "Restore complete."
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# borg-browser.sh — fzf-based Borg archive browser with passphrase prompt
|
||||
|
||||
[ "$EUID" -ne 0 ] && { echo "Please run as root."; exec sudo "$0" "$@"; }
|
||||
|
||||
REPO="/holocron/backups"
|
||||
|
||||
# Prompt once for Borg passphrase
|
||||
read -rs -p "Borg passphrase: " BORG_PASSPHRASE
|
||||
echo
|
||||
export BORG_PASSPHRASE
|
||||
|
||||
# Pick an archive
|
||||
ARCHIVE=$(borg list --short "$REPO" | fzf --prompt="Select archive: ") || {
|
||||
unset BORG_PASSPHRASE
|
||||
exit
|
||||
}
|
||||
[ -z "$ARCHIVE" ] && { unset BORG_PASSPHRASE; exit; }
|
||||
|
||||
# Function to browse directories hierarchically
|
||||
browse_borg_dir() {
|
||||
local prefix="$1"
|
||||
|
||||
while true; do
|
||||
# Get immediate children of the current path
|
||||
ITEMS=$(borg list --format='{path}{NL}' "$REPO::$ARCHIVE" \
|
||||
| awk -v p="$prefix" -F/ '
|
||||
BEGIN{n=split(p,a,"/")}
|
||||
index($0,p)==1 && NF>n {
|
||||
if (NF==n+1) print $NF;
|
||||
else print $(n+1)"/";
|
||||
}' \
|
||||
| sort -u)
|
||||
|
||||
[ -z "$ITEMS" ] && { echo "No items found in $prefix"; return; }
|
||||
|
||||
SELECTION=$(echo -e "../\n$ITEMS" | fzf --prompt="${prefix:-/}> ")
|
||||
case "$SELECTION" in
|
||||
"../")
|
||||
prefix="${prefix%/*}"
|
||||
prefix="${prefix%/}"
|
||||
;;
|
||||
"")
|
||||
return
|
||||
;;
|
||||
*/)
|
||||
prefix="${prefix:+$prefix/}${SELECTION%/}"
|
||||
;;
|
||||
*)
|
||||
local fullpath="${prefix:+$prefix/}$SELECTION"
|
||||
echo "Selected file: $fullpath"
|
||||
read -rp "Extract it here? [y/N]: " yn
|
||||
if [[ $yn =~ ^[Yy]$ ]]; then
|
||||
borg extract "$REPO::$ARCHIVE" "$fullpath"
|
||||
fi
|
||||
return
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
browse_borg_dir ""
|
||||
unset BORG_PASSPHRASE
|
||||
|
||||
@@ -17,6 +17,10 @@ TARGET=""
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-m|--media)
|
||||
OWNER=":media"
|
||||
shift
|
||||
;;
|
||||
-o|--owner)
|
||||
OWNER="$2"
|
||||
shift 2
|
||||
46
bin/rebuild
Executable file
46
bin/rebuild
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
#echo "searching generations"
|
||||
# your hostname (flake target)
|
||||
hostname="$(hostname)"
|
||||
#old_gen=$(nixos-rebuild list-generations | grep current | awk '{print $1}')
|
||||
#gen=$((old_gen + 1))
|
||||
#echo "gen $old_gen --> gen $gen"
|
||||
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
nix_dir="$HOME/.nix"
|
||||
logfile="$nix_dir/.nixos-switch-log"
|
||||
|
||||
|
||||
pushd "$nix_dir" >/dev/null
|
||||
|
||||
# function to get current nixos generation
|
||||
#get_current_generation() {
|
||||
# nixos-rebuild list-generations
|
||||
#}
|
||||
|
||||
echo "diffs:"
|
||||
git diff
|
||||
echo ""
|
||||
echo "files:"
|
||||
git status --short
|
||||
read -rp "commit message: " commit_msg
|
||||
echo "rebuilding nixos with flake.nix..."
|
||||
#if ! sudo nixos-rebuild switch --flake .#"$hostname" 2>&1 | tee "$logfile"; then
|
||||
#if ! nh os switch 2>&1 | tee "$logfile"; then
|
||||
if ! sudo nixos-rebuild switch --flake .#"$hostname" 2>&1 | tee "$logfile"; then
|
||||
echo "rebuild failed; exited with no commit"
|
||||
exit 1
|
||||
fi
|
||||
#if sed -n '3p' flake.nix | grep -q '^# generation:'; then
|
||||
# # replace the comment on line 3
|
||||
# sed -i "3s|^# generation:.*|# generation: $gen, timestamp: $timestamp|" flake.nix
|
||||
#else
|
||||
# # insert comment on line 3
|
||||
# sed -i "3i# generation: $gen, timestamp: $timestamp" flake.nix
|
||||
#fi
|
||||
echo "committing..."
|
||||
git add $nix_dir
|
||||
git commit -m "$commit_msg"
|
||||
echo "flake rebuild and commit fin"
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
pushd ~/.nix
|
||||
# nvim flake.nix
|
||||
# alejandra . &>/dev/null
|
||||
# git diff -U0 *.nix
|
||||
|
||||
# add generation comment to flake.nix
|
||||
gen=$(nixos-rebuild list-generations | grep current)
|
||||
if sed -n '3p' flake.nix | grep -q '^# generation:'; then
|
||||
# replace the comment on line 3
|
||||
sed -i "3s/^# generation:.*/# generation: $gen/" flake.nix
|
||||
else
|
||||
# insert comment on line 3
|
||||
sed -i "3i# generation: $gen" flake.nix
|
||||
fi
|
||||
|
||||
git diff -U0 $(find . -name '*.nix')
|
||||
|
||||
echo "nixos rebuilding..."
|
||||
#sudo nixos-rebuild switch --flake ~/.nix#snowbelle &>.nixos-switch-log || (
|
||||
# cat .nixos-switch-log | grep --color error && false)
|
||||
sudo nixos-rebuild switch --flake ~/.nix#snowbelle 2>&1 | tee .nixos-switch-log | grep --color=always -E "error|$" && true
|
||||
|
||||
git commit -am "$gen"
|
||||
popd
|
||||
1420
flake.lock
generated
1420
flake.lock
generated
File diff suppressed because it is too large
Load Diff
150
flake.nix
150
flake.nix
@@ -1,52 +1,134 @@
|
||||
# flake for blakes nixos config
|
||||
# define new devices in outputs
|
||||
# generation: 203 current 2025-10-10 00:56:13 25.05.20251006.20c4598 6.12.50 *
|
||||
# generation: 378, timestamp: 2025-10-12 19:57:35
|
||||
{
|
||||
description = "blakes nix config";
|
||||
inputs = {
|
||||
nixpkgs.url = "nixpkgs/nixos-25.05";
|
||||
nixpkgs.url = "nixpkgs/nixos-25.11";
|
||||
nixpkgs-unstable.url = "nixpkgs/nixos-unstable";
|
||||
nix-darwin = {
|
||||
url = "github:nix-darwin/nix-darwin/master";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
};
|
||||
home-manager = {
|
||||
url = "github:nix-community/home-manager/release-25.05";
|
||||
url = "github:nix-community/home-manager/release-25.11";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
home-manager-unstable = {
|
||||
url = "github:nix-community/home-manager";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
};
|
||||
nix-homebrew.url = "github:zhaofengli/nix-homebrew";
|
||||
nix-flatpak.url = "github:gmodena/nix-flatpak/?ref=latest";
|
||||
sops-nix = {
|
||||
url = "github:Mic92/sops-nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
disko = {
|
||||
url = "github:nix-community/disko/latest";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
lanzaboote = {
|
||||
url = "github:nix-community/lanzaboote/v0.4.3";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
watershot = {
|
||||
url = "github:Kirottu/watershot";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
vpn-confinement = {
|
||||
url = "github:Maroka-chan/VPN-Confinement";
|
||||
};
|
||||
};
|
||||
outputs = { self, nixpkgs, nixpkgs-unstable, ... }@inputs:
|
||||
let
|
||||
systems = {
|
||||
x86_64 = "x86_64-linux";
|
||||
arm64 = "aarch64-linux";
|
||||
darwin = "aarch64-darwin";
|
||||
};
|
||||
stable_pkgs = builtins.mapAttrs (k: v: import nixpkgs { system = v; }) systems;
|
||||
unstable_pkgs = builtins.mapAttrs (k: v: import nixpkgs-unstable { system = v; }) systems;
|
||||
in
|
||||
{
|
||||
nixosConfigurations = {
|
||||
snowbelle = nixpkgs.lib.nixosSystem {
|
||||
system = systems.x86_64;
|
||||
specialArgs = { inherit inputs stable_pkgs unstable_pkgs; };
|
||||
modules = [
|
||||
./hosts/snowbelle/configuration.nix
|
||||
inputs.home-manager.nixosModules.default
|
||||
inputs.vpn-confinement.nixosModules.default
|
||||
];
|
||||
};
|
||||
vaniville = nixpkgs.lib.nixosSystem {
|
||||
system = systems.x86_64;
|
||||
specialArgs = { inherit inputs stable_pkgs unstable_pkgs; };
|
||||
modules = [
|
||||
./hosts/vaniville/configuration.nix
|
||||
inputs.home-manager.nixosModules.default
|
||||
];
|
||||
};
|
||||
};
|
||||
nvf = {
|
||||
url = "github:notashelf/nvf/v0.8";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
autoaspm = {
|
||||
url = "git+https://git.notthebe.ee/notthebee/AutoASPM.git";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
stylix = {
|
||||
url = "github:nix-community/stylix";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
};
|
||||
copyparty.url = "github:9001/copyparty";
|
||||
slippi = {
|
||||
url = "github:lytedev/slippi-nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
};
|
||||
};
|
||||
outputs = {
|
||||
self,
|
||||
nixpkgs,
|
||||
nixpkgs-unstable,
|
||||
nix-darwin,
|
||||
nix-homebrew,
|
||||
...
|
||||
} @ inputs: let
|
||||
systems = {
|
||||
x86_64 = "x86_64-linux";
|
||||
arm64 = "aarch64-linux";
|
||||
darwin = "aarch64-darwin";
|
||||
};
|
||||
stable_pkgs = builtins.mapAttrs (k: v: import nixpkgs {system = v;}) systems;
|
||||
unstable_pkgs = builtins.mapAttrs (k: v: import nixpkgs-unstable {system = v;}) systems;
|
||||
in {
|
||||
nixosConfigurations = {
|
||||
snowbelle = nixpkgs.lib.nixosSystem {
|
||||
system = systems.x86_64;
|
||||
specialArgs = {inherit inputs stable_pkgs unstable_pkgs;};
|
||||
modules = [
|
||||
./hosts/nixos/snowbelle/configuration.nix
|
||||
inputs.home-manager.nixosModules.default
|
||||
];
|
||||
};
|
||||
yveltal = nixpkgs-unstable.lib.nixosSystem {
|
||||
system = systems.x86_64;
|
||||
specialArgs = {inherit inputs stable_pkgs unstable_pkgs;};
|
||||
modules = [
|
||||
./hosts/nixos/yveltal/configuration.nix
|
||||
./hosts/nixos/yveltal/disko.nix
|
||||
inputs.home-manager-unstable.nixosModules.default
|
||||
inputs.disko.nixosModules.disko
|
||||
];
|
||||
};
|
||||
mew = nixpkgs-unstable.lib.nixosSystem {
|
||||
system = systems.x86_64;
|
||||
specialArgs = {inherit inputs stable_pkgs unstable_pkgs;};
|
||||
modules = [
|
||||
./hosts/nixos/mew/configuration.nix
|
||||
./hosts/nixos/mew/disko.nix
|
||||
inputs.home-manager-unstable.nixosModules.default
|
||||
inputs.disko.nixosModules.disko
|
||||
];
|
||||
};
|
||||
vaniville = nixpkgs.lib.nixosSystem {
|
||||
system = systems.x86_64;
|
||||
specialArgs = {inherit inputs stable_pkgs unstable_pkgs;};
|
||||
modules = [
|
||||
./hosts/nixos/vaniville/configuration.nix
|
||||
inputs.home-manager.nixosModules.default
|
||||
];
|
||||
};
|
||||
};
|
||||
darwinConfigurations = {
|
||||
CEN-IT-07 = nix-darwin.lib.darwinSystem {
|
||||
system = systems.darwin;
|
||||
specialArgs = {inherit inputs stable_pkgs unstable_pkgs nix-homebrew;};
|
||||
modules = [
|
||||
#./hosts/darwin/cen-it-07/configuration.nix
|
||||
inputs.home-manager.darwinModules.default
|
||||
nix-homebrew.darwinModules.nix-homebrew
|
||||
{
|
||||
nix-homebrew = {
|
||||
enable = true; # install homebrew
|
||||
enableRosetta = true; # install homebrew for rosetta as well
|
||||
autoMigrate = true;
|
||||
user = "bhelderman"; # user owning homebrew prefix
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
40
hosts/darwin/default.nix
Normal file
40
hosts/darwin/default.nix
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}: {
|
||||
|
||||
imports = [
|
||||
];
|
||||
|
||||
# base system package install list
|
||||
environment.systemPackages = with pkgs; [
|
||||
wget
|
||||
curl
|
||||
rsync
|
||||
git
|
||||
age
|
||||
fzf
|
||||
neofetch
|
||||
usbutils
|
||||
pciutils
|
||||
python3
|
||||
vim
|
||||
lf
|
||||
btop
|
||||
powertop
|
||||
];
|
||||
|
||||
# set timezone
|
||||
time.timeZone = "America/Chicago";
|
||||
|
||||
# allow proprietary packages
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
# enable flakes
|
||||
nix.settings.experimental-features = ["nix-command" "flakes"];
|
||||
users.defaultUserShell = pkgs.zsh;
|
||||
|
||||
}
|
||||
120
hosts/nixos/default.nix
Normal file
120
hosts/nixos/default.nix
Normal file
@@ -0,0 +1,120 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
inputs.autoaspm.nixosModules.default
|
||||
];
|
||||
|
||||
# set timezone
|
||||
time.timeZone = "America/Chicago";
|
||||
|
||||
nix = {
|
||||
# garbage collect & remove builds older then 14 days
|
||||
gc = {
|
||||
automatic = true;
|
||||
dates = "daily";
|
||||
options = "--delete-older-than 14d";
|
||||
persistent = true;
|
||||
};
|
||||
# optimise nix store, dedupe and such
|
||||
optimise = {
|
||||
automatic = true;
|
||||
dates = [ "daily" ];
|
||||
};
|
||||
# the goats
|
||||
settings = {
|
||||
substituters = [
|
||||
"https://cache.nixos.org"
|
||||
];
|
||||
trusted-public-keys = [
|
||||
];
|
||||
experimental-features = lib.mkDefault [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# allow proprietary packages
|
||||
nixpkgs = {
|
||||
config = {
|
||||
allowUnfree = true;
|
||||
allowUnfreePredicate = _: true;
|
||||
};
|
||||
};
|
||||
|
||||
# power management
|
||||
services.autoaspm.enable = true;
|
||||
powerManagement.powertop.enable = true;
|
||||
|
||||
# things are better this way
|
||||
users.defaultUserShell = pkgs.zsh;
|
||||
|
||||
# base system package install list
|
||||
environment.systemPackages = with pkgs; [
|
||||
wget
|
||||
curl
|
||||
dig
|
||||
nmap
|
||||
rsync
|
||||
iperf3
|
||||
jq
|
||||
git
|
||||
age
|
||||
vim
|
||||
ncdu
|
||||
btop
|
||||
powertop
|
||||
iotop
|
||||
cifs-utils
|
||||
usbutils
|
||||
pciutils
|
||||
lm_sensors
|
||||
];
|
||||
|
||||
# nice to have passwordless sudo
|
||||
security.sudo = {
|
||||
extraRules = [
|
||||
{
|
||||
users = ["blake"];
|
||||
commands = [
|
||||
{
|
||||
command = "/run/current-system/sw/bin/nixos-rebuild";
|
||||
options = ["NOPASSWD"];
|
||||
}
|
||||
{
|
||||
command = "/run/current-system/sw/bin/systemctl";
|
||||
options = ["NOPASSWD"];
|
||||
}
|
||||
{
|
||||
command = "/run/current-system/sw/bin/journalctl";
|
||||
options = ["NOPASSWD"];
|
||||
}
|
||||
{
|
||||
command = "/run/current-system/sw/bin/tailscale";
|
||||
options = ["NOPASSWD"];
|
||||
}
|
||||
{
|
||||
command = "/etc/profiles/per-user/blake/bin/nom";
|
||||
options = ["NOPASSWD"];
|
||||
}
|
||||
{
|
||||
command = "/etc/profiles/per-user/blake/bin/nom-build";
|
||||
options = ["NOPASSWD"];
|
||||
}
|
||||
{
|
||||
command = "/etc/profiles/per-user/blake/bin/nom-shell";
|
||||
options = ["NOPASSWD"];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
extraConfig = ''
|
||||
Defaults insults
|
||||
'';
|
||||
};
|
||||
}
|
||||
70
hosts/nixos/froakie/disko.nix
Normal file
70
hosts/nixos/froakie/disko.nix
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
disko.devices = {
|
||||
disk = {
|
||||
main = {
|
||||
type = "disk";
|
||||
device = ""; # disk id here
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
size = "1G";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [ "umask=0077" ];
|
||||
};
|
||||
};
|
||||
luks = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "luks";
|
||||
name = "crypted";
|
||||
# disable settings.keyFile if you want to use interactive password entry
|
||||
#passwordFile = "/tmp/secret.key"; # Interactive
|
||||
settings = {
|
||||
allowDiscards = true;
|
||||
#keyFile = "/tmp/secret.key";
|
||||
};
|
||||
#additionalKeyFiles = [ "/tmp/additionalSecret.key" ];
|
||||
content = {
|
||||
type = "btrfs";
|
||||
extraArgs = [ "-f" ];
|
||||
subvolumes = {
|
||||
"@root" = {
|
||||
mountpoint = "/";
|
||||
mountOptions = [
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"@home" = {
|
||||
mountpoint = "/home";
|
||||
mountOptions = [
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"@nix" = {
|
||||
mountpoint = "/nix";
|
||||
mountOptions = [
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"@swap" = {
|
||||
mountpoint = "/.swapvol";
|
||||
swap.swapfile.size = "32G";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
113
hosts/nixos/mew/configuration.nix
Normal file
113
hosts/nixos/mew/configuration.nix
Normal file
@@ -0,0 +1,113 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
modulesPath,
|
||||
inputs,
|
||||
stable_pkgs,
|
||||
unstable_pkgs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
# Include the results of the hardware scan.
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
#./hardware-configuration.nix
|
||||
../../nixos
|
||||
../../../users/blake
|
||||
../../../modules/desktop
|
||||
../../../modules/system
|
||||
];
|
||||
|
||||
# home grown nixos modules
|
||||
system = {
|
||||
secure_boot.enable = false;
|
||||
cifs_mounts.enable = true;
|
||||
udiskie.enable = true;
|
||||
ssh.enable = true;
|
||||
sops.enable = true;
|
||||
japanese.enable = true;
|
||||
yubikey.enable = true;
|
||||
yubikey.lock_on_remove = false;
|
||||
tailscale.enable = true;
|
||||
syncthing.enable = true;
|
||||
flatpak.enable = true;
|
||||
graphics = {
|
||||
enable = true;
|
||||
vendor = "amd";
|
||||
};
|
||||
};
|
||||
desktop = {
|
||||
pipewire.enable = true;
|
||||
hypr.enable = true;
|
||||
greetd.enable = true;
|
||||
};
|
||||
gaming = {
|
||||
steam.enable = true;
|
||||
lutris.enable = true;
|
||||
proton_ge.enable = true;
|
||||
gamemode.enable = true;
|
||||
mangohud.enable = true;
|
||||
};
|
||||
|
||||
# import home grown host specific home-manager modules
|
||||
home-manager.users.blake.imports = [
|
||||
../../../users/blake/hosts/yveltal.nix
|
||||
];
|
||||
|
||||
# fix power buttons
|
||||
# move this to a laptops file at some point
|
||||
services.logind.settings.Login = {
|
||||
HandlePowerKey = "suspend-then-hibernate";
|
||||
HandleLidSwitch = "suspend-then-hibernate";
|
||||
};
|
||||
# sets the delay before hibernation for ^
|
||||
systemd.sleep.extraConfig = ''
|
||||
HibernateDelaySec=1800
|
||||
'';
|
||||
|
||||
# boot (systemd is growing on me)
|
||||
boot = {
|
||||
kernelModules = [ "kvm-amd" ];
|
||||
extraModulePackages = [];
|
||||
loader = {
|
||||
systemd-boot.enable = true; # systemd your pretty cool ya know
|
||||
efi.canTouchEfiVariables = true;
|
||||
};
|
||||
initrd = {
|
||||
systemd.enable = true; # better logging
|
||||
availableKernelModules = ["xhci_pci" "thunderbolt" "vmd" "nvme" "usb_storage" "sd_mod" "ahci"];
|
||||
kernelModules = [];
|
||||
};
|
||||
};
|
||||
|
||||
# setup hostname and networking stack
|
||||
networking = {
|
||||
hostName = "mew"; # hostname
|
||||
useDHCP = lib.mkDefault true;
|
||||
interfaces = {
|
||||
wlp7s0.useDHCP = lib.mkDefault true;
|
||||
};
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [22];
|
||||
allowedUDPPorts = [51820]; # wireguard
|
||||
};
|
||||
networkmanager = {
|
||||
enable = true; # the goat
|
||||
dns = "systemd-resolved"; # the backup dancer!
|
||||
};
|
||||
};
|
||||
services.resolved = {
|
||||
enable = true;
|
||||
fallbackDns = ["1.1.1.1" "9.9.9.9"];
|
||||
dnsovertls = "opportunistic";
|
||||
};
|
||||
|
||||
hardware.bluetooth.enable = true;
|
||||
|
||||
system.stateVersion = "25.05"; # stays here : )
|
||||
|
||||
# hardware shit
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
||||
70
hosts/nixos/mew/disko.nix
Normal file
70
hosts/nixos/mew/disko.nix
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
disko.devices = {
|
||||
disk = {
|
||||
main = {
|
||||
type = "disk";
|
||||
device = "/dev/disk/by-id/nvme-MTFDHBA512TDV-1AZ1AABHA_UJUND0170FW7O0"; # disk id here
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
size = "1G";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [ "umask=0077" ];
|
||||
};
|
||||
};
|
||||
luks = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "luks";
|
||||
name = "crypted";
|
||||
# disable settings.keyFile if you want to use interactive password entry
|
||||
#passwordFile = "/tmp/secret.key"; # Interactive
|
||||
settings = {
|
||||
allowDiscards = true;
|
||||
#keyFile = "/tmp/secret.key";
|
||||
};
|
||||
#additionalKeyFiles = [ "/tmp/additionalSecret.key" ];
|
||||
content = {
|
||||
type = "btrfs";
|
||||
extraArgs = [ "-f" ];
|
||||
subvolumes = {
|
||||
"@root" = {
|
||||
mountpoint = "/";
|
||||
mountOptions = [
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"@home" = {
|
||||
mountpoint = "/home";
|
||||
mountOptions = [
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"@nix" = {
|
||||
mountpoint = "/nix";
|
||||
mountOptions = [
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"@swap" = {
|
||||
mountpoint = "/.swapvol";
|
||||
swap.swapfile.size = "32G";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
{ config, lib, stable_pkgs, unstable_pkgs, ... }:
|
||||
{ config, lib, inputs, stable_pkgs, unstable_pkgs, ... }:
|
||||
|
||||
let
|
||||
pkgs = stable_pkgs.x86_64;
|
||||
@@ -8,57 +8,66 @@ in
|
||||
imports =
|
||||
[ # Include the results of the hardware scan.
|
||||
./hardware-configuration.nix
|
||||
../../users/users.nix
|
||||
../../modules/system/default.nix
|
||||
../../modules/homelab/default.nix
|
||||
../../nixos
|
||||
../../../users/blake
|
||||
../../../modules/system
|
||||
../../../modules/holocron
|
||||
../../../modules/homelab
|
||||
../../../modules/gameservers/minecraft_recpro
|
||||
../../../modules/gameservers/minecraft_modded
|
||||
];
|
||||
|
||||
modules = {
|
||||
system = {
|
||||
ssh.enable = true;
|
||||
backups.enable = true;
|
||||
backups.repo = "/holocron/backups";
|
||||
sops.enable = true;
|
||||
docker.enable = true;
|
||||
syncthing.enable = true;
|
||||
tailscale.enable = true;
|
||||
vpns.enable = false;
|
||||
vpns.wg_mex = false;
|
||||
vpn-confinement.enable = false;
|
||||
nvidia.enable = true;
|
||||
};
|
||||
homelab = {
|
||||
home-manager.users.blake.imports = [
|
||||
../../../users/blake/hosts/snowbelle.nix
|
||||
];
|
||||
|
||||
system = {
|
||||
ssh.enable = true;
|
||||
sops.enable = true;
|
||||
podman.enable = true;
|
||||
yubikey.enable = true;
|
||||
graphics = {
|
||||
enable = true;
|
||||
zfs.enable = true;
|
||||
smb.enable = true;
|
||||
nfs.enable = true;
|
||||
nginx-proxy.enable = true;
|
||||
};
|
||||
services = {
|
||||
jellyfin.enable = true;
|
||||
vaultwarden.enable = true;
|
||||
gitea.enable = true;
|
||||
qbittorrent.enable = true;
|
||||
immich.enable = true;
|
||||
home-assistant.enable = true;
|
||||
zigbee2mqtt.enable = true;
|
||||
mosquitto.enable = true;
|
||||
prowlarr.enable = true;
|
||||
flaresolverr.enable = true;
|
||||
bazarr.enable = true;
|
||||
radarr.enable = true;
|
||||
sonarr.enable = true;
|
||||
uptime-kuma.enable = true;
|
||||
};
|
||||
gameservers = {
|
||||
minecraft_recpro.enable = true;
|
||||
vendor = "nvidia";
|
||||
};
|
||||
};
|
||||
|
||||
# configure users & groups
|
||||
users = {
|
||||
blake.enable = true; # main user, home manager
|
||||
defaultUserShell = pkgs.zsh; # the goat
|
||||
holocron = {
|
||||
syncthing.enable = true;
|
||||
copyparty.enable = false;
|
||||
ensure_perms.enable = false;
|
||||
zfs.enable = true;
|
||||
smb.enable = true;
|
||||
nfs.enable = true;
|
||||
};
|
||||
homelab = {
|
||||
enable = true;
|
||||
tailscale.enable = true;
|
||||
dnsmasq.enable = true;
|
||||
backups.enable = true;
|
||||
motd.enable = true;
|
||||
postfix.enable = true;
|
||||
gitea.enable = true;
|
||||
glance.enable = true;
|
||||
immich.enable = true;
|
||||
hass.enable = true;
|
||||
jellyfin.enable = true;
|
||||
audiobookshelf.enable = true;
|
||||
yacreader.enable = true;
|
||||
qbittorrent.enable = true;
|
||||
sonarr.enable = true;
|
||||
radarr.enable = true;
|
||||
bazarr.enable = true;
|
||||
prowlarr.enable = true;
|
||||
flaresolverr.enable = true;
|
||||
zigbee2mqtt.enable = true;
|
||||
mosquitto.enable = true;
|
||||
caddy.enable = true;
|
||||
uptime-kuma.enable = true;
|
||||
vaultwarden.enable = true;
|
||||
};
|
||||
gameservers = {
|
||||
minecraft_recpro.enable = true;
|
||||
minecraft_modded.enable = true;
|
||||
};
|
||||
|
||||
# boot (systemd is going on me)
|
||||
@@ -94,48 +103,10 @@ in
|
||||
};
|
||||
|
||||
|
||||
# set timezone
|
||||
time.timeZone = "America/Chicago";
|
||||
|
||||
hardware.bluetooth.enable = true;
|
||||
|
||||
# define shell
|
||||
programs.zsh.enable = true;
|
||||
|
||||
# package install list
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
age
|
||||
rsync
|
||||
wget
|
||||
curl
|
||||
fzf
|
||||
fd
|
||||
tree
|
||||
vim
|
||||
lf
|
||||
tmux
|
||||
btop
|
||||
neofetch
|
||||
usbutils
|
||||
inetutils
|
||||
iptables
|
||||
bluez
|
||||
];
|
||||
|
||||
|
||||
# allow proprietary packages
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
# ld fix
|
||||
programs.nix-ld.enable = true;
|
||||
programs.nix-ld.libraries = with pkgs; [
|
||||
# Add any missing dynamic libraries for unpackaged
|
||||
# programs here, NOT in environment.systemPackages
|
||||
];
|
||||
|
||||
# enable flakes
|
||||
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
||||
|
||||
# Open ports in the firewall.
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
@@ -167,6 +138,7 @@ in
|
||||
7704 # srv - hass
|
||||
7705 # srv - zigbee2mqtt
|
||||
7901 # srv - uptime kuma
|
||||
7902 # srv - copyparty
|
||||
25777 # srv - minecraft
|
||||
25565 # ^ ^ ^
|
||||
25566 # | | |
|
||||
@@ -177,7 +149,7 @@ in
|
||||
# Or disable the firewall altogether.
|
||||
networking.firewall.enable = true;
|
||||
|
||||
system.stateVersion = "25.05"; # Did you read the comment?
|
||||
system.stateVersion = "25.05"; # stays here : )
|
||||
|
||||
}
|
||||
|
||||
@@ -8,25 +8,16 @@ in
|
||||
imports =
|
||||
[ # Include the results of the hardware scan.
|
||||
./hardware-configuration.nix
|
||||
../../users/blake/blake.nix
|
||||
../../modules/system/system.nix
|
||||
../../users/users.nix
|
||||
../../modules/system
|
||||
];
|
||||
|
||||
modules = {
|
||||
system = {
|
||||
ssh.enable = true;
|
||||
docker.enable = true;
|
||||
syncthing.enable = false;
|
||||
tailscale.enable = true;
|
||||
nvidia.enable = false;
|
||||
};
|
||||
homelab = {
|
||||
docker.ddns.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
# enable user
|
||||
users.blake.enable = true;
|
||||
|
||||
# use the systemd-boot EFI boot loader.
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
@@ -64,7 +55,7 @@ in
|
||||
# Open ports in the firewall.
|
||||
networking.firewall.enable = true;
|
||||
networking.firewall.extraCommands = ''
|
||||
HOMELAB_IP="10.10.0.30" # destination address
|
||||
HOMELAB_IP="10.10.0.10" # destination address
|
||||
PUBLIC_IF="eth0" # vps public interface
|
||||
TAILSCALE_IF="tailscale0" # tailscale interface
|
||||
|
||||
112
hosts/nixos/yveltal/configuration.nix
Normal file
112
hosts/nixos/yveltal/configuration.nix
Normal file
@@ -0,0 +1,112 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
modulesPath,
|
||||
inputs,
|
||||
stable_pkgs,
|
||||
unstable_pkgs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
# Include the results of the hardware scan.
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
#./hardware-configuration.nix
|
||||
../../nixos
|
||||
../../../users/blake
|
||||
../../../modules/desktop
|
||||
../../../modules/system
|
||||
];
|
||||
|
||||
# home grown nixos modules
|
||||
system = {
|
||||
secure_boot.enable = true;
|
||||
cifs_mounts.enable = true;
|
||||
udiskie.enable = true;
|
||||
ssh.enable = true;
|
||||
sops.enable = true;
|
||||
yubikey.enable = true;
|
||||
yubikey.lock_on_remove = true;
|
||||
tailscale.enable = true;
|
||||
syncthing.enable = true;
|
||||
flatpak.enable = true;
|
||||
graphics = {
|
||||
enable = true;
|
||||
vendor = "intel";
|
||||
};
|
||||
};
|
||||
desktop = {
|
||||
pipewire.enable = true;
|
||||
hypr.enable = true;
|
||||
greetd.enable = true;
|
||||
};
|
||||
gaming = {
|
||||
steam.enable = true;
|
||||
lutris.enable = true;
|
||||
proton_ge.enable = true;
|
||||
gamemode.enable = true;
|
||||
mangohud.enable = true;
|
||||
};
|
||||
|
||||
# import home grown host specific home-manager modules
|
||||
home-manager.users.blake.imports = [
|
||||
../../../users/blake/hosts/yveltal.nix
|
||||
];
|
||||
|
||||
# fix power buttons
|
||||
# move this to a laptops file at some point
|
||||
services.logind.settings.Login = {
|
||||
HandlePowerKey = "suspend-then-hibernate";
|
||||
HandleLidSwitch = "suspend-then-hibernate";
|
||||
};
|
||||
# sets the delay before hibernation for ^
|
||||
systemd.sleep.extraConfig = ''
|
||||
HibernateDelaySec=1800
|
||||
'';
|
||||
|
||||
# boot (systemd is growing on me)
|
||||
boot = {
|
||||
kernelModules = ["kvm-intel"];
|
||||
extraModulePackages = [];
|
||||
loader = {
|
||||
systemd-boot.enable = true; # systemd your pretty cool ya know
|
||||
efi.canTouchEfiVariables = true;
|
||||
};
|
||||
initrd = {
|
||||
systemd.enable = true; # better logging
|
||||
availableKernelModules = ["xhci_pci" "thunderbolt" "vmd" "nvme" "usb_storage" "sd_mod"];
|
||||
kernelModules = [];
|
||||
};
|
||||
};
|
||||
|
||||
# setup hostname and networking stack
|
||||
networking = {
|
||||
hostName = "yveltal"; # hostname
|
||||
useDHCP = lib.mkDefault true;
|
||||
interfaces = {
|
||||
wlp0s20f3.useDHCP = lib.mkDefault true;
|
||||
};
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [22];
|
||||
allowedUDPPorts = [51820]; # wireguard
|
||||
};
|
||||
networkmanager = {
|
||||
enable = true; # the goat
|
||||
dns = "systemd-resolved"; # the backup dancer!
|
||||
};
|
||||
};
|
||||
services.resolved = {
|
||||
enable = true;
|
||||
fallbackDns = ["1.1.1.1" "9.9.9.9"];
|
||||
dnsovertls = "opportunistic";
|
||||
};
|
||||
|
||||
hardware.bluetooth.enable = true;
|
||||
|
||||
system.stateVersion = "25.05"; # stays here : )
|
||||
|
||||
# hardware shit
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
||||
70
hosts/nixos/yveltal/disko.nix
Normal file
70
hosts/nixos/yveltal/disko.nix
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
disko.devices = {
|
||||
disk = {
|
||||
main = {
|
||||
type = "disk";
|
||||
device = "/dev/disk/by-id/nvme-PC_SN530_NVMe_WDC_512GB_210513807733"; # disk id here
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
size = "1G";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [ "umask=0077" ];
|
||||
};
|
||||
};
|
||||
luks = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "luks";
|
||||
name = "crypted";
|
||||
# disable settings.keyFile if you want to use interactive password entry
|
||||
#passwordFile = "/tmp/secret.key"; # Interactive
|
||||
settings = {
|
||||
allowDiscards = true;
|
||||
#keyFile = "/tmp/secret.key";
|
||||
};
|
||||
#additionalKeyFiles = [ "/tmp/additionalSecret.key" ];
|
||||
content = {
|
||||
type = "btrfs";
|
||||
extraArgs = [ "-f" ];
|
||||
subvolumes = {
|
||||
"@root" = {
|
||||
mountpoint = "/";
|
||||
mountOptions = [
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"@home" = {
|
||||
mountpoint = "/home";
|
||||
mountOptions = [
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"@nix" = {
|
||||
mountpoint = "/nix";
|
||||
mountOptions = [
|
||||
"compress=zstd"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
"@swap" = {
|
||||
mountpoint = "/.swapvol";
|
||||
swap.swapfile.size = "32G";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
13
modules/desktop/default.nix
Normal file
13
modules/desktop/default.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./pipewire
|
||||
./hypr
|
||||
./greetd
|
||||
./gaming
|
||||
];
|
||||
}
|
||||
16
modules/desktop/gaming/default.nix
Normal file
16
modules/desktop/gaming/default.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
inputs,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
inputs.slippi.nixosModules.default # gcc drivers
|
||||
./steam
|
||||
./lutris
|
||||
./proton_ge
|
||||
./gamemode
|
||||
./mangohud
|
||||
];
|
||||
}
|
||||
20
modules/desktop/gaming/gamemode/default.nix
Normal file
20
modules/desktop/gaming/gamemode/default.nix
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.gaming.gamemode;
|
||||
in {
|
||||
options.gaming.gamemode = {
|
||||
enable = lib.mkEnableOption "enable lutris";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# enable gamemode for game optimizations
|
||||
# requires setting launch option `gamemoderun %command%`
|
||||
programs.gamemode.enable = true;
|
||||
|
||||
};
|
||||
}
|
||||
19
modules/desktop/gaming/lutris/default.nix
Normal file
19
modules/desktop/gaming/lutris/default.nix
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.gaming.lutris;
|
||||
in {
|
||||
options.gaming.lutris = {
|
||||
enable = lib.mkEnableOption "enable lutris";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = with pkgs; [
|
||||
lutris
|
||||
wine
|
||||
];
|
||||
};
|
||||
}
|
||||
20
modules/desktop/gaming/mangohud/default.nix
Normal file
20
modules/desktop/gaming/mangohud/default.nix
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.gaming.mangohud;
|
||||
in {
|
||||
options.gaming.mangohud = {
|
||||
enable = lib.mkEnableOption "enable lutris";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# preformance overlay
|
||||
# requires setting launch option `mangohud %command%`
|
||||
environment.systemPackages = with pkgs; [
|
||||
mangohud
|
||||
];
|
||||
};
|
||||
}
|
||||
24
modules/desktop/gaming/proton_ge/default.nix
Normal file
24
modules/desktop/gaming/proton_ge/default.nix
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.gaming.proton_ge;
|
||||
in {
|
||||
options.gaming.proton_ge = {
|
||||
enable = lib.mkEnableOption "enable proton ge";
|
||||
};
|
||||
|
||||
# this is an imperitive install after rebuild run `protonup`
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = with pkgs; [
|
||||
protonup-ng
|
||||
];
|
||||
|
||||
# tells `protonup` what path to use
|
||||
environment.sessionVariables = {
|
||||
STEAM_EXTRA_COMPACT_TOOLS_PATHS = "/home/blake/.steam/root/compatibilitytools.d";
|
||||
};
|
||||
};
|
||||
}
|
||||
22
modules/desktop/gaming/steam/default.nix
Normal file
22
modules/desktop/gaming/steam/default.nix
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.gaming.steam;
|
||||
in {
|
||||
options.gaming.steam = {
|
||||
enable = lib.mkEnableOption "enable steam";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
programs.steam = {
|
||||
enable = true;
|
||||
gamescopeSession.enable = true; # requires setting launch option `gamescope <options> -- %command%`
|
||||
remotePlay.openFirewall = true; # open ports for remote play
|
||||
#dedicatedServer.openFirewall = true; # open ports for source dedicated server
|
||||
protontricks.enable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
34
modules/desktop/greetd/default.nix
Normal file
34
modules/desktop/greetd/default.nix
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.desktop.greetd;
|
||||
in {
|
||||
options.desktop.greetd = {
|
||||
enable = lib.mkEnableOption "enable greetd with tuigreet";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.greetd = {
|
||||
enable = true;
|
||||
# tuigreet command to run
|
||||
settings = {
|
||||
default_session = {
|
||||
user = "greeter";
|
||||
command = "${pkgs.tuigreet}/bin/tuigreet -c Hyprland -t --greeting \"howdy o/\" --user-menu --remember --remember-user-session --power-shutdown \"systemctl poweroff\" --power-reboot \"systemctl reboot\"";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# allow yubikey signin with u2f
|
||||
security.pam.services.greetd.u2fAuth = true;
|
||||
|
||||
# ensure the user exists
|
||||
users.users.greeter = {
|
||||
isSystemUser = true;
|
||||
description = "user for greetd";
|
||||
};
|
||||
};
|
||||
}
|
||||
22
modules/desktop/hypr/default.nix
Normal file
22
modules/desktop/hypr/default.nix
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.desktop.hypr;
|
||||
in {
|
||||
options.desktop.hypr = {
|
||||
enable = lib.mkEnableOption "enable hypr on nixos side";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# enable hyprland
|
||||
programs.hyprland.enable = true;
|
||||
|
||||
# give hyprlock perms to unlock
|
||||
security.pam.services.hyprlock = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
136
modules/desktop/pipewire/default.nix
Normal file
136
modules/desktop/pipewire/default.nix
Normal file
@@ -0,0 +1,136 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.desktop.pipewire;
|
||||
in {
|
||||
options.desktop.pipewire = {
|
||||
enable = lib.mkEnableOption "enable pipewire for sound!";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
security.rtkit.enable = true;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
qpwgraph # patching software
|
||||
pavucontrol # volume mixer
|
||||
pulsemixer
|
||||
];
|
||||
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa = {
|
||||
enable = true;
|
||||
support32Bit = true;
|
||||
};
|
||||
pulse.enable = true;
|
||||
jack.enable = true;
|
||||
|
||||
wireplumber = {
|
||||
enable = true;
|
||||
extraConfig = {
|
||||
"90-yveltal-renames" = {
|
||||
"monitor.alsa.rules" = [
|
||||
# audio sinks
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
"node.name" = "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__Speaker__sink";
|
||||
}
|
||||
];
|
||||
actions = {
|
||||
"update-props" = {
|
||||
"node.description" = "Speakers / 3.5mm";
|
||||
"node.nick" = "Speakers / 3.5mm";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
"node.name" = "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__HDMI1__sink";
|
||||
}
|
||||
];
|
||||
actions = {
|
||||
"update-props" = {
|
||||
"node.description" = "HDMI / DP 1";
|
||||
"node.nick" = "HDMI / DP 1";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
"node.name" = "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__HDMI2__sink";
|
||||
}
|
||||
];
|
||||
actions = {
|
||||
"update-props" = {
|
||||
"node.description" = "HDMI / DP 2";
|
||||
"node.nick" = "HDMI / DP 2";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
"node.name" = "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__HDMI3__sink";
|
||||
}
|
||||
];
|
||||
actions = {
|
||||
"update-props" = {
|
||||
"node.description" = "HDMI / DP 3";
|
||||
"node.nick" = "HDMI / DP 3";
|
||||
};
|
||||
};
|
||||
}
|
||||
# audio sources
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
"node.name" = "alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__Headset__source";
|
||||
}
|
||||
];
|
||||
actions = {
|
||||
"update-props" = {
|
||||
"node.description" = "3.5mm Mic";
|
||||
"node.nick" = "3.5mm Mic";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
"node.name" = "alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__Mic1__source";
|
||||
}
|
||||
];
|
||||
actions = {
|
||||
"update-props" = {
|
||||
"node.description" = "Laptop Mic";
|
||||
"node.nick" = "Laptop Mic";
|
||||
};
|
||||
};
|
||||
}
|
||||
# audio controllers
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
"device.name" = "alsa_card.pci-0000_00_1f.3-platform-skl_hda_dsp_generic";
|
||||
}
|
||||
];
|
||||
actions = {
|
||||
"update-props" = {
|
||||
"node.description" = "Laptop Controller";
|
||||
"node.nick" = "Laptop Controller";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
156
modules/gameservers/minecraft_modded/default.nix
Normal file
156
modules/gameservers/minecraft_modded/default.nix
Normal file
@@ -0,0 +1,156 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
service = "minecraft_modded";
|
||||
cfg = config.gameservers.${service};
|
||||
sec = config.sops.secrets;
|
||||
servers = {
|
||||
cobblemon = {
|
||||
data_dir = "/var/lib/gameservers/minecraft_modded/cobblemon";
|
||||
start_file = "start.sh";
|
||||
};
|
||||
};
|
||||
in {
|
||||
options.gameservers.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "mc.recoil.pro";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/gameservers/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 25565;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = "velocity";
|
||||
};
|
||||
backup_repo = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/holocron/archives/gameservers/minecraft/modded";
|
||||
description = "path to take hourly backups to with borg!";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# declare ${service} user
|
||||
users.users.minecraft = lib.mkDefault {
|
||||
description = "minecraft server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
shell = pkgs.bash;
|
||||
group = "minecraft";
|
||||
extraGroups = [];
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules =
|
||||
lib.attrsets.mapAttrsToList (
|
||||
name: cfg: "d ${cfg.data_dir} 0770 minecraft minecraft -"
|
||||
)
|
||||
servers;
|
||||
|
||||
# Create a systemd service per server running in tmux
|
||||
systemd.services =
|
||||
lib.attrsets.mapAttrs (name: srv: {
|
||||
description = "minecraft_recpro: ${name}";
|
||||
after = ["network.target"];
|
||||
wants = ["network.target"];
|
||||
serviceConfig = {
|
||||
User = "minecraft";
|
||||
Group = "minecraft";
|
||||
WorkingDirectory = srv.data_dir;
|
||||
UMask = "0007";
|
||||
ExecStart = "${pkgs.openjdk21}/bin/java -Xms4G -Xmx12G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true @libraries/net/neoforged/neoforge/21.1.211/unix_args.txt";
|
||||
#ExecStart = "${srv.data_dir}/${srv.start_file}";
|
||||
Restart = "on-failure";
|
||||
KillMode = "process";
|
||||
};
|
||||
wantedBy = ["multi-user.target"];
|
||||
})
|
||||
servers;
|
||||
|
||||
environment.systemPackages = with pkgs; [openjdk21 mcrcon];
|
||||
|
||||
# services.mysql = {
|
||||
# enable = true;
|
||||
# package = pkgs.mariadb;
|
||||
# ensureDatabases = ["minecraft_recpro_db"];
|
||||
# ensureUsers = [
|
||||
# {
|
||||
# name = "minecraft";
|
||||
# ensurePermissions = {"minecraft_recpro_db.*" = "ALL PRIVILEGES";};
|
||||
# }
|
||||
# ];
|
||||
# initialScript = pkgs.writeText "minecraft_recpro-init.sql" ''
|
||||
# CREATE USER IF NOT EXISTS 'minecraft_recpro'@'localhost' IDENTIFIED BY 'IKNOWTHISISBADIJUSTNEEDTHISTOWORKRNPLS';
|
||||
# GRANT ALL PRIVILEGES ON minecraft_recpro_db.* TO 'minecraft_recpro'@'localhost';
|
||||
# FLUSH PRIVILEGES;
|
||||
# '';
|
||||
# };
|
||||
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [25778];
|
||||
|
||||
# sops.secrets = {
|
||||
# "velocity_forwarding" = {
|
||||
# owner = "minecraft";
|
||||
# group = "minecraft";
|
||||
# path = "/var/lib/gameservers/minecraft_recpro/velocity/forwarding.secret";
|
||||
# mode = "0400";
|
||||
# };
|
||||
# "minecraft_recpro_db_passwd" = {
|
||||
# owner = "mysql";
|
||||
# group = "mysql";
|
||||
# };
|
||||
# };
|
||||
|
||||
# backups minecraft_recpro with borg!
|
||||
services.borgbackup.jobs.${service} = {
|
||||
archiveBaseName = service;
|
||||
repo = cfg.backup_repo;
|
||||
paths = lib.flatten (
|
||||
lib.attrValues (
|
||||
lib.mapAttrs (_: srv:
|
||||
[srv.data_dir]
|
||||
++ (
|
||||
if builtins.hasAttr "db_dump" srv
|
||||
then [srv.db_dump]
|
||||
else []
|
||||
))
|
||||
servers
|
||||
)
|
||||
);
|
||||
compression = "auto,zstd";
|
||||
#preHook = "systemctl start mysql-backup.service";
|
||||
startAt = "*-*-* *:00:00";
|
||||
group = "archives";
|
||||
encryption.mode = "repokey-blake2";
|
||||
encryption.passCommand = "cat ${config.sops.secrets."borg_passwd".path}";
|
||||
extraArgs = ["--verbose" "--show-rc" "--umask" "0007"];
|
||||
extraCreateArgs = ["--list" "--stats" "--filter" "AME"];
|
||||
prune.keep = {
|
||||
within = "1d"; # Keep all archives from the last day
|
||||
hourly = 24;
|
||||
daily = 7;
|
||||
weekly = 12;
|
||||
monthly = -1; # Keep at least one archive for each month
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
170
modules/gameservers/minecraft_recpro/default.nix
Normal file
170
modules/gameservers/minecraft_recpro/default.nix
Normal file
@@ -0,0 +1,170 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
service = "minecraft_recpro";
|
||||
cfg = config.gameservers.${service};
|
||||
sec = config.sops.secrets;
|
||||
servers = {
|
||||
velocity = {
|
||||
data_dir = "/var/lib/gameservers/minecraft_recpro/velocity";
|
||||
db_dump = "/var/backup/mysql/${service}_db.zst";
|
||||
ram = "2G";
|
||||
};
|
||||
smp = {
|
||||
data_dir = "/var/lib/gameservers/minecraft_recpro/smp";
|
||||
ram = "12G";
|
||||
};
|
||||
superflat = {
|
||||
data_dir = "/var/lib/gameservers/minecraft_recpro/superflat";
|
||||
ram = "4G";
|
||||
};
|
||||
bento = {
|
||||
data_dir = "/var/lib/gameservers/minecraft_recpro/bento";
|
||||
ram = "2G";
|
||||
};
|
||||
};
|
||||
in {
|
||||
options.gameservers.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "mc.recoil.pro";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/gameservers/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 25565;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = "velocity";
|
||||
};
|
||||
backup_repo = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/holocron/archives/gameservers/minecraft/recpro_stack";
|
||||
description = "path to take hourly backups to with borg!";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# declare ${service} group
|
||||
users.groups.minecraft = {gid = lib.mkForce cfg.ids;};
|
||||
|
||||
# declare ${service} user
|
||||
users.users.minecraft = {
|
||||
description = "minecraft server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
shell = pkgs.bash;
|
||||
group = "minecraft";
|
||||
extraGroups = [];
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules =
|
||||
lib.attrsets.mapAttrsToList (
|
||||
name: cfg: "d ${cfg.data_dir} 0770 minecraft minecraft -"
|
||||
)
|
||||
servers;
|
||||
|
||||
# Create a systemd service per server running in tmux
|
||||
systemd.services =
|
||||
lib.attrsets.mapAttrs (name: srv: {
|
||||
description = "minecraft_recpro: ${name}";
|
||||
after = ["network.target"];
|
||||
wants = ["network.target"];
|
||||
serviceConfig = {
|
||||
User = "minecraft";
|
||||
Group = "minecraft";
|
||||
WorkingDirectory = srv.data_dir;
|
||||
UMask = "0007";
|
||||
ExecStart = "${pkgs.openjdk21}/bin/java -Xmx${srv.ram} -jar server.jar nogui";
|
||||
Restart = "on-failure";
|
||||
KillMode = "process";
|
||||
};
|
||||
wantedBy = ["multi-user.target"];
|
||||
})
|
||||
servers;
|
||||
|
||||
environment.systemPackages = with pkgs; [openjdk21 mcrcon];
|
||||
|
||||
services.mysql = {
|
||||
enable = true;
|
||||
package = pkgs.mariadb;
|
||||
ensureDatabases = ["minecraft_recpro_db"];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "minecraft";
|
||||
ensurePermissions = {"minecraft_recpro_db.*" = "ALL PRIVILEGES";};
|
||||
}
|
||||
];
|
||||
initialScript = pkgs.writeText "minecraft_recpro-init.sql" ''
|
||||
CREATE USER IF NOT EXISTS 'minecraft_recpro'@'localhost' IDENTIFIED BY 'IKNOWTHISISBADIJUSTNEEDTHISTOWORKRNPLS';
|
||||
GRANT ALL PRIVILEGES ON minecraft_recpro_db.* TO 'minecraft_recpro'@'localhost';
|
||||
FLUSH PRIVILEGES;
|
||||
'';
|
||||
};
|
||||
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [25777 25565 25566 25567];
|
||||
|
||||
sops.secrets = {
|
||||
"velocity_forwarding" = {
|
||||
owner = "minecraft";
|
||||
group = "minecraft";
|
||||
path = "/var/lib/gameservers/minecraft_recpro/velocity/forwarding.secret";
|
||||
mode = "0400";
|
||||
};
|
||||
"minecraft_recpro_db_passwd" = {
|
||||
owner = "mysql";
|
||||
group = "mysql";
|
||||
};
|
||||
};
|
||||
|
||||
# backups minecraft_recpro with borg!
|
||||
services.borgbackup.jobs.${service} = {
|
||||
archiveBaseName = service;
|
||||
repo = cfg.backup_repo;
|
||||
paths = lib.flatten (
|
||||
lib.attrValues (
|
||||
lib.mapAttrs (_: srv:
|
||||
[srv.data_dir]
|
||||
++ (
|
||||
if builtins.hasAttr "db_dump" srv
|
||||
then [srv.db_dump]
|
||||
else []
|
||||
))
|
||||
servers
|
||||
)
|
||||
);
|
||||
compression = "auto,zstd";
|
||||
preHook = "systemctl start mysql-backup.service";
|
||||
startAt = "*-*-* *:00:00";
|
||||
group = "archives";
|
||||
encryption.mode = "repokey-blake2";
|
||||
encryption.passCommand = "cat ${config.sops.secrets."borg_passwd".path}";
|
||||
extraArgs = ["--verbose" "--show-rc" "--umask" "0007"];
|
||||
extraCreateArgs = ["--list" "--stats" "--filter" "AME"];
|
||||
prune.keep = {
|
||||
within = "1d"; # Keep all archives from the last day
|
||||
hourly = 24;
|
||||
daily = 7;
|
||||
weekly = 12;
|
||||
monthly = -1; # Keep at least one archive for each month
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
160
modules/holocron/copyparty/default.nix
Normal file
160
modules/holocron/copyparty/default.nix
Normal file
@@ -0,0 +1,160 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}: let
|
||||
service = "copyparty";
|
||||
cfg = config.holocron.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.homelab;
|
||||
in {
|
||||
imports = [inputs.copyparty.nixosModules.default];
|
||||
|
||||
options.holocron.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 7902;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${service}.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = cfg.port;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
nixpkgs.overlays = [inputs.copyparty.overlays.default];
|
||||
# declare ${service} group
|
||||
users.groups.${service} = {
|
||||
gid = lib.mkForce cfg.ids;
|
||||
};
|
||||
|
||||
# declare ${service} user
|
||||
users.users.${service} = {
|
||||
description = lib.mkForce "${service} server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = service;
|
||||
extraGroups = [ "media" "blake" "archives" ];
|
||||
};
|
||||
|
||||
# enable the ${service} service
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
user = service;
|
||||
group = service;
|
||||
settings = {
|
||||
i = "0.0.0.0";
|
||||
p = [7902];
|
||||
rproxy = 1;
|
||||
};
|
||||
accounts = {
|
||||
blake = {
|
||||
passwordFile = sec."copyparty_passwd".path;
|
||||
};
|
||||
};
|
||||
groups = {
|
||||
media = ["blake"];
|
||||
};
|
||||
volumes = {
|
||||
"/archives" = {
|
||||
path = "/holocron/archives";
|
||||
access = {
|
||||
r = "*";
|
||||
A = "blake";
|
||||
};
|
||||
flags = {
|
||||
chmod_f = 660;
|
||||
chmod_d = 770;
|
||||
#gid = ?;
|
||||
};
|
||||
};
|
||||
"/media" = {
|
||||
path = "/holocron/media";
|
||||
access = {
|
||||
r = "*";
|
||||
w = "@media";
|
||||
A = "blake";
|
||||
};
|
||||
flags = {
|
||||
chmod_f = 660;
|
||||
chmod_d = 770;
|
||||
gid = "700";
|
||||
};
|
||||
};
|
||||
"/users/blake" = {
|
||||
path = "/holocron/users/blake";
|
||||
access = {
|
||||
A = "blake";
|
||||
};
|
||||
flags = {
|
||||
chmod_f = 660;
|
||||
chmod_d = 770;
|
||||
gid = "1000";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [cfg.port];
|
||||
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
serverAliases = ["${service}.${homelab.public_domain}"];
|
||||
extraConfig = ''
|
||||
tls /etc/ssl/blakedheld.xyz.crt /etc/ssl/blakedheld.xyz.key
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port} {
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
# add to glance (local service)
|
||||
homelab.glance.links.system = [
|
||||
{
|
||||
title = service;
|
||||
url = "https://${cfg.url}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}";
|
||||
}
|
||||
];
|
||||
|
||||
sops.secrets = {
|
||||
"${service}_passwd" = {
|
||||
owner = service;
|
||||
group = service;
|
||||
};
|
||||
};
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = {
|
||||
paths = [cfg.data_dir];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
21
modules/holocron/default.nix
Normal file
21
modules/holocron/default.nix
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}: {
|
||||
# services show up in glance in reverse import order lmao
|
||||
imports = [
|
||||
./nfs
|
||||
./smb
|
||||
./zfs
|
||||
./syncthing
|
||||
./copyparty
|
||||
./perms
|
||||
];
|
||||
|
||||
# define the groups used for backups and archives
|
||||
users.groups.archives = {gid = 727;};
|
||||
|
||||
}
|
||||
@@ -1,15 +1,18 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
# define nfs exports
|
||||
let
|
||||
cfg = config.modules.homelab.nfs;
|
||||
cfg = config.holocron.nfs;
|
||||
nfs_exports = ''
|
||||
/holocron/vault *(rw,sync,no_subtree_check,no_root_squash)
|
||||
/holocron/media *(ro,sync,no_subtree_check)
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.modules.homelab.nfs = {
|
||||
#/holocron/users *(rw,sync,no_subtree_check,no_root_squash)
|
||||
in {
|
||||
options.holocron.nfs = {
|
||||
enable = lib.mkEnableOption "enables nfs";
|
||||
};
|
||||
|
||||
65
modules/holocron/perms/default.nix
Normal file
65
modules/holocron/perms/default.nix
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
service = "ensure_perms";
|
||||
cfg = config.holocron.${service};
|
||||
|
||||
# define variables for paths
|
||||
archives_path = "/holocron/archives";
|
||||
media_path = "/holocron/media";
|
||||
users_path = "/holocron/users";
|
||||
in {
|
||||
options.holocron.ensure_perms = {
|
||||
enable = lib.mkEnableOption "enables perms ensurence script";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# service to run periodically to reset the perms on all zpools
|
||||
# everything works fine without this, just for peace of mind
|
||||
# and to clean up the ownership from the arr stack in /holocron/media
|
||||
systemd.services.${service} = {
|
||||
description = "ensure file permissions for archives, media and user folders";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = pkgs.writeShellScript "ensure_perms" ''
|
||||
|
||||
# Fix ownership for archives directory
|
||||
echo "starting ${archives_path}"
|
||||
chown -Rc root:archives ${archives_path}
|
||||
find "${archives_path}" -type d -exec chmod 2770 "$@" {} +
|
||||
find "${archives_path}" -type f -exec chmod 660 "$@" {} +
|
||||
|
||||
# Fix ownership for media directory
|
||||
echo "starting ${media_path}"
|
||||
chown -Rc root:media ${media_path}
|
||||
find "${media_path}" -type d -exec chmod 2770 "$@" {} +
|
||||
find "${media_path}" -type f -exec chmod 660 "$@" {} +
|
||||
|
||||
# Fix user directories
|
||||
for user_dir in ${users_path}/*; do
|
||||
if [ -d "$user_dir" ]; then
|
||||
user=$(basename "$user_dir")
|
||||
echo "starting $user_dir"
|
||||
chown -Rc $user:$user $user_dir
|
||||
find $user_dir -type d -exec chmod 2770 "$@" {} +
|
||||
find $user_dir -type f -exec chmod 660 "$@" {} +
|
||||
fi
|
||||
done
|
||||
echo "fin"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.${service} = {
|
||||
description = "run script to ensure_perms daily";
|
||||
wantedBy = ["timers.target"];
|
||||
timerConfig = {
|
||||
OnCalendar = "03:30";
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
59
modules/holocron/smb/default.nix
Normal file
59
modules/holocron/smb/default.nix
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
# define smb shares
|
||||
let
|
||||
cfg = config.holocron.smb;
|
||||
smb_shares = {
|
||||
archives = {
|
||||
path = "/holocron/archives";
|
||||
browseable = true;
|
||||
writable = true;
|
||||
guestOk = false;
|
||||
"create mask" = "0775";
|
||||
"directory mask" = "0775";
|
||||
};
|
||||
timemachine = {
|
||||
browseable = true;
|
||||
"path" = "/holocron/archives/timemachine";
|
||||
#"valid users" = "blake";
|
||||
"public" = "no";
|
||||
"writeable" = "yes";
|
||||
#"force user" = "blake";
|
||||
"fruit:aapl" = "yes";
|
||||
"fruit:time machine" = "yes";
|
||||
"vfs objects" = "catia fruit streams_xattr";
|
||||
};
|
||||
users = {
|
||||
path = "/holocron/users";
|
||||
browseable = true;
|
||||
writable = true;
|
||||
guestOk = false;
|
||||
"create mask" = "0660";
|
||||
"directory mask" = "0770";
|
||||
};
|
||||
media = {
|
||||
path = "/holocron/media";
|
||||
browseable = true;
|
||||
writable = true;
|
||||
guestOk = false;
|
||||
"create mask" = "0775";
|
||||
"directory mask" = "0775";
|
||||
};
|
||||
};
|
||||
in {
|
||||
options.holocron.smb = {
|
||||
enable = lib.mkEnableOption "enables smb";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# enable smb with all shares
|
||||
services.samba = {
|
||||
enable = true;
|
||||
settings = smb_shares;
|
||||
};
|
||||
};
|
||||
}
|
||||
87
modules/holocron/syncthing/default.nix
Normal file
87
modules/holocron/syncthing/default.nix
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
service = "syncthing";
|
||||
cfg = config.holocron.${service};
|
||||
sec = config.sops.secrets;
|
||||
url = "syncthing.snowbelle.lan";
|
||||
homelab = config.homelab;
|
||||
in {
|
||||
options.holocron.${service} = {
|
||||
enable = lib.mkEnableOption "enables syncthing";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.syncthing = {
|
||||
enable = true;
|
||||
user = "blake";
|
||||
group = "blake";
|
||||
dataDir = "/var/lib/syncthing";
|
||||
guiAddress = "0.0.0.0:2222";
|
||||
openDefaultPorts = true;
|
||||
#extraFlags = ["--no-default-folder"];
|
||||
key = sec."${service}/snowbelle/key".path;
|
||||
cert = sec."${service}/snowbelle/cert".path;
|
||||
settings = {
|
||||
devices = {
|
||||
"lugia" = {id = "BKKSFPH-YEOVVAB-DTT7KK3-UDKAEJ2-PC6ECG7-Y76ZIVP-JRYMMXS-RTZYVQ3";};
|
||||
"zygarde" = {id = "UYLTF52-VVKUR7F-JN33HQZ-RFNWGL3-JER52LA-GZD2LPJ-QIFEE7K-MNMZRQ5";};
|
||||
"yveltal" = {id = "ZVSQ4WJ-7OICYOZ-3ECES4X-KH37IPB-TKHKUJG-BSEGXVM-AHYY5C3-VKG44AX";};
|
||||
"CEN-IT-07" = {id = "DPYKA4Z-3PX7JB2-FBEOXXX-SC7TLT2-QC5P2IR-SXOPJGX-QO3DMII-5B7UCA4";};
|
||||
"CEN-IT-00007" = {id = "XBPXGYU-DUJSLDH-6BDNF4D-CO2COC3-N3FM6W5-IHZOJBM-Z2N77RI-IVAV5AH";};
|
||||
};
|
||||
folders = {
|
||||
"holocron" = {
|
||||
path = "/holocron/users/blake/holocron";
|
||||
devices = ["lugia" "zygarde" "CEN-IT-07" "CEN-IT-00007" "yveltal"];
|
||||
id = "5voxg-c3he2";
|
||||
versioning = {
|
||||
type = "staggered";
|
||||
fsPath = "/holocron/users/blake/holocron/.stversions";
|
||||
params = {
|
||||
cleanInterval = "3600";
|
||||
maxAge = "0";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
options = {
|
||||
urAccepted = -1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sops.secrets = {
|
||||
"${service}/snowbelle/key" = {
|
||||
owner = "blake";
|
||||
group = "blake";
|
||||
};
|
||||
"${service}/snowbelle/cert" = {
|
||||
owner = "blake";
|
||||
group = "blake";
|
||||
};
|
||||
};
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ config.services.syncthing.dataDir ]; };
|
||||
};
|
||||
|
||||
services.caddy.virtualHosts."${url}" = {
|
||||
extraConfig = ''
|
||||
tls /etc/ssl/blakedheld.xyz.crt /etc/ssl/blakedheld.xyz.key
|
||||
reverse_proxy 127.0.0.1:2222
|
||||
'';
|
||||
};
|
||||
|
||||
# add to glance (local service)
|
||||
homelab.glance.links.system = [{
|
||||
title = service;
|
||||
url = "https://${url}";
|
||||
error-url = "http://${homelab.host_ip}:2222";
|
||||
check-url = "http://${homelab.host_ip}:2222";
|
||||
icon = "di:${service}"; }];
|
||||
};
|
||||
}
|
||||
78
modules/holocron/zfs/default.nix
Normal file
78
modules/holocron/zfs/default.nix
Normal file
@@ -0,0 +1,78 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
cfg = config.holocron.zfs;
|
||||
in {
|
||||
options.holocron.zfs = {
|
||||
enable = lib.mkEnableOption "enables zfs";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# set network host id
|
||||
networking.hostId = "3e6e7055";
|
||||
|
||||
# enable zfs support
|
||||
boot.kernelModules = ["zfs"];
|
||||
boot.supportedFilesystems = ["zfs"];
|
||||
|
||||
# arc cache size
|
||||
boot.kernelParams = [ "zfs.zfs_arc_max=12884901888" ];
|
||||
|
||||
# pools to import
|
||||
#boot.zfs.extraPools = [ "holocron" "holocron/archives" "/holocron/media" "/holocron/users" ];
|
||||
#boot.zfs.extraPools = [ "holocron" ];
|
||||
|
||||
# enable smart monitoring
|
||||
services.smartd = {
|
||||
enable = true;
|
||||
autodetect = true;
|
||||
defaults.monitored = "-a -o on -s (S/../.././05|L/../01/./05)";
|
||||
notifications.mail = {
|
||||
enable = true;
|
||||
sender = "zfs@snowbelle.lan";
|
||||
};
|
||||
};
|
||||
|
||||
# enable zfs
|
||||
services.zfs = {
|
||||
autoScrub.enable = true;
|
||||
autoScrub.interval = "weekly";
|
||||
# email notifs
|
||||
zed = {
|
||||
enableMail = true;
|
||||
settings = {
|
||||
ZED_EMAIL_ADDR = ["root"];
|
||||
# send notification if scrub succeeds
|
||||
ZED_NOTIFY_VERBOSE = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# install userspace tools for acl's
|
||||
environment.systemPackages = with pkgs; [smartmontools];
|
||||
|
||||
fileSystems."/holocron" = {
|
||||
device = "holocron";
|
||||
fsType = "zfs";
|
||||
options = ["nofail"];
|
||||
};
|
||||
fileSystems."/holocron/archives" = {
|
||||
device = "holocron/archives";
|
||||
fsType = "zfs";
|
||||
options = ["nofail"];
|
||||
};
|
||||
fileSystems."/holocron/users" = {
|
||||
device = "holocron/users";
|
||||
fsType = "zfs";
|
||||
options = ["nofail"];
|
||||
};
|
||||
fileSystems."/holocron/media" = {
|
||||
device = "holocron/media";
|
||||
fsType = "zfs";
|
||||
options = ["nofail"];
|
||||
};
|
||||
};
|
||||
}
|
||||
123
modules/homelab/.default.nix.template.nix
Normal file
123
modules/homelab/.default.nix.template.nix
Normal file
@@ -0,0 +1,123 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
service = "";
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.homelab;
|
||||
in {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = <port>;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${service}.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = cfg.port;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# declare ${service} group
|
||||
users.groups.${service} = {
|
||||
gid = lib.mkForce cfg.ids;
|
||||
};
|
||||
|
||||
# declare ${service} user
|
||||
users.users.${service} = {
|
||||
description = "${service} server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = service;
|
||||
extraGroups = ["media"];
|
||||
};
|
||||
|
||||
# enable the ${service} service
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
user = service;
|
||||
group = service;
|
||||
dataDir = cfg.data_dir;
|
||||
settings = {
|
||||
server.port = cfg.port;
|
||||
};
|
||||
};
|
||||
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
# User = service;
|
||||
# Group = service;
|
||||
};
|
||||
|
||||
# # open firewall
|
||||
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
serverAliases = ["${service}.${homelab.public_domain}"];
|
||||
extraConfig = ''
|
||||
tls /etc/ssl/blakedheld.xyz.crt /etc/ssl/blakedheld.xyz.key
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# # add to glance (public service)
|
||||
# homelab.glance.links.<category> = [{
|
||||
# title = service;
|
||||
# url = "https://${service}.${homelab.public_domain}";
|
||||
# error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
# check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
# icon = "di:${service}"; }];
|
||||
#---------------------------------------------------------------------------
|
||||
# # add to glance (local service)
|
||||
# homelab.glance.links.<category> = [{
|
||||
# title = service;
|
||||
# url = "https://${cfg.url}";
|
||||
# error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
# check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
# icon = "di:${service}"; }];
|
||||
#---------------------------------------------------------------------------
|
||||
#
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = ;
|
||||
# group = ;
|
||||
# };
|
||||
# };
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = {
|
||||
paths = [cfg.data_dir];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
let
|
||||
service = "bazarr";
|
||||
cfg = config.modules.services.${service};
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
@@ -36,6 +36,10 @@ in
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -50,7 +54,7 @@ in
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = "${service}";
|
||||
group = service;
|
||||
extraGroups = [ "media" ];
|
||||
};
|
||||
|
||||
@@ -58,8 +62,8 @@ in
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
user = "${service}";
|
||||
group = "${service}";
|
||||
user = service;
|
||||
group = service;
|
||||
listenPort = cfg.port;
|
||||
};
|
||||
|
||||
@@ -71,17 +75,25 @@ in
|
||||
# # open firewall
|
||||
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
extraConfig = ''
|
||||
tls internal
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# add to glance
|
||||
homelab.glance.links.mediastack = [{
|
||||
title = service;
|
||||
url = "https://${cfg.url}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
let
|
||||
service = "flaresolverr";
|
||||
cfg = config.modules.services.${service};
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
@@ -36,6 +36,10 @@ in
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -48,7 +52,7 @@ in
|
||||
description = "${service} server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
group = "${service}";
|
||||
group = service;
|
||||
};
|
||||
|
||||
# enable the ${service} service
|
||||
@@ -60,21 +64,19 @@ in
|
||||
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
User = "${service}";
|
||||
Group = "${service}";
|
||||
User = service;
|
||||
Group = service;
|
||||
};
|
||||
|
||||
# # open firewall
|
||||
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
extraConfig = ''
|
||||
tls internal
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
let
|
||||
service = "prowlarr";
|
||||
cfg = config.modules.services.${service};
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
@@ -36,6 +36,10 @@ in
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -50,7 +54,7 @@ in
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = "${service}";
|
||||
group = service;
|
||||
extraGroups = [ "media" ];
|
||||
};
|
||||
|
||||
@@ -66,24 +70,32 @@ in
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
User = "${service}";
|
||||
Group = "${service}";
|
||||
User = service;
|
||||
Group = service;
|
||||
};
|
||||
|
||||
# # open firewall
|
||||
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
extraConfig = ''
|
||||
tls internal
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# add to glance
|
||||
homelab.glance.links.mediastack = [{
|
||||
title = service;
|
||||
url = "https://${cfg.url}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
let
|
||||
service = "radarr";
|
||||
cfg = config.modules.services.${service};
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
@@ -36,10 +36,17 @@ in
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# required
|
||||
environment.systemPackages = with pkgs; [ffmpeg_6-headless];
|
||||
|
||||
# declare ${service} group
|
||||
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
|
||||
|
||||
@@ -50,7 +57,7 @@ in
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = "${service}";
|
||||
group = service;
|
||||
extraGroups = [ "media" ];
|
||||
};
|
||||
|
||||
@@ -58,8 +65,8 @@ in
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
user = "${service}";
|
||||
group = "${service}";
|
||||
user = service;
|
||||
group = service;
|
||||
dataDir = cfg.data_dir;
|
||||
settings = {
|
||||
server.port = cfg.port;
|
||||
@@ -69,24 +76,32 @@ in
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
# User = "${service}";
|
||||
# Group = "${service}";
|
||||
# User = service;
|
||||
# Group = service;
|
||||
};
|
||||
|
||||
# # open firewall
|
||||
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
extraConfig = ''
|
||||
tls internal
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# add to glance
|
||||
homelab.glance.links.mediastack = [{
|
||||
title = service;
|
||||
url = "https://${cfg.url}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
let
|
||||
service = "sonarr";
|
||||
cfg = config.modules.services.${service};
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
@@ -36,10 +36,17 @@ in
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# required
|
||||
environment.systemPackages = with pkgs; [ffmpeg_6-headless];
|
||||
|
||||
# declare ${service} group
|
||||
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
|
||||
|
||||
@@ -50,7 +57,7 @@ in
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = "${service}";
|
||||
group = service;
|
||||
extraGroups = [ "media" ];
|
||||
};
|
||||
|
||||
@@ -58,8 +65,8 @@ in
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
user = "${service}";
|
||||
group = "${service}";
|
||||
user = service;
|
||||
group = service;
|
||||
dataDir = cfg.data_dir;
|
||||
settings = {
|
||||
server.port = cfg.port;
|
||||
@@ -74,17 +81,26 @@ in
|
||||
# # open firewall
|
||||
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
# tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
|
||||
extraConfig = ''
|
||||
tls internal
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# add to glance
|
||||
homelab.glance.links.mediastack = [{
|
||||
title = service;
|
||||
url = "https://${cfg.url}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
105
modules/homelab/audiobookshelf/default.nix
Normal file
105
modules/homelab/audiobookshelf/default.nix
Normal file
@@ -0,0 +1,105 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
service = "audiobookshelf";
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 7101;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "abs.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = cfg.port;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# declare ${service} group
|
||||
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
|
||||
|
||||
# declare ${service} user
|
||||
users.users.${service} = {
|
||||
description = "${service} server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
# home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = service;
|
||||
extraGroups = [ "media" ];
|
||||
};
|
||||
|
||||
# enable the ${service} service
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
user = service;
|
||||
group = service;
|
||||
# dataDir = cfg.data_dir;
|
||||
host = "0.0.0.0";
|
||||
port = cfg.port;
|
||||
};
|
||||
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
# User = service;
|
||||
# Group = service;
|
||||
};
|
||||
|
||||
# # open firewall
|
||||
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
serverAliases = [ "abs.${homelab.public_domain}" ];
|
||||
extraConfig = ''
|
||||
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port} {
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
# add to glance public service
|
||||
homelab.glance.links.mediastack = [{
|
||||
title = service;
|
||||
url = "https://abs.${homelab.public_domain}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
89
modules/homelab/backups/default.nix
Normal file
89
modules/homelab/backups/default.nix
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
/*
|
||||
to restore mysql/marinadb database:
|
||||
mysql -u root -p -e "DROP DATABASE IF EXISTS <database_name>;" # delete old db if still lingering
|
||||
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS <database_name>;" # create empty db w/ correct name
|
||||
zstd -dc <path_to_backup> | mysql -u root -p <database_name>
|
||||
|
||||
to restore a postgres database:
|
||||
sudo -u postgres psql -c "DROP DATABASE IF EXISTS <database_name>;" # delete old db if lingering (prolly wont work)
|
||||
sudo -u postgres psql -c "CREATE DATABASE <database_name>;" # create empty db w/ correct name
|
||||
zstd -dc <path_to_backup> | sudo -u postgres psql -d immich # restore from the dump
|
||||
*/
|
||||
let
|
||||
cfg = config.homelab.backups;
|
||||
sec = config.sops.secrets;
|
||||
in {
|
||||
options.homelab.backups = {
|
||||
enable = lib.mkEnableOption "enables borg backups for state files and db backup services";
|
||||
baks = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.attrsOf (lib.types.listOf lib.types.path));
|
||||
default = {};
|
||||
description = "backup jobs, nested attribute sets should be <bak_name> = paths [<list_of_paths>]";
|
||||
};
|
||||
backup_repo = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/holocron/archives/homelab";
|
||||
description = "path to take daily backups to with borg!";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# backups homelab with borg
|
||||
services.borgbackup.jobs.homelab = lib.mkIf (cfg.baks != {}) {
|
||||
archiveBaseName = "homelab";
|
||||
repo = cfg.backup_repo;
|
||||
paths = lib.flatten (lib.attrsets.mapAttrsToList (_: arg: arg.paths) cfg.baks);
|
||||
compression = "auto,zstd";
|
||||
startAt = "03:30";
|
||||
group = "archives";
|
||||
encryption.mode = "repokey-blake2";
|
||||
encryption.passCommand = "cat ${sec."borg_passwd".path}";
|
||||
preHook = ''
|
||||
systemctl start mysql-backup.service
|
||||
systemctl start $(systemctl list-unit-files 'postgresqlBackup-*.service' --no-legend --no-pager | cut -d' ' -f1)
|
||||
'';
|
||||
extraArgs = ["--verbose" "--show-rc" "--umask" "0007"];
|
||||
extraCreateArgs = ["--list" "--stats" "--filter" "AME"];
|
||||
prune.keep = {
|
||||
within = "1d"; # Keep all archives from the last day
|
||||
daily = 7;
|
||||
weekly = 12;
|
||||
monthly = -1; # Keep at least one archive for each month
|
||||
};
|
||||
};
|
||||
|
||||
# mysql backups currently minecraft_recpro is the only thing using this
|
||||
services.mysqlBackup = lib.mkIf (config.services.mysql.ensureDatabases != []) {
|
||||
enable = true;
|
||||
location = "/var/backup/mysql";
|
||||
user = "root";
|
||||
calendar = "daily"; # goes fast, included in back up with server dirs at **:00
|
||||
compressionAlg = "zstd";
|
||||
databases = config.services.mysql.ensureDatabases; # set to all databases defined in esure databases
|
||||
};
|
||||
# postgresql backups currently immich is the only user
|
||||
services.postgresqlBackup = lib.mkIf (config.services.postgresql.ensureDatabases != []) {
|
||||
enable = true;
|
||||
location = "/var/backup/postgresql";
|
||||
compression = "zstd"; # optional: "xz", "zstd", "none"
|
||||
startAt = "daily"; # the dump is included in a backup taken at 4:00
|
||||
databases = config.services.postgresql.ensureDatabases; # set to all databases defined in esure databases
|
||||
};
|
||||
|
||||
# helpful and for scripts
|
||||
environment.systemPackages = with pkgs; [borgbackup tree];
|
||||
|
||||
sops.secrets = {
|
||||
"borg_passwd" = {
|
||||
owner = "root";
|
||||
group = "root";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
102
modules/homelab/caddy/default.nix
Normal file
102
modules/homelab/caddy/default.nix
Normal file
@@ -0,0 +1,102 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
service = "caddy";
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# declare ${service} group
|
||||
users.groups.${service} = {};
|
||||
|
||||
# declare ${service} user
|
||||
users.users.${service} = {
|
||||
description = "${service} server user";
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = service;
|
||||
extraGroups = [];
|
||||
};
|
||||
|
||||
# enable the ${service} service
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
user = service;
|
||||
group = service;
|
||||
dataDir = cfg.data_dir;
|
||||
email = "me@blakedheld.xyz";
|
||||
globalConfig = ''
|
||||
auto_https ignore_loaded_certs
|
||||
'';
|
||||
|
||||
virtualHosts."key.${homelab.public_domain}" = {
|
||||
extraConfig = ''
|
||||
root * /var/www/keys
|
||||
file_server
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# enable acme for auto ssl certs with lets encrypt
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults.email = "me@blakedheld.xyz";
|
||||
};
|
||||
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
};
|
||||
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
|
||||
sops.secrets = {
|
||||
"ssl_blakedheld_crt" = {
|
||||
owner = "caddy";
|
||||
group = "caddy";
|
||||
path = "/etc/ssl/blakedheld.xyz.crt";
|
||||
};
|
||||
"ssl_blakedheld_key" = {
|
||||
owner = "caddy";
|
||||
group = "caddy";
|
||||
path = "/etc/ssl/blakedheld.xyz.key";
|
||||
};
|
||||
"klefki_pub.asc" = {
|
||||
owner = "caddy";
|
||||
group = "caddy";
|
||||
path = "/var/www/keys/klefki_pub.asc";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
|
||||
let
|
||||
cfg = config.modules.homelab;
|
||||
cfg = config.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.homelab = {
|
||||
options.homelab = {
|
||||
enable = lib.mkEnableOption "enable homelab services and configuration";
|
||||
media_user = lib.mkOption {
|
||||
default = "media";
|
||||
@@ -27,13 +27,43 @@ in
|
||||
type = lib.types.str;
|
||||
description = "base domain used for reverse proxy";
|
||||
};
|
||||
public_domain = lib.mkOption {
|
||||
default = "blakedheld.xyz";
|
||||
type = lib.types.str;
|
||||
description = "base domain used for reverse proxy";
|
||||
};
|
||||
host_ip = lib.mkOption {
|
||||
default = "10.10.0.10";
|
||||
type = lib.types.str;
|
||||
description = "base domain used for reverse proxy";
|
||||
};
|
||||
};
|
||||
|
||||
# the order determines the order in glance :3
|
||||
imports = [
|
||||
./services
|
||||
./shares/nfs.nix
|
||||
./shares/smb.nix
|
||||
./shares/zfs.nix
|
||||
./motd
|
||||
./dnsmasq
|
||||
./backups
|
||||
./glance
|
||||
./postfix
|
||||
./caddy
|
||||
./home/zigbee2mqtt
|
||||
./vaultwarden
|
||||
./gitea
|
||||
./home/homeassistant
|
||||
./immich
|
||||
./arr/bazarr
|
||||
./arr/prowlarr
|
||||
./arr/radarr
|
||||
./qbittorrent
|
||||
./arr/sonarr
|
||||
./yacreader
|
||||
./audiobookshelf
|
||||
./jellyfin
|
||||
./arr/flaresolverr
|
||||
./home/mosquitto
|
||||
./uptime-kuma
|
||||
./tailscale
|
||||
];
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -47,5 +77,6 @@ in
|
||||
group = cfg.media_group;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
42
modules/homelab/dnsmasq/default.nix
Normal file
42
modules/homelab/dnsmasq/default.nix
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
service = "dnsmasq";
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.homelab;
|
||||
in {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 53;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# enable the ${service} service
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
settings = {
|
||||
listen-address = "10.10.0.10"; # your LAN IP
|
||||
#interface = "enp89s0";
|
||||
bind-interfaces = true;
|
||||
address = "/snowbelle.lan/10.10.0.10";
|
||||
server = [ # upstream dns
|
||||
"9.9.9.9"
|
||||
"1.1.1.1"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
networking.firewall.allowedUDPPorts = [ cfg.port ];
|
||||
|
||||
};
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
service = "minecraft_recpro";
|
||||
cfg = config.modules.gameservers.${service};
|
||||
sec = config.sops.secrets;
|
||||
servers = {
|
||||
velocity = { data_dir = "/var/lib/gameserver/minecraft_recpro/velocity"; ram = "2G"; };
|
||||
smp = { data_dir = "/var/lib/gameserver/minecraft_recpro/smp"; ram = "12G"; };
|
||||
superflat = { data_dir = "/var/lib/gameserver/minecraft_recpro/superflat"; ram = "4G"; };
|
||||
bento = { data_dir = "/var/lib/gameserver/minecraft_recpro"; ram = "2G"; };
|
||||
};
|
||||
in
|
||||
{
|
||||
options.modules.gameservers.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "mc.recoil.pro";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/gameservers/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 25565;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# declare ${service} group
|
||||
users.groups.minecraft = { gid = lib.mkForce cfg.ids; };
|
||||
|
||||
# declare ${service} user
|
||||
users.users.minecraft = {
|
||||
description = "minecraft server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
group = "minecraft";
|
||||
extraGroups = [];
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = lib.concatStringsSep "\n" (mapAttrsToList (name: cfg:
|
||||
"d ${cfg.data_dir} 0755 minecraft minecraft -") servers);
|
||||
|
||||
# Create a systemd service per server running in tmux
|
||||
systemd.services = lib.attrsets.mapAttrs (name: srv: {
|
||||
description = "minecraft_recpro: ${name}";
|
||||
after = [ "network.target" ];
|
||||
wants = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
User = "minecraft";
|
||||
WorkingDirectory = srv.data_dir;
|
||||
ExecStart = "${pkgs.tmux}/bin/tmux new-session -d -s ${name} '${pkgs.openjdk21}/bin/java -Xmx${srv.ram} -jar ${srv.data_dir}/server.jar nogui'";
|
||||
ExecStop = "${pkgs.tmux}/bin/tmux send-keys -t ${name} C-c"; # stop server by sending Ctrl+C to tmux session
|
||||
Restart = "on-failure";
|
||||
KillMode = "process";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
UMask = "0007";
|
||||
}) servers;
|
||||
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [ 25777 25565 25566 25567 ];
|
||||
|
||||
# # internal reverse proxy entry
|
||||
# services.nginx.virtualHosts."${cfg.url}" = {
|
||||
# forceSSL = true;
|
||||
# sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
# sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
# locations."/" = {
|
||||
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
# };
|
||||
# };
|
||||
# # external reverse proxy entry
|
||||
# services.nginx.virtualHosts."${service}.blakedheld.xyz" = {
|
||||
# forceSSL = true;
|
||||
# sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
# sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
# locations."/" = {
|
||||
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
# };
|
||||
# };
|
||||
#
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
# group = "${service}";
|
||||
# };
|
||||
# };
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
};
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
{ pkgs, nixpkgs-unstable, config, lib, ... }:
|
||||
|
||||
let
|
||||
service = "gitea";
|
||||
cfg = config.modules.services.${service};
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
@@ -41,6 +41,10 @@ in
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -56,8 +60,12 @@ in
|
||||
shell = pkgs.bash;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = "${service}";
|
||||
group = service;
|
||||
extraGroups = [];
|
||||
# if you wanna attempt system ssh again
|
||||
#openssh.authorizedKeys.keyFiles = [
|
||||
# "${cfg.data_dir}/.ssh/authorized_keys"
|
||||
#];
|
||||
};
|
||||
|
||||
# declare the gitea service
|
||||
@@ -69,12 +77,26 @@ in
|
||||
appName = "gitea";
|
||||
settings = {
|
||||
server = {
|
||||
# http config
|
||||
ROOT_URL = "https://git.blakedheld.xyz";
|
||||
DOMAIN = "git.blakedheld.xyz";
|
||||
HTTP_PORT = cfg.port;
|
||||
# local network config
|
||||
#LOCAL_ROOT_URL = "https://git.snowbelle.lan";
|
||||
ALLOW_LOCALNETWORKS = true;
|
||||
ALLOWED_DOMAINS = "10.10.0.10";
|
||||
SKIP_TLS_VERIFY = true;
|
||||
# configure for system ssh (trying to use the systms on nix sucks)
|
||||
SSH_PORT = cfg.ssh_port;
|
||||
START_SSH_SERVER = true;
|
||||
# SSH_PORT = 22;
|
||||
# START_SSH_SERVER = false;
|
||||
# SSH_ROOT_PATH = "${cfg.data_dir}/.ssh";
|
||||
# SSH_CREATE_AUTHORIZED_KEYS_FILE = true;
|
||||
# actual git config
|
||||
DEFAULT_BRANCH = "trunk";
|
||||
ENABLE_PUSH_CREATE_USER = true;
|
||||
|
||||
DEFAULT_PUSH_CREATE_PRIVATE = true;
|
||||
};
|
||||
};
|
||||
database = {
|
||||
@@ -90,32 +112,41 @@ in
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [ cfg.port cfg.ssh_port ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."git.${homelab.public_domain}" = {
|
||||
extraConfig = ''
|
||||
reverse_proxy localhost:${toString cfg.port} {
|
||||
}
|
||||
'';
|
||||
};
|
||||
# external reverse proxy entry
|
||||
services.nginx.virtualHosts."git.blakedheld.xyz" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
extraConfig = ''
|
||||
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
|
||||
reverse_proxy localhost:${toString cfg.port} {
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
# add to glance
|
||||
homelab.glance.links.services = [{
|
||||
title = service;
|
||||
url = "https://git.${homelab.public_domain}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
# manage secrets with sops
|
||||
sops.secrets = {
|
||||
"${service}_database_password" = {
|
||||
owner = "${service}";
|
||||
group = "${service}";
|
||||
owner = service;
|
||||
group = service;
|
||||
};
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
338
modules/homelab/glance/default.nix
Normal file
338
modules/homelab/glance/default.nix
Normal file
@@ -0,0 +1,338 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
/*
|
||||
this is a wrapper module for glance that allows you to
|
||||
to pass monitor entries in with nix, all declaratively!
|
||||
|
||||
| <8yy> |
|
||||
V V
|
||||
# add to glance
|
||||
homelab.glance.links.mediastack = [{
|
||||
title = service;
|
||||
url = "https://${cfg.url}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}";
|
||||
allow-insecure = true; }];
|
||||
*/
|
||||
|
||||
let
|
||||
service = "glance";
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.homelab;
|
||||
|
||||
uptimekuma_url = "localhost:7901";
|
||||
uptimekuma_page = "glance";
|
||||
in
|
||||
{
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 7700;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = cfg.port;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
links = {
|
||||
services = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.attrs;
|
||||
default = [ ];
|
||||
description = "list of links for ${service}";
|
||||
};
|
||||
mediastack = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.attrs;
|
||||
default = [ ];
|
||||
description = "list of links for ${service}";
|
||||
};
|
||||
system = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.attrs;
|
||||
default = [ ];
|
||||
description = "list of links for ${service}";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# declare ${service} group
|
||||
users.groups.${service} = {
|
||||
gid = lib.mkForce cfg.ids;
|
||||
};
|
||||
|
||||
# declare ${service} user
|
||||
users.users.${service} = {
|
||||
description = "${service} server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = service;
|
||||
extraGroups = [ ];
|
||||
};
|
||||
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
settings = {
|
||||
server = {
|
||||
host = "0.0.0.0";
|
||||
port = cfg.port;
|
||||
assets-path = "${cfg.data_dir}/assets";
|
||||
};
|
||||
# theme = {custom-css-file = "/assets/user.css";};
|
||||
auth = {
|
||||
secret-key = "+mYVAc1uO85hUUz5Ij6Lpelv1RqiLlneYqZD5Jv45buoF2+LZtIt2okRrbFCppiRQbqXkGoRMtSI0bROg4uFUw==";
|
||||
users = {
|
||||
blake = {
|
||||
password-hash = "$2a$10$RwPCkcto35DCp4vNTDpH6.G3TpecPJ/zUL1jI93uzr.lg6v233Sie";
|
||||
};
|
||||
};
|
||||
};
|
||||
branding = {
|
||||
logo-url = "/assets/icons/snowbelle.png";
|
||||
favicon-url = "/assets/icons/favicon.ico";
|
||||
};
|
||||
pages = [
|
||||
{
|
||||
name = "snowbelle";
|
||||
hide-desktop-navigation = true;
|
||||
columns = [
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{
|
||||
type = "calendar";
|
||||
first-day-of-week = "monday";
|
||||
}
|
||||
{
|
||||
type = "server-stats";
|
||||
servers = [
|
||||
{
|
||||
type = "local";
|
||||
name = "snowbelle";
|
||||
hide-mountpoints-by-default = true;
|
||||
mountpoints = {
|
||||
"/" = {name = "root"; hide = false;};
|
||||
"/holocron" = {name = "holocron"; hide = false;};
|
||||
"/holocron/media" = {name = "media"; hide = false;};
|
||||
"/holocron/vault" = {name = "vault"; hide = false;};
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "clock";
|
||||
hour-format = "24h";
|
||||
timezones = [
|
||||
{
|
||||
timezone = "America/Chicago";
|
||||
label = "HTX";
|
||||
}
|
||||
{
|
||||
timezone = "America/Denver";
|
||||
label = "AF";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "twitch-channels";
|
||||
channels = [
|
||||
"SaltSSBM"
|
||||
"thewaffle77"
|
||||
"ironmouse"
|
||||
"linustech"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "full";
|
||||
widgets = [
|
||||
{
|
||||
type = "search";
|
||||
autofocus = true;
|
||||
search-engine = "https://duckduckgo.com/?q={QUERY}";
|
||||
new-tab = true;
|
||||
bangs = [
|
||||
{
|
||||
title = "youtube";
|
||||
shortcut = "!y";
|
||||
url = "https://www.youtube.com/results?search_query={QUERY}";
|
||||
}
|
||||
{
|
||||
title = "google";
|
||||
shortcut = "!g";
|
||||
url = "https://www.google.com/search?q={QUERY}";
|
||||
}
|
||||
{
|
||||
title = "github";
|
||||
shortcut = "!gh";
|
||||
url = "https://github.com/search?q={QUERY}&type=repositories";
|
||||
}
|
||||
{
|
||||
title = "nixos options";
|
||||
shortcut = "!no";
|
||||
url = "https://search.nixos.org/options?channel=25.05&query={QUERY}";
|
||||
}
|
||||
{
|
||||
title = "nixos packages";
|
||||
shortcut = "!np";
|
||||
url = "https://search.nixos.org/packages?channel=25.05&query={QUERY}";
|
||||
}
|
||||
{
|
||||
title = "home-manager options";
|
||||
shortcut = "!hm";
|
||||
url = "https://home-manager-options.extranix.com/?query={QUERY}&release=release-25.05";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = "services";
|
||||
sites = cfg.links.services;
|
||||
}
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = "mediastack";
|
||||
sites = cfg.links.mediastack;
|
||||
}
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = "system";
|
||||
sites = cfg.links.system;
|
||||
}
|
||||
{
|
||||
type = "custom-api";
|
||||
title = "recpro";
|
||||
url = "https://api.mcstatus.io/v2/status/java/mc.recoil.pro";
|
||||
cache = "5s";
|
||||
template = "<div style=\"display:flex; align-items:center; gap:12px;\">\n <div style=\"width:40px; height:40px; flex-shrink:0; border-radius:4px; display:flex; justify-content:center; align-items:center; overflow:hidden;\">\n {{ if .JSON.Bool \"online\" }}\n <img src=\"{{ .JSON.String \"icon\" | safeURL }}\" width=\"64\" height=\"64\" style=\"object-fit:contain;\">\n {{ else }}\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" style=\"width:32px; height:32px; opacity:0.5;\">\n <path fill-rule=\"evenodd\" d=\"M1 5.25A2.25 2.25 0 0 1 3.25 3h13.5A2.25 2.25 0 0 1 19 5.25v9.5A2.25 2.25 0 0 1 16.75 17H3.25A2.25 2.25 0 0 1 1 14.75v-9.5Zm1.5 5.81v3.69c0 .414.336.75.75.75h13.5a.75.75 0 0 0 .75-.75v-2.69l-2.22-2.219a.75.75 0 0 0-1.06 0l-1.91 1.909.47.47a.75.75 0 1 1-1.06 1.06L6.53 8.091a.75.75 0 0 0-1.06 0l-2.97 2.97ZM12 7a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\" clip-rule=\"evenodd\" />\n </svg>\n {{ end }}\n </div>\n\n <div style=\"flex-grow:1; min-width:0;\">\n <a class=\"size-h4 block text-truncate color-highlight\">\n {{ .JSON.String \"host\" }}\n {{ if .JSON.Bool \"online\" }}\n <span\n style=\"width: 8px; height: 8px; border-radius: 50%; background-color: var(--color-positive); display: inline-block; vertical-align: middle;\"\n data-popover-type=\"text\"\n data-popover-text=\"Online\"\n ></span>\n {{ else }}\n <span\n style=\"width: 8px; height: 8px; border-radius: 50%; background-color: var(--color-negative); display: inline-block; vertical-align: middle;\"\n data-popover-type=\"text\"\n data-popover-text=\"Offline\"\n ></span>\n {{ end }}\n </a>\n\n <ul class=\"list-horizontal-text\">\n <li>\n {{ if .JSON.Bool \"online\" }}\n <span>{{ .JSON.String \"version.name_clean\" }}</span>\n {{ else }}\n <span>Offline</span>\n {{ end }}\n </li>\n {{ if .JSON.Bool \"online\" }}\n <li data-popover-type=\"html\">\n <div data-popover-html>\n {{ range .JSON.Array \"players.list\" }}{{ .String \"name_clean\" }}<br>{{ end }}\n </div>\n <p style=\"display:inline-flex;align-items:center;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"size-6\" style=\"height:1em;vertical-align:middle;margin-right:0.5em;\">\n <path fill-rule=\"evenodd\" d=\"M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z\" clip-rule=\"evenodd\" />\n </svg>\n {{ .JSON.Int \"players.online\" | formatNumber }}/{{ .JSON.Int \"players.max\" | formatNumber }} players\n </p>\n </li>\n {{ else }}\n <li>\n <p style=\"display:inline-flex;align-items:center;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"size-6\" style=\"height:1em;vertical-align:middle;margin-right:0.5em;opacity:0.5;\">\n <path fill-rule=\"evenodd\" d=\"M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z\" clip-rule=\"evenodd\" />\n </svg>\n 0 players\n </p>\n </li>\n {{ end }}\n </ul>\n </div>\n</div>";
|
||||
}
|
||||
{
|
||||
type = "custom-api";
|
||||
title = "cobblemon";
|
||||
url = "https://api.mcstatus.io/v2/status/java/cobblemon.recoil.pro";
|
||||
cache = "5s";
|
||||
template = "<div style=\"display:flex; align-items:center; gap:12px;\">\n <div style=\"width:40px; height:40px; flex-shrink:0; border-radius:4px; display:flex; justify-content:center; align-items:center; overflow:hidden;\">\n {{ if .JSON.Bool \"online\" }}\n <img src=\"{{ .JSON.String \"icon\" | safeURL }}\" width=\"64\" height=\"64\" style=\"object-fit:contain;\">\n {{ else }}\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" style=\"width:32px; height:32px; opacity:0.5;\">\n <path fill-rule=\"evenodd\" d=\"M1 5.25A2.25 2.25 0 0 1 3.25 3h13.5A2.25 2.25 0 0 1 19 5.25v9.5A2.25 2.25 0 0 1 16.75 17H3.25A2.25 2.25 0 0 1 1 14.75v-9.5Zm1.5 5.81v3.69c0 .414.336.75.75.75h13.5a.75.75 0 0 0 .75-.75v-2.69l-2.22-2.219a.75.75 0 0 0-1.06 0l-1.91 1.909.47.47a.75.75 0 1 1-1.06 1.06L6.53 8.091a.75.75 0 0 0-1.06 0l-2.97 2.97ZM12 7a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\" clip-rule=\"evenodd\" />\n </svg>\n {{ end }}\n </div>\n\n <div style=\"flex-grow:1; min-width:0;\">\n <a class=\"size-h4 block text-truncate color-highlight\">\n {{ .JSON.String \"host\" }}\n {{ if .JSON.Bool \"online\" }}\n <span\n style=\"width: 8px; height: 8px; border-radius: 50%; background-color: var(--color-positive); display: inline-block; vertical-align: middle;\"\n data-popover-type=\"text\"\n data-popover-text=\"Online\"\n ></span>\n {{ else }}\n <span\n style=\"width: 8px; height: 8px; border-radius: 50%; background-color: var(--color-negative); display: inline-block; vertical-align: middle;\"\n data-popover-type=\"text\"\n data-popover-text=\"Offline\"\n ></span>\n {{ end }}\n </a>\n\n <ul class=\"list-horizontal-text\">\n <li>\n {{ if .JSON.Bool \"online\" }}\n <span>{{ .JSON.String \"version.name_clean\" }}</span>\n {{ else }}\n <span>Offline</span>\n {{ end }}\n </li>\n {{ if .JSON.Bool \"online\" }}\n <li data-popover-type=\"html\">\n <div data-popover-html>\n {{ range .JSON.Array \"players.list\" }}{{ .String \"name_clean\" }}<br>{{ end }}\n </div>\n <p style=\"display:inline-flex;align-items:center;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"size-6\" style=\"height:1em;vertical-align:middle;margin-right:0.5em;\">\n <path fill-rule=\"evenodd\" d=\"M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z\" clip-rule=\"evenodd\" />\n </svg>\n {{ .JSON.Int \"players.online\" | formatNumber }}/{{ .JSON.Int \"players.max\" | formatNumber }} players\n </p>\n </li>\n {{ else }}\n <li>\n <p style=\"display:inline-flex;align-items:center;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" class=\"size-6\" style=\"height:1em;vertical-align:middle;margin-right:0.5em;opacity:0.5;\">\n <path fill-rule=\"evenodd\" d=\"M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z\" clip-rule=\"evenodd\" />\n </svg>\n 0 players\n </p>\n </li>\n {{ end }}\n </ul>\n </div>\n</div>";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{
|
||||
type = "weather";
|
||||
location = "Pearland, Texas, United States";
|
||||
units = "imperial";
|
||||
hour-format = "24h";
|
||||
}
|
||||
{
|
||||
type = "markets";
|
||||
markets = [
|
||||
{
|
||||
symbol = "SPY";
|
||||
name = "S&P 500";
|
||||
}
|
||||
{
|
||||
symbol = "XMR-USD";
|
||||
name = "Monero";
|
||||
}
|
||||
{
|
||||
symbol = "NVDA";
|
||||
name = "NVIDIA";
|
||||
}
|
||||
{
|
||||
symbol = "AAPL";
|
||||
name = "Apple";
|
||||
}
|
||||
{
|
||||
symbol = "MSFT";
|
||||
name = "Microsoft";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "releases";
|
||||
cache = "1d";
|
||||
repositories = [
|
||||
"glanceapp/glance"
|
||||
"go-gitea/gitea"
|
||||
"immich-app/immich"
|
||||
"syncthing/syncthing"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
User = service;
|
||||
Group = service;
|
||||
};
|
||||
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
# serverAliases = [ "${homelab.public_domain}" ];
|
||||
extraConfig = ''
|
||||
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = {
|
||||
paths = [ cfg.data_dir ];
|
||||
};
|
||||
};
|
||||
|
||||
# add to udr to glance
|
||||
homelab.glance.links.system = [{
|
||||
title = "bebe";
|
||||
url = "https://bebe.lan";
|
||||
error-url = "https://10.10.0.1";
|
||||
check-url = "https://10.10.0.1";
|
||||
icon = "di:unifi";
|
||||
allow-insecure = true; }];
|
||||
};
|
||||
}
|
||||
161
modules/homelab/home/homeassistant/default.nix
Normal file
161
modules/homelab/home/homeassistant/default.nix
Normal file
@@ -0,0 +1,161 @@
|
||||
{ pkgs, config, lib, inputs, ... }:
|
||||
|
||||
let
|
||||
nixservice = "home-assistant";
|
||||
service = "hass";
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 7704;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${service}.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = cfg.port;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = "podman-hass";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# declare ${service} group
|
||||
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
|
||||
|
||||
# declare ${service} user
|
||||
users.users.${service} = {
|
||||
description = "${service} server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = service;
|
||||
extraGroups = [];
|
||||
};
|
||||
|
||||
# still suss as fuck bro man fuck
|
||||
virtualisation.oci-containers.containers = {
|
||||
hass = {
|
||||
image = "homeassistant/home-assistant:stable";
|
||||
autoStart = true;
|
||||
extraOptions = [
|
||||
"--pull=newer"
|
||||
"--network=host"
|
||||
];
|
||||
volumes = [
|
||||
"${cfg.data_dir}:/config"
|
||||
];
|
||||
# ports = [
|
||||
# "0.0.0.0:7704:8123"
|
||||
# "0.0.0.0:4141:4141"
|
||||
# ];
|
||||
environment = {
|
||||
TZ = homelab.tz;
|
||||
PUID = toString config.users.users.${service}.uid;
|
||||
PGID = toString config.users.groups.${service}.gid;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
};
|
||||
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [ cfg.port 8123 ];
|
||||
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
serverAliases = [ "${service}.${homelab.public_domain}" ];
|
||||
extraConfig = ''
|
||||
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
|
||||
# add to glance
|
||||
homelab.glance.links.services = [{
|
||||
title = "home assistant";
|
||||
url = "https://hass.${homelab.public_domain}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${nixservice}"; }];
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
# here lies my tough, and I mean fucking tough, swing at
|
||||
# getting this to work bare metal, ggs ill see you again
|
||||
# - didnt take long
|
||||
# --------------------------------------------------------------------------------
|
||||
# # enable the ${service} service
|
||||
# services.${nixservice} = {
|
||||
# enable = true;
|
||||
# package = inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}.home-assistant;
|
||||
# extraComponents = [
|
||||
# # required for onboarding
|
||||
# "analytics"
|
||||
# "google_translate"
|
||||
# "met"
|
||||
# "radio_browser"
|
||||
# "shopping_list"
|
||||
# "isal"
|
||||
# "default_config"
|
||||
# "mqtt"
|
||||
# ];
|
||||
# extraPackages = python3Packages: with python3Packages; [
|
||||
# psycopg2
|
||||
# universal-silabs-flasher
|
||||
# getmac
|
||||
# zha
|
||||
# ha-silabs-firmware-client
|
||||
# paho-mqtt
|
||||
# aiomqtt
|
||||
# aiounifi
|
||||
# ibeacon-ble
|
||||
# ];
|
||||
# # imperative config
|
||||
# config = null;
|
||||
# lovelaceConfig = null;
|
||||
# configDir = cfg.data_dir;
|
||||
# # declartive poggers!
|
||||
## config = {
|
||||
## # Includes dependencies for a basic setup
|
||||
## default_config = {};
|
||||
## };
|
||||
# };
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
let
|
||||
service = "mosquitto";
|
||||
cfg = config.modules.services.${service};
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
@@ -36,6 +36,10 @@ in
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -50,7 +54,7 @@ in
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = "${service}";
|
||||
group = service;
|
||||
extraGroups = [];
|
||||
};
|
||||
|
||||
@@ -60,38 +64,36 @@ in
|
||||
{
|
||||
port = 1883;
|
||||
address = "0.0.0.0";
|
||||
settings.allow_anonymous = true;
|
||||
#passwordFile = sec."mosquitto_password_file".path; # optional
|
||||
users.zigbee = {
|
||||
acl = [ "readwrite #" ];
|
||||
hashedPassword = "$7$101$140powz2MtsRawFT$ydndjal9wCAywIWtUEAh/IusdfDFvnHMupTFjdS7Ad/EjsEIbJgHrLY9waCe4Z3142XieuxMrXUDjMTp2qwyiw==";
|
||||
};
|
||||
# use with no auth
|
||||
# settings.allow_anonymous = true;
|
||||
# acl = [ "pattern readwrite #" ];
|
||||
# omitPasswordAuth = true;
|
||||
}
|
||||
];
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
User = "${service}";
|
||||
Group = "${service}";
|
||||
User = service;
|
||||
Group = service;
|
||||
};
|
||||
|
||||
# # open firewall
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# # internal reverse proxy entry
|
||||
# services.nginx.virtualHosts."${cfg.url}" = {
|
||||
# forceSSL = true;
|
||||
# sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
# sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
# locations."/" = {
|
||||
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
# };
|
||||
# };
|
||||
|
||||
sops.secrets = {
|
||||
"${service}_password_file" = {
|
||||
owner = "${service}";
|
||||
group = "${service}";
|
||||
"${service}_hashed_passwd" = {
|
||||
owner = service;
|
||||
group = service;
|
||||
};
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
let
|
||||
service = "zigbee2mqtt";
|
||||
cfg = config.modules.services.${service};
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
@@ -18,7 +18,7 @@ in
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${service}.${homelab.base_domain}";
|
||||
default = "z2m.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
@@ -36,6 +36,10 @@ in
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -50,7 +54,7 @@ in
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = "${service}";
|
||||
group = service;
|
||||
extraGroups = [];
|
||||
};
|
||||
|
||||
@@ -61,7 +65,11 @@ in
|
||||
settings = {
|
||||
mqtt = {
|
||||
base_topic = "zigbee2mqtt";
|
||||
client_id = "zigbee2mqtt";
|
||||
server = "mqtt://localhost:1883";
|
||||
user = "!/run/secrets/mosquitto_passwd.yaml user";
|
||||
password = "!/run/secrets/mosquitto_passwd.yaml password";
|
||||
keepalive = 20;
|
||||
};
|
||||
serial = {
|
||||
port = "/dev/serial/by-id/usb-Itead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_V2_4a4e75d63653ef1198d728e0174bec31-if00-port0";
|
||||
@@ -83,31 +91,40 @@ in
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
User = "${service}";
|
||||
Group = "${service}";
|
||||
User = service;
|
||||
Group = service;
|
||||
};
|
||||
|
||||
# # open firewall
|
||||
networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
serverAliases = [ "z2m.${homelab.public_domain}" ];
|
||||
extraConfig = ''
|
||||
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
|
||||
# add to glance
|
||||
homelab.glance.links.services = [{
|
||||
title = service;
|
||||
url = "https://${cfg.url}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
sops.secrets = {
|
||||
"mosquitto_passwd.yaml" = {
|
||||
owner = service;
|
||||
group = service;
|
||||
};
|
||||
};
|
||||
#
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
# group = "${service}";
|
||||
# };
|
||||
# };
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
120
modules/homelab/immich/default.nix
Normal file
120
modules/homelab/immich/default.nix
Normal file
@@ -0,0 +1,120 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
unstable_pkgs,
|
||||
...
|
||||
}: let
|
||||
service = "immich";
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.homelab;
|
||||
in {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 7702;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "photos.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = cfg.port;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = "immich-server";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# declare ${service} group
|
||||
users.groups.${service} = {gid = lib.mkForce cfg.ids;};
|
||||
|
||||
# declare ${service} user
|
||||
users.users.${service} = {
|
||||
description = "${service} server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = service;
|
||||
extraGroups = ["video" "render" "blake"];
|
||||
};
|
||||
|
||||
# enable the ${service} service
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
#package = inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}.immich;
|
||||
package = unstable_pkgs.x86_64.immich;
|
||||
openFirewall = true;
|
||||
user = service;
|
||||
group = service;
|
||||
mediaLocation = cfg.data_dir;
|
||||
host = "0.0.0.0";
|
||||
port = cfg.port;
|
||||
settings = null;
|
||||
#settings.server.externalDomain = "https://photos.blakedheld.xyz";
|
||||
};
|
||||
|
||||
# override umask to make permissions work out
|
||||
# systemd.services."${toString service}-server".serviceConfig = {
|
||||
# UMask = lib.mkForce "0007";
|
||||
# };
|
||||
# systemd.services."${toString service}-machine-learning".serviceConfig = {
|
||||
# UMask = lib.mkForce "0007";
|
||||
# };
|
||||
|
||||
# # open firewall
|
||||
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
serverAliases = ["photos.${homelab.public_domain}"];
|
||||
extraConfig = ''
|
||||
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
|
||||
# add to glance
|
||||
homelab.glance.links.services = [
|
||||
{
|
||||
title = service;
|
||||
url = "https://photos.${homelab.public_domain}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}";
|
||||
}
|
||||
];
|
||||
|
||||
# add postgresql database that is automatically created to the backup list
|
||||
#services.postgresqlBackup.databases = ["immich"]; # set to all databases defined in esure databases
|
||||
|
||||
services.postgresql.ensureDatabases = [service]; # set to all databases defined in esure databases
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = {paths = [cfg.data_dir "/var/lib/redis-immich" "/var/backup/postgresql/immich.sql.zstd"];};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
let
|
||||
service = "jellyfin";
|
||||
cfg = config.modules.services.${service};
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
@@ -36,6 +36,10 @@ in
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -50,7 +54,7 @@ in
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = "${service}";
|
||||
group = service;
|
||||
extraGroups = [ "media" "video" "render" ];
|
||||
};
|
||||
|
||||
@@ -58,8 +62,8 @@ in
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
user = "${service}";
|
||||
group = "${service}";
|
||||
user = service;
|
||||
group = service;
|
||||
dataDir = cfg.data_dir;
|
||||
};
|
||||
|
||||
@@ -71,33 +75,26 @@ in
|
||||
# # open firewall
|
||||
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
# external reverse proxy entry
|
||||
services.nginx.virtualHosts."media.blakedheld.xyz" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
serverAliases = [ "media.${homelab.public_domain}" ];
|
||||
extraConfig = ''
|
||||
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
# group = "${service}";
|
||||
# };
|
||||
# };
|
||||
# add to glance
|
||||
homelab.glance.links.mediastack = [{
|
||||
title = service;
|
||||
url = "https://media.${homelab.public_domain}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
98
modules/homelab/motd/default.nix
Normal file
98
modules/homelab/motd/default.nix
Normal file
@@ -0,0 +1,98 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf mkOption types filterAttrs mapAttrsToList;
|
||||
cfg = config.homelab.motd;
|
||||
|
||||
# collect services to display
|
||||
motd_list =
|
||||
mapAttrsToList (_: v: v.motd)
|
||||
(filterAttrs (_: v: v ? motd && v.motd != null) config.homelab);
|
||||
in {
|
||||
options.homelab.motd = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "enable motd script";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.etc."motd".text = ''
|
||||
#!/usr/bin/env bash
|
||||
|
||||
active=$'\033[1;34m'
|
||||
inactive=$'\033[1;31m'
|
||||
headings=$'\033[1;35m'
|
||||
bold=$'\e[1m'
|
||||
reset=$'\033[0m'
|
||||
memory=`free -m | awk 'NR==2{printf "%s/%sMB (%.2f%%)\n", $3,$2,$3*100 / $2 }'`
|
||||
load1=`cat /proc/loadavg | awk {'print $1'}`
|
||||
load5=`cat /proc/loadavg | awk {'print $2'}`
|
||||
load15=`cat /proc/loadavg | awk {'print $3'}`
|
||||
uptime=`cat /proc/uptime | cut -f1 -d.`
|
||||
up_days=$((uptime/60/60/24))
|
||||
up_hours=$((uptime/60/60%24))
|
||||
up_mins=$((uptime/60%60))
|
||||
up_secs=$((uptime%60))
|
||||
nixos_version=$(nixos-version | sed -E 's/^([0-9]{2}\.[0-9]{2}).*\(([^)]+)\)$/\1 (\2)/')
|
||||
cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print 100 - $8 "%"}')
|
||||
mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
|
||||
mem_avail=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
|
||||
mem_used=$((mem_total - mem_avail))
|
||||
mem_percent=$((100 * mem_used / mem_total))
|
||||
uptime_fmt=$(uptime -p 2>/dev/null || cat /proc/uptime | awk '{print int($1/3600)"h "int(($1%3600)/60)"m"}')
|
||||
|
||||
printf "$bold welcome to $(hostname)!$reset\n"
|
||||
printf "\n"
|
||||
printf "$bold * %-20s$reset %s\n" "Release" "$nixos_version"
|
||||
printf "$bold * %-20s$reset %s\n" "Kernel" "$(uname -rs)"
|
||||
printf "\n"
|
||||
printf "$bold * %-20s$reset %s\n" "CPU usage" "$load1, $load5, $load15 (1, 5, 15 min)"
|
||||
printf "$bold * %-20s$reset %s\n" "Memory" "$memory"
|
||||
printf "$bold * %-20s$reset %s\n" "System uptime" "$up_days days $up_hours hours $up_mins minutes $up_secs seconds"
|
||||
|
||||
echo
|
||||
|
||||
# --- services ---
|
||||
echo -e "''${headings}homelab services:''${reset}"
|
||||
|
||||
${lib.concatStringsSep "\n" (map (service: ''
|
||||
if systemctl list-units --type=service --all | grep -q "${service}"; then
|
||||
status=$(systemctl is-active ${service} 2>/dev/null)
|
||||
if [ "$status" = "active" ]; then
|
||||
printf "%-32s%s\n" " ''${active}[${service}]''${reset}" "running"
|
||||
else
|
||||
printf "%-32s%s\n" " ''${active}[${service}]''${reset}" "not running"
|
||||
fi
|
||||
else
|
||||
printf "%-32s%s\n" " ''${active}[${service}]''${reset}" "not found"
|
||||
fi
|
||||
'')
|
||||
motd_list)}
|
||||
|
||||
echo
|
||||
|
||||
# --- gameservers ---
|
||||
echo -e "''${headings}gameservers:''${reset}"
|
||||
for service in velocity smp superflat bento cobblemon; do
|
||||
status=$(systemctl is-active $service 2>/dev/null)
|
||||
if [ "$status" = "active" ]; then
|
||||
printf "%-32s%s\n" " ''${active}[$service]''${reset}" "running"
|
||||
else
|
||||
printf "%-32s%s\n" " ''${active}[$service]''${reset}" "not running"
|
||||
fi
|
||||
done
|
||||
echo
|
||||
'';
|
||||
|
||||
environment.etc."motd".mode = "0755";
|
||||
|
||||
programs.zsh.interactiveShellInit = ''
|
||||
/etc/motd
|
||||
'';
|
||||
};
|
||||
}
|
||||
99
modules/homelab/postfix/default.nix
Normal file
99
modules/homelab/postfix/default.nix
Normal file
@@ -0,0 +1,99 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
service = "postfix";
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.homelab;
|
||||
in {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 587;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${service}.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = cfg.port;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# declare ${service} group
|
||||
# users.groups.${service} = {
|
||||
# gid = lib.mkForce cfg.ids;
|
||||
# };
|
||||
#
|
||||
# # declare ${service} user
|
||||
# users.users.${service} = {
|
||||
# description = "${service} server user";
|
||||
# uid = lib.mkForce cfg.ids;
|
||||
# isSystemUser = true;
|
||||
# home = cfg.data_dir;
|
||||
# createHome = true;
|
||||
# group = service;
|
||||
# extraGroups = [];
|
||||
# };
|
||||
|
||||
# enable the ${service} service
|
||||
services.postfix = {
|
||||
enable = true;
|
||||
settings.main = {
|
||||
relayhost = ["smtp.gmail.com:${toString cfg.port}"];
|
||||
smtp_tls_security_level = "may";
|
||||
smtp_sasl_auth_enable = "yes";
|
||||
smtp_sasl_security_options = "noanonymous";
|
||||
smtp_sasl_password_maps = "texthash:${config.sops.secrets."postfix_passwd".path}";
|
||||
# optional: Forward mails to root (e.g. from cron jobs, smartd)
|
||||
# to me privately and to my work email:
|
||||
virtual_alias_maps = "inline:{ {root=me@blakedheld.xyz, throwedspam@gmail.com} }";
|
||||
};
|
||||
};
|
||||
|
||||
# override umask to make permissions work out
|
||||
# systemd.services.${service}.serviceConfig = {
|
||||
# UMask = lib.mkForce "0007";
|
||||
# User = service;
|
||||
# Group = service;
|
||||
#};
|
||||
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
sops.secrets = {
|
||||
"${service}_passwd" = {
|
||||
owner = config.services.postfix.user;
|
||||
group = config.services.postfix.group;
|
||||
};
|
||||
};
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = {
|
||||
paths = [cfg.data_dir];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
100
modules/homelab/postfix/default.nix.icloud_attempt
Normal file
100
modules/homelab/postfix/default.nix.icloud_attempt
Normal file
@@ -0,0 +1,100 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
service = "postfix";
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.homelab;
|
||||
in {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 587;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${service}.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = cfg.port;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# declare ${service} group
|
||||
# users.groups.${service} = {
|
||||
# gid = lib.mkForce cfg.ids;
|
||||
# };
|
||||
#
|
||||
# # declare ${service} user
|
||||
# users.users.${service} = {
|
||||
# description = "${service} server user";
|
||||
# uid = lib.mkForce cfg.ids;
|
||||
# isSystemUser = true;
|
||||
# home = cfg.data_dir;
|
||||
# createHome = true;
|
||||
# group = service;
|
||||
# extraGroups = [];
|
||||
# };
|
||||
|
||||
# enable the ${service} service
|
||||
services.postfix = {
|
||||
enable = true;
|
||||
relayHost = "smtp.mail.me.com";
|
||||
relayPort = cfg.port;
|
||||
config = {
|
||||
smtp_tls_security_level = "may";
|
||||
smtp_sasl_auth_enable = "yes";
|
||||
smtp_sasl_security_options = "";
|
||||
smtp_sasl_password_maps = "texthash:${config.sops.secrets."postfix_passwd".path}";
|
||||
# optional: Forward mails to root (e.g. from cron jobs, smartd)
|
||||
# to me privately and to my work email:
|
||||
virtual_alias_maps = "inline:{ {root=me@blakedheld.xyz} }";
|
||||
};
|
||||
};
|
||||
|
||||
# override umask to make permissions work out
|
||||
# systemd.services.${service}.serviceConfig = {
|
||||
# UMask = lib.mkForce "0007";
|
||||
# User = service;
|
||||
# Group = service;
|
||||
#};
|
||||
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
sops.secrets = {
|
||||
"${service}_passwd" = {
|
||||
owner = config.services.postfix.user;
|
||||
group = config.services.postfix.group;
|
||||
};
|
||||
};
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = {
|
||||
paths = [cfg.data_dir];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
let
|
||||
service = "qbittorrent";
|
||||
cfg = config.modules.services.${service};
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
@@ -46,12 +46,18 @@ in
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# declare ${service} group
|
||||
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
|
||||
# ensure media dirs existence
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /holocron/media/downloads 2775 qbittorrent media -"
|
||||
];
|
||||
|
||||
# declare ${service} user
|
||||
users.users.${service} = {
|
||||
@@ -60,16 +66,15 @@ in
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = "${service}";
|
||||
extraGroups = [ "media" ];
|
||||
group = "media";
|
||||
};
|
||||
|
||||
# enable the qbittorrent service
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
user = "${service}";
|
||||
group = "${service}";
|
||||
user = service;
|
||||
group = lib.mkForce "media"; # override for permissions
|
||||
profileDir = cfg.data_dir;
|
||||
webuiPort = cfg.port;
|
||||
# torrentingPort = cfg.torrenting_port;
|
||||
@@ -109,17 +114,25 @@ in
|
||||
# # open firewall
|
||||
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
extraConfig = ''
|
||||
tls internal
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# add to glance
|
||||
homelab.glance.links.mediastack = [{
|
||||
title = service;
|
||||
url = "https://${cfg.url}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
{
|
||||
|
||||
imports = [
|
||||
./jellyfin
|
||||
./vaultwarden
|
||||
./gitea
|
||||
./qbittorrent
|
||||
./immich
|
||||
./uptime-kuma
|
||||
./nginx-proxy
|
||||
./smarthome/homeassistant
|
||||
./smarthome/zigbee2mqtt
|
||||
./smarthome/mosquitto
|
||||
./arr/prowlarr
|
||||
./arr/flaresolverr
|
||||
./arr/bazarr
|
||||
./arr/sonarr
|
||||
./arr/radarr
|
||||
];
|
||||
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
service = "";
|
||||
cfg = config.modules.services.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = <port>;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${service}.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = cfg.port;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# declare ${service} group
|
||||
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
|
||||
|
||||
# declare ${service} user
|
||||
users.users.${service} = {
|
||||
description = "${service} server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = "${service}";
|
||||
extraGroups = [ "media" ];
|
||||
};
|
||||
|
||||
# enable the ${service} service
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
user = "${service}";
|
||||
group = "${service}";
|
||||
dataDir = cfg.data_dir;
|
||||
settings = {
|
||||
server.port = cfg.port;
|
||||
};
|
||||
};
|
||||
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
# User = "${service}";
|
||||
# Group = "${service}";
|
||||
};
|
||||
|
||||
# # open firewall
|
||||
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
# # external reverse proxy entry
|
||||
# services.nginx.virtualHosts."${service}.blakedheld.xyz" = {
|
||||
# forceSSL = true;
|
||||
# sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
# sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
# locations."/" = {
|
||||
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
# };
|
||||
# };
|
||||
#
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
# group = "${service}";
|
||||
# };
|
||||
# };
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
};
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
{ pkgs, config, lib, inputs, ... }:
|
||||
|
||||
let
|
||||
service = "immich";
|
||||
cfg = config.modules.services.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 7702;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "$=photos.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = cfg.port;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# declare ${service} group
|
||||
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
|
||||
|
||||
# declare ${service} user
|
||||
users.users.${service} = {
|
||||
description = "${service} server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = "${service}";
|
||||
extraGroups = [ "video" "render" ];
|
||||
};
|
||||
|
||||
# enable the ${service} service
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
package = inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}.immich;
|
||||
openFirewall = true;
|
||||
user = "${service}";
|
||||
group = "${service}";
|
||||
mediaLocation = cfg.data_dir;
|
||||
host = "0.0.0.0";
|
||||
port = cfg.port;
|
||||
settings.server.externalDomain = "https://pics.blakedheld.xyz";
|
||||
};
|
||||
|
||||
# override umask to make permissions work out
|
||||
# systemd.services."${toString service}-server".serviceConfig = {
|
||||
# UMask = lib.mkForce "0007";
|
||||
# };
|
||||
|
||||
# # open firewall
|
||||
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
# external reverse proxy entry
|
||||
services.nginx.virtualHosts."photos.blakedheld.xyz" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir "/var/lib/redis-immich" ];
|
||||
};
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.modules.homelab.nginx-proxy;
|
||||
in
|
||||
{
|
||||
options.modules.homelab.nginx-proxy = {
|
||||
enable = lib.mkEnableOption "enables nginx-proxy";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# enable nginx proxy manager
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
};
|
||||
# enable acme for auto ssl certs with lets encrypt
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults.email = "me@blakedheld.xyz";
|
||||
};
|
||||
|
||||
# nginx secrets
|
||||
sops.secrets = {
|
||||
"ssl_blakedheld_crt" = {
|
||||
restartUnits = [ "nginx.service" ];
|
||||
owner = "nginx";
|
||||
group = "nginx";
|
||||
# neededForUsers = true;
|
||||
};
|
||||
"ssl_blakedheld_key" = {
|
||||
owner = "nginx";
|
||||
group = "nginx";
|
||||
# neededForUsers = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
{ pkgs, config, lib, inputs, ... }:
|
||||
|
||||
let
|
||||
service = "home-assistant";
|
||||
cfg = config.modules.services.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 7704;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "hass.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/hass";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = cfg.port;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# declare ${service} group
|
||||
users.groups.hass = { gid = lib.mkForce cfg.ids; };
|
||||
|
||||
# declare ${service} user
|
||||
users.users.hass = {
|
||||
description = "${service} server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
#home = cfg.data_dir;
|
||||
#createHome = true;
|
||||
group = "hass";
|
||||
extraGroups = [ "bluetooth" ];
|
||||
};
|
||||
|
||||
# enable the ${service} service
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
package = inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}.home-assistant;
|
||||
extraComponents = [
|
||||
# required for onboarding
|
||||
"analytics"
|
||||
"google_translate"
|
||||
"met"
|
||||
"radio_browser"
|
||||
"shopping_list"
|
||||
# zlib
|
||||
"isal"
|
||||
];
|
||||
# imperative config
|
||||
# config = null;
|
||||
# lovelaceConfig = null;
|
||||
# configDir = cfg.data_dir;
|
||||
# declartive poggers!
|
||||
config = {
|
||||
# Includes dependencies for a basic setup
|
||||
default_config = {};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
User = lib.mkForce "hass";
|
||||
Group = lib.mkForce "hass";
|
||||
};
|
||||
|
||||
# # open firewall
|
||||
networking.firewall.allowedTCPPorts = [ cfg.port 8123 ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
# external reverse proxy entry
|
||||
services.nginx.virtualHosts."hass.blakedheld.xyz" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
# group = "${service}";
|
||||
# };
|
||||
# };
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
};
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
# define smb shares
|
||||
let
|
||||
cfg = config.modules.homelab.smb;
|
||||
smb_shares = {
|
||||
vault = {
|
||||
path = "/holocron/vault";
|
||||
browseable = true;
|
||||
writable = true;
|
||||
guestOk = false;
|
||||
};
|
||||
media = {
|
||||
path = "/holocron/media";
|
||||
browseable = true;
|
||||
writable = true;
|
||||
guestOk = false;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options.modules.homelab.smb = {
|
||||
enable = lib.mkEnableOption "enables smb";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# enable smb with all shares
|
||||
services.samba = {
|
||||
enable = true;
|
||||
settings = smb_shares;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.modules.homelab.zfs;
|
||||
in
|
||||
{
|
||||
options.modules.homelab.zfs = {
|
||||
enable = lib.mkEnableOption "enables zfs";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# set network host id
|
||||
networking.hostId = "3e6e7055";
|
||||
|
||||
# enable zfs support
|
||||
boot.kernelModules = [ "zfs" ];
|
||||
boot.supportedFilesystems = [ "zfs" ];
|
||||
|
||||
# enable smart monitoring
|
||||
services.smartd.enable = true;
|
||||
|
||||
# enable zfs
|
||||
services.zfs = {
|
||||
autoScrub.enable = true;
|
||||
autoScrub.interval = "weekly";
|
||||
};
|
||||
|
||||
fileSystems."/holocron" = {
|
||||
device = "holocron";
|
||||
fsType = "zfs";
|
||||
options = [ "nofail" ];
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
40
modules/homelab/tailscale/default.nix
Normal file
40
modules/homelab/tailscale/default.nix
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
cfg = config.homelab.tailscale;
|
||||
authkey_file = config.sops.secrets."tailscale_authkey".path;
|
||||
in {
|
||||
options.homelab.tailscale = {
|
||||
enable = lib.mkEnableOption "enables tailscale";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
useRoutingFeatures = "both";
|
||||
authKeyFile = authkey_file;
|
||||
extraSetFlags = [
|
||||
"--advertise-routes=10.10.0.10/32" # advertise self
|
||||
"--accept-routes=false" # true is equilivant to useRoutingFeatures = "client" (breaks shit)
|
||||
"--accept-dns=true" # explicitly allow resolved
|
||||
];
|
||||
extraUpFlags = [
|
||||
];
|
||||
};
|
||||
|
||||
# network config
|
||||
networking.firewall.trustedInterfaces = ["tailscale0"];
|
||||
networking.firewall.allowedUDPPorts = [config.services.tailscale.port];
|
||||
|
||||
# declare authkey secrets
|
||||
sops.secrets = {
|
||||
"tailscale_authkey" = {
|
||||
owner = "root";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
let
|
||||
service = "uptime-kuma";
|
||||
cfg = config.modules.services.${service};
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
@@ -36,6 +36,10 @@ in
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -60,46 +64,37 @@ in
|
||||
settings =
|
||||
{
|
||||
PORT = toString cfg.port;
|
||||
HOST = "0.0.0.0";
|
||||
};
|
||||
};
|
||||
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
# User = "${service}";
|
||||
# Group = "${service}";
|
||||
};
|
||||
|
||||
# # open firewall
|
||||
# networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
extraConfig = ''
|
||||
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
# # external reverse proxy entry
|
||||
# services.nginx.virtualHosts."uptime.blakedheld.xyz" = {
|
||||
# forceSSL = true;
|
||||
# sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
# sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
# locations."/" = {
|
||||
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
# };
|
||||
# };
|
||||
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
# group = "${service}";
|
||||
# };
|
||||
# };
|
||||
# add to glance
|
||||
homelab.glance.links.system = [{
|
||||
title = service;
|
||||
url = "https://${cfg.url}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
let
|
||||
service = "vaultwarden";
|
||||
cfg = config.modules.services.${service};
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
homelab = config.homelab;
|
||||
domain = "https://pass.blakedheld.xyz";
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
@@ -37,6 +37,10 @@ in
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -51,7 +55,7 @@ in
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = "${service}";
|
||||
group = service;
|
||||
extraGroups = [];
|
||||
};
|
||||
|
||||
@@ -84,25 +88,23 @@ in
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
# external reverse proxy entry
|
||||
services.nginx.virtualHosts."pass.blakedheld.xyz" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
serverAliases = [ "pass.${homelab.public_domain}" ];
|
||||
extraConfig = ''
|
||||
tls /etc/ssl/blakedheld.xyz.crt /etc/ssl/blakedheld.xyz.key
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port}
|
||||
'';
|
||||
};
|
||||
|
||||
# add to glance
|
||||
homelab.glance.links.services = [{
|
||||
title = service;
|
||||
url = "https://pass.${homelab.public_domain}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
sops.secrets = {
|
||||
"${service}_admin_token" = {
|
||||
owner = "${service}";
|
||||
@@ -111,6 +113,8 @@ in
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
109
modules/homelab/yacreader/default.nix
Normal file
109
modules/homelab/yacreader/default.nix
Normal file
@@ -0,0 +1,109 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
service = "yacreader";
|
||||
cfg = config.homelab.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.homelab;
|
||||
in
|
||||
{
|
||||
options.homelab.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 7102;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "manga.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = cfg.port;
|
||||
description = "set uid and pid of ${service} user (matches port by default)";
|
||||
};
|
||||
backup = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "enable backups for ${service}";
|
||||
};
|
||||
motd = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = service;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# install the binary
|
||||
environment.systemPackages = with pkgs; [ yacreader ];
|
||||
|
||||
# declare ${service} group
|
||||
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
|
||||
|
||||
# declare ${service} user
|
||||
users.users.${service} = {
|
||||
description = "${service} server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = service;
|
||||
extraGroups = [ "media" ];
|
||||
};
|
||||
|
||||
# enable the ${service} service
|
||||
systemd.services.${service} = {
|
||||
description = "${service} library server";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
User = service;
|
||||
Group = service;
|
||||
Restart = "always";
|
||||
RestartSec = "5s";
|
||||
Type = "simple";
|
||||
ExecStart = "${pkgs.yacreader}/bin/YACReaderLibraryServer start --port ${toString cfg.port}";
|
||||
WorkingDirectory = "/var/lib/yacreader";
|
||||
TimeoutStopSec = "20s";
|
||||
};
|
||||
};
|
||||
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# add to caddy for reverse proxy
|
||||
services.caddy.virtualHosts."${cfg.url}" = {
|
||||
extraConfig = ''
|
||||
tls ${sec."ssl_blakedheld_crt".path} ${sec."ssl_blakedheld_key".path}
|
||||
reverse_proxy 127.0.0.1:${toString cfg.port} {
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
# add to glance local service
|
||||
homelab.glance.links.mediastack = [{
|
||||
title = service;
|
||||
url = "https://${cfg.url}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:yac-reader"; }];
|
||||
|
||||
# add to backups
|
||||
homelab.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.modules.system.backups;
|
||||
borg = "${pkgs.borgbackup}/bin/borg";
|
||||
backup_paths = lib.unique config.modules.system.backups.paths;
|
||||
passwd_file = config.sops.secrets."borg_passwd".path;
|
||||
in
|
||||
{
|
||||
options.modules.system.backups = {
|
||||
enable = lib.mkEnableOption "enables backups with borg";
|
||||
paths = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.path;
|
||||
default = [];
|
||||
description = "list of directories to back up";
|
||||
};
|
||||
repo = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/holocron/borg";
|
||||
description = "borg repository path";
|
||||
};
|
||||
passphraseFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = passwd_file;
|
||||
description = "borg repository passphrase file";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf (cfg.enable && backup_paths != []) {
|
||||
|
||||
# systemd.tmpfiles.rules = [
|
||||
# "d ${cfg.repo} 0755 root root"
|
||||
# ];
|
||||
|
||||
systemd.services.backups = {
|
||||
description = "backup service with borg!";
|
||||
path = [ pkgs.borgbackup ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
EnvironmentFile = config.modules.system.backups.passphraseFile;
|
||||
# the actual script borg is using
|
||||
ExecStart = pkgs.writeShellScript "borg-backup" ''
|
||||
set -euo pipefail
|
||||
export BORG_PASSPHRASE="$(cat ${passwd_file})"
|
||||
export BORG_REPO="${cfg.repo}"
|
||||
timestamp="$(date +'%Y-%m-%dT%H:%M:%S')"
|
||||
|
||||
# Initialize repo if it doesn't exist
|
||||
if ! borg info "$BORG_REPO" >/dev/null 2>&1; then
|
||||
echo "init borg repo at $BORG_REPO"
|
||||
borg init --encryption=repokey "$BORG_REPO"
|
||||
fi
|
||||
|
||||
# Create backup
|
||||
echo "starting backup..."
|
||||
borg create \
|
||||
--verbose \
|
||||
--filter AME \
|
||||
--list \
|
||||
--stats \
|
||||
--show-rc \
|
||||
--compression lz4 \
|
||||
"$BORG_REPO::${toString config.networking.hostName}-$timestamp" \
|
||||
${lib.concatStringsSep " " cfg.paths}
|
||||
|
||||
# Prune old backups according to retention policy
|
||||
echo "Pruning old backups..."
|
||||
borg prune -v --list "$BORG_REPO" \
|
||||
--keep-daily=7 \
|
||||
--keep-weekly=52 \
|
||||
--keep-monthly=-1
|
||||
|
||||
echo "$timestamp - backup completed successfully."
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# create timer to run backups daily
|
||||
systemd.timers.backups = {
|
||||
description = "daily borg backup timer";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "daily";
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
|
||||
# install borg binary
|
||||
environment.systemPackages = [ pkgs.borgbackup ];
|
||||
|
||||
# declare secret for repo password
|
||||
sops.secrets = {
|
||||
"borg_passwd" = {
|
||||
owner = "root";
|
||||
group = "root";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
# add to modules
|
||||
# modules.system.backups.paths = lib.mkIf cfg.backups [ <path> ];
|
||||
72
modules/system/cifs_mounts/default.nix
Normal file
72
modules/system/cifs_mounts/default.nix
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
cfg = config.system.cifs_mounts;
|
||||
sec = config.sops.secrets;
|
||||
in {
|
||||
options.system.cifs_mounts = {
|
||||
enable = lib.mkEnableOption "enables mounting holocron fileshare on the client side";
|
||||
};
|
||||
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
cifs-utils
|
||||
];
|
||||
|
||||
fileSystems."/media/holocron/blake" = {
|
||||
device = "//10.10.0.10/users/blake";
|
||||
fsType = "cifs";
|
||||
options = [
|
||||
"x-systemd.automount"
|
||||
"noauto"
|
||||
"_netdev"
|
||||
"credentials=${sec."holocron_creds".path}"
|
||||
"uid=1000"
|
||||
"gid=1000"
|
||||
"file_mode=0664"
|
||||
"dir_mode=0775"
|
||||
];
|
||||
};
|
||||
fileSystems."/media/holocron/archives" = {
|
||||
device = "//10.10.0.10/archives";
|
||||
fsType = "cifs";
|
||||
options = [
|
||||
"x-systemd.automount"
|
||||
"noauto"
|
||||
"_netdev"
|
||||
"credentials=${sec."holocron_creds".path}"
|
||||
"uid=1000"
|
||||
"gid=1000"
|
||||
"file_mode=0664"
|
||||
"dir_mode=0775"
|
||||
];
|
||||
};
|
||||
fileSystems."/media/holocron/media" = {
|
||||
device = "//10.10.0.10/media";
|
||||
fsType = "cifs";
|
||||
options = [
|
||||
"x-systemd.automount"
|
||||
"noauto"
|
||||
"_netdev"
|
||||
"credentials=${sec."holocron_creds".path}"
|
||||
"uid=1000"
|
||||
"gid=1000"
|
||||
"file_mode=0664"
|
||||
"dir_mode=0775"
|
||||
];
|
||||
};
|
||||
# manage secrets with sops
|
||||
sops.secrets = {
|
||||
"holocron_creds" = {
|
||||
owner = "blake";
|
||||
group = "blake";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,26 +1,27 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./ssh.nix
|
||||
./backups.nix
|
||||
./sops.nix
|
||||
./docker.nix
|
||||
./tailscale.nix
|
||||
./vpns.nix
|
||||
./vpn-confinement.nix
|
||||
./syncthing.nix
|
||||
./nvidia.nix
|
||||
./ssh
|
||||
./sops
|
||||
./docker
|
||||
./podman
|
||||
./yubikey
|
||||
./tailscale
|
||||
./japanese
|
||||
./vpns
|
||||
./vpn-confinement
|
||||
./syncthing
|
||||
./graphics
|
||||
./flatpak
|
||||
./secure_boot
|
||||
./cifs_mounts
|
||||
./udiskie
|
||||
];
|
||||
|
||||
modules.system.ssh.enable = lib.mkDefault true;
|
||||
modules.system.backups.enable = lib.mkDefault true;
|
||||
modules.system.sops.enable = lib.mkDefault true;
|
||||
modules.system.docker.enable = lib.mkDefault false;
|
||||
modules.system.tailscale.enable = lib.mkDefault true;
|
||||
modules.system.vpns.enable = lib.mkDefault false;
|
||||
modules.system.vpn-confinement.enable = lib.mkDefault false;
|
||||
modules.system.syncthing.enable = lib.mkDefault false;
|
||||
modules.system.nvidia.enable = lib.mkDefault false;
|
||||
|
||||
system.ssh.enable = lib.mkDefault true;
|
||||
system.sops.enable = lib.mkDefault true;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.modules.system.docker;
|
||||
cfg = config.system.docker;
|
||||
in
|
||||
{
|
||||
options.modules.system.docker = {
|
||||
options.system.docker = {
|
||||
enable = lib.mkEnableOption "enables docker";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
virtualisation.docker = {
|
||||
enable = true;
|
||||
daemon.settings.features.cdi = true;
|
||||
rootless.daemon.settings.features.cdi = true;
|
||||
daemon.settings = {
|
||||
experimental = true;
|
||||
};
|
||||
19
modules/system/flatpak/default.nix
Normal file
19
modules/system/flatpak/default.nix
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
cfg = config.system.flatpak;
|
||||
in {
|
||||
options.system.flatpak = {
|
||||
enable = lib.mkEnableOption "enables nix-flatpak on nixos side";
|
||||
};
|
||||
|
||||
imports = [inputs.nix-flatpak.nixosModules.nix-flatpak];
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.flatpak.enable = true;
|
||||
};
|
||||
}
|
||||
89
modules/system/graphics/default.nix
Normal file
89
modules/system/graphics/default.nix
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
cfg = config.system.graphics;
|
||||
in {
|
||||
options.system.graphics = {
|
||||
enable = lib.mkEnableOption "enables nvidia";
|
||||
vendor = lib.mkOption {
|
||||
type = lib.types.enum ["intel" "amd" "nvidia"];
|
||||
default = "intel";
|
||||
description = ''
|
||||
set the vendor of your graphics device
|
||||
supported options are "intel" "amd" "nvidia"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable (lib.mkMerge [
|
||||
{
|
||||
hardware.graphics.enable = true;
|
||||
hardware.graphics.enable32Bit = true;
|
||||
}
|
||||
|
||||
(lib.mkIf (cfg.vendor == "intel") {
|
||||
services.xserver.videoDrivers = ["modesetting"];
|
||||
|
||||
# userspace tools
|
||||
environment.systemPackages = with pkgs; [
|
||||
intel-gpu-tools
|
||||
];
|
||||
|
||||
hardware.graphics.extraPackages = with pkgs; [
|
||||
# Required for modern Intel GPUs (Xe iGPU and ARC)
|
||||
intel-media-driver # VA-API (iHD) userspace
|
||||
vpl-gpu-rt # oneVPL (QSV) runtime
|
||||
|
||||
# Optional (compute / tooling):
|
||||
intel-compute-runtime # OpenCL (NEO) + Level Zero for Arc/Xe
|
||||
];
|
||||
|
||||
environment.sessionVariables = {
|
||||
LIBVA_DRIVER_NAME = "iHD"; # Prefer the modern iHD backend
|
||||
};
|
||||
})
|
||||
|
||||
(lib.mkIf (cfg.vendor == "amd") {
|
||||
boot.initrd.kernelModules = ["amdgpu"];
|
||||
services.xserver.videoDrivers = ["amdgpu"];
|
||||
|
||||
# userspace tools
|
||||
environment.systemPackages = with pkgs; [
|
||||
radeontop
|
||||
];
|
||||
|
||||
# enable amd vulkan (program will choose this or regular)
|
||||
hardware.graphics.extraPackages = with pkgs; [
|
||||
rocmPackages.clr.icd # enable open cl (compute framework like cuda)
|
||||
];
|
||||
# ^ but 32 bit
|
||||
hardware.graphics.extraPackages32 = with pkgs; [
|
||||
];
|
||||
|
||||
# make hip work (extension on cli.icd ^)
|
||||
systemd.tmpfiles.rules = [
|
||||
"L+ /opt/rocm/hip - - - - ${pkgs.rocmPackages.clr}"
|
||||
];
|
||||
})
|
||||
|
||||
(lib.mkIf (cfg.vendor == "nvidia") {
|
||||
boot.kernelModules = ["nvidia" "nvidia_modeset" "nvidia_uvm" "nvidia_drm"];
|
||||
services.xserver.videoDrivers = ["nvidia"];
|
||||
|
||||
# enable nvidia proprietary driver
|
||||
hardware.nvidia = {
|
||||
modesetting.enable = true; # required
|
||||
open = false; # use proprietary driver
|
||||
nvidiaSettings = true; # no shit
|
||||
powerManagement.enable = false; # can cause sleep issues
|
||||
package = config.boot.kernelPackages.nvidiaPackages.stable;
|
||||
};
|
||||
|
||||
# enable docker gpu passthrough
|
||||
hardware.nvidia-container-toolkit.enable = true;
|
||||
})
|
||||
]);
|
||||
}
|
||||
52
modules/system/japanese/default.nix
Normal file
52
modules/system/japanese/default.nix
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
cfg = config.system.japanese;
|
||||
in {
|
||||
options.system.japanese = {
|
||||
enable = lib.mkEnableOption "enables japanese tools";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# japanese input
|
||||
i18n.inputMethod = {
|
||||
enabled = "fcitx5";
|
||||
|
||||
fcitx5.addons = with pkgs; [
|
||||
fcitx5-mozc
|
||||
fcitx5-gtk
|
||||
fcitx5-qt
|
||||
];
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
fcitx5
|
||||
fcitx5-configtool
|
||||
];
|
||||
|
||||
# fonts for japanese
|
||||
fonts = {
|
||||
enableDefaultPackages = true;
|
||||
packages = with pkgs; [
|
||||
noto-fonts
|
||||
noto-fonts-cjk
|
||||
noto-fonts-emoji
|
||||
source-han-sans
|
||||
source-han-serif
|
||||
];
|
||||
|
||||
fontconfig = {
|
||||
defaultFonts = {
|
||||
serif = [ "Noto Serif CJK JP" ];
|
||||
sansSerif = [ "Noto Sans CJK JP" ];
|
||||
monospace = [ "Noto Sans Mono CJK JP" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.modules.system.nvidia;
|
||||
in
|
||||
{
|
||||
options.modules.system.nvidia = {
|
||||
enable = lib.mkEnableOption "enables nvidia";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
services.xserver.videoDrivers = [ "nvidia" ];
|
||||
boot.kernelModules = [ "nvidia" "nvidia_modeset" "nvidia_uvm" "nvidia_drm" ];
|
||||
# boot.kernelModules = [ "nvidia" ];
|
||||
|
||||
hardware.graphics = {
|
||||
enable = true;
|
||||
enable32Bit = true;
|
||||
};
|
||||
|
||||
# enable nvidia proprietary driver
|
||||
hardware.nvidia = {
|
||||
modesetting.enable = true; # required
|
||||
open = false; # use proprietary driver
|
||||
nvidiaSettings = true; # no shit
|
||||
powerManagement.enable = false; # can cause sleep issues
|
||||
package = config.boot.kernelPackages.nvidiaPackages.stable;
|
||||
};
|
||||
|
||||
# enable docker gpu passthrough
|
||||
hardware.nvidia-container-toolkit.enable = true;
|
||||
virtualisation.docker.daemon.settings.features.cdi = true;
|
||||
virtualisation.docker.rootless.daemon.settings.features.cdi = true;
|
||||
|
||||
};
|
||||
}
|
||||
29
modules/system/podman/default.nix
Normal file
29
modules/system/podman/default.nix
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
cfg = config.system.podman;
|
||||
in {
|
||||
options.system.podman = {
|
||||
enable = lib.mkEnableOption "enables podman";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# install the binary for compose
|
||||
environment.systemPackages = with pkgs; [podman-compose];
|
||||
|
||||
virtualisation = {
|
||||
oci-containers.backend = "podman";
|
||||
podman = {
|
||||
enable = true;
|
||||
dockerCompat = true;
|
||||
autoPrune.enable = true;
|
||||
defaultNetwork.settings = {
|
||||
dns_enabled = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
43
modules/system/secure_boot/default.nix
Normal file
43
modules/system/secure_boot/default.nix
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
cfg = config.system.secure_boot;
|
||||
in {
|
||||
options.system.secure_boot = {
|
||||
enable = lib.mkEnableOption "enables secureboot with lanzaboote";
|
||||
};
|
||||
|
||||
imports = [inputs.lanzaboote.nixosModules.lanzaboote];
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# install userspace secureboot tools
|
||||
environment.systemPackages = with pkgs; [
|
||||
sbctl
|
||||
e2fsprogs
|
||||
];
|
||||
|
||||
# force disable systemd-boot so lanzaboote can be used
|
||||
boot.loader.systemd-boot.enable = lib.mkForce false;
|
||||
|
||||
/*
|
||||
this uses the project lanzaboote for secureboot (extension on systemd)
|
||||
setup guide can be found here: https://github.com/nix-community/lanzaboote/blob/master/docs/QUICK_START.md
|
||||
tldr:
|
||||
while currently using systemd-boot
|
||||
generate keys with `nix-shell -p --run "sudo sbctl create-keys"`
|
||||
rebuild with this module enabled then check `sudo sbctl verify`
|
||||
reboot and enable secureboot setup mode in bios
|
||||
check that setup mode is enabled with `sudo sbctl status`
|
||||
enroll keys with `sudo sbctl enroll-keys` use the `--microsoft` flag to incude their keys for compatibality
|
||||
reboot (disable secureboot setup mode if not done automatically) then check secure boot status with `sudo bootctl status`
|
||||
*/
|
||||
boot.lanzaboote = {
|
||||
enable = true;
|
||||
pkiBundle = "/var/lib/sbctl";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,25 +1,27 @@
|
||||
{ pkgs, config, lib, inputs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.modules.system.sops;
|
||||
in
|
||||
{
|
||||
imports = [ inputs.sops-nix.nixosModules.sops ];
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}: let
|
||||
cfg = config.system.sops;
|
||||
in {
|
||||
imports = [inputs.sops-nix.nixosModules.sops];
|
||||
|
||||
options.modules.system.sops = {
|
||||
options.system.sops = {
|
||||
enable = lib.mkEnableOption "enables sops";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# enable and configure sops for secrets
|
||||
sops = {
|
||||
defaultSopsFile = ../../secrets/secrets.yaml;
|
||||
defaultSopsFile = ../../../secrets/secrets.yaml;
|
||||
defaultSopsFormat = "yaml";
|
||||
# age.keyFile = "/home/blake/.config/sops/age/keys.txt";
|
||||
age.keyFile = "/etc/sops/keys.txt";
|
||||
|
||||
secrets = {
|
||||
"blake_passwd" = lib.mkIf config.users.blake.enable {
|
||||
"blake_passwd" = {
|
||||
owner = "root";
|
||||
group = "root";
|
||||
neededForUsers = true;
|
||||
@@ -1,10 +1,10 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.modules.system.ssh;
|
||||
cfg = config.system.ssh;
|
||||
in
|
||||
{
|
||||
options.modules.system.ssh = {
|
||||
options.system.ssh = {
|
||||
enable = lib.mkEnableOption "enables ssh";
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ in
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings = {
|
||||
PasswordAuthentication = true;
|
||||
PasswordAuthentication = false;
|
||||
PermitRootLogin = "no";
|
||||
X11Forwarding = false;
|
||||
};
|
||||
@@ -1,38 +0,0 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.modules.system.syncthing;
|
||||
in
|
||||
{
|
||||
options.modules.system.syncthing = {
|
||||
enable = lib.mkEnableOption "enables syncthing";
|
||||
|
||||
# mode = lib.mkOption {
|
||||
# type = lib.types.enum [ "server" "client" ];
|
||||
# default = "client";
|
||||
# description = "whether syncthing should run as a client (user) or server (system-wide).";
|
||||
# };
|
||||
#
|
||||
# data_dir = lib.mkOption {
|
||||
# type = lib.types.str;
|
||||
# default = if cfg.mode == "server"
|
||||
# then "/var/lib/syncthing"
|
||||
# else "/home/blake/.local/state/syncthing";
|
||||
# description = "optional override for syncthing data directory.";
|
||||
# };
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# systemd.tmpfiles.rules = lib.optionals (cfg.mode == "server") ["d /var/lib/syncthing 0775 blake blake -"];
|
||||
|
||||
services.syncthing = {
|
||||
enable = true;
|
||||
# user = "blake";
|
||||
# group = "blake";
|
||||
# dataDir = "/var/lib/syncthing";
|
||||
guiAddress = "0.0.0.0:2222";
|
||||
# openDefaultPorts = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
95
modules/system/syncthing/default.nix
Normal file
95
modules/system/syncthing/default.nix
Normal file
@@ -0,0 +1,95 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
service = "syncthing";
|
||||
cfg = config.system.${service};
|
||||
sec = config.sops.secrets;
|
||||
in {
|
||||
options.system.${service} = {
|
||||
enable = lib.mkEnableOption "enables syncthing";
|
||||
host = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = config.networking.hostName;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.syncthing = {
|
||||
enable = true;
|
||||
user = "blake";
|
||||
group = "blake";
|
||||
guiAddress = "0.0.0.0:2222";
|
||||
openDefaultPorts = true;
|
||||
dataDir = "/home/blake/.config/syncthing";
|
||||
#extraFlags = ["--no-default-folder"];
|
||||
overrideFolders = false;
|
||||
overrideDevices = false;
|
||||
key = sec."${service}/${cfg.host}/key".path;
|
||||
cert = sec."${service}/${cfg.host}/cert".path;
|
||||
settings = {
|
||||
devices = {
|
||||
"snowbelle" = {id = "6WQ6ATA-5AT4RUM-NW67PAL-N62CPNV-ALRFG3P-5BDRO22-HWFC2Q4-5S5BDA5";};
|
||||
"lugia" = {id = "BKKSFPH-YEOVVAB-DTT7KK3-UDKAEJ2-PC6ECG7-Y76ZIVP-JRYMMXS-RTZYVQ3";};
|
||||
"zygarde" = {id = "UYLTF52-VVKUR7F-JN33HQZ-RFNWGL3-JER52LA-GZD2LPJ-QIFEE7K-MNMZRQ5";};
|
||||
"mew" = {id = "7ZC2NAS-QONQKAL-Z54NPMB-7TRXM6M-K7Z6PZD-FG4AI4H-V7SMFJN-JOYBHQO";};
|
||||
"yveltal" = {id = "ZVSQ4WJ-7OICYOZ-3ECES4X-KH37IPB-TKHKUJG-BSEGXVM-AHYY5C3-VKG44AX";};
|
||||
"CEN-IT-07" = {id = "DPYKA4Z-3PX7JB2-FBEOXXX-SC7TLT2-QC5P2IR-SXOPJGX-QO3DMII-5B7UCA4";};
|
||||
"CEN-IT-00007" = {id = "XBPXGYU-DUJSLDH-6BDNF4D-CO2COC3-N3FM6W5-IHZOJBM-Z2N77RI-IVAV5AH";};
|
||||
};
|
||||
folders = {
|
||||
"holocron" = {
|
||||
path = "/home/blake/holocron";
|
||||
devices = ["lugia" "zygarde" "mew" "yveltal" "CEN-IT-07" "CEN-IT-00007" "snowbelle"];
|
||||
id = "5voxg-c3he2";
|
||||
versioning = {
|
||||
type = "staggered";
|
||||
fsPath = "/home/blake/holocron/.stversions";
|
||||
params = {
|
||||
cleanInterval = "3600";
|
||||
maxAge = "0";
|
||||
};
|
||||
};
|
||||
ignorePerms = true;
|
||||
ignorePatterns = [
|
||||
"// syncthing"
|
||||
"/.versions"
|
||||
"/.versions/**"
|
||||
"/.stversions"
|
||||
"/.stversions/**"
|
||||
"// macos system junk"
|
||||
"(?d).DS_Store"
|
||||
"(?d).AppleDouble"
|
||||
"(?d).LSOverride"
|
||||
"(?d)Icon?"
|
||||
"(?d)._*"
|
||||
"(?d).Spotlight-V100"
|
||||
"(?d).Trashes"
|
||||
"(?d).fseventsd"
|
||||
"(?d).metadata_never_index"
|
||||
"(?d).com.apple.timemachine.donotpresent"
|
||||
"(?d).com.apple.*"
|
||||
"(?d)~*.tmp"
|
||||
];
|
||||
};
|
||||
};
|
||||
options = {
|
||||
urAccepted = -1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sops.secrets = {
|
||||
"${service}/${cfg.host}/key" = {
|
||||
owner = "blake";
|
||||
group = "blake";
|
||||
};
|
||||
"${service}/${cfg.host}/cert" = {
|
||||
owner = "blake";
|
||||
group = "blake";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.modules.system.tailscale;
|
||||
authkey_file = config.sops.secrets."tailscale_authkey".path;
|
||||
in
|
||||
{
|
||||
options.modules.system.tailscale = {
|
||||
enable = lib.mkEnableOption "enables tailscale";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
useRoutingFeatures = "both";
|
||||
authKeyFile = authkey_file;
|
||||
extraUpFlags = [
|
||||
"--accept-routes=false" # true is equilivant to useRoutingFeatures = "client" (breaks shit)
|
||||
"--accept-dns=true" # explicitly allow resolved
|
||||
];
|
||||
};
|
||||
|
||||
# declare authkey secrets
|
||||
sops.secrets = {
|
||||
"tailscale_authkey" = {
|
||||
owner = "root";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
39
modules/system/tailscale/default.nix
Normal file
39
modules/system/tailscale/default.nix
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
cfg = config.system.tailscale;
|
||||
authkey_file = config.sops.secrets."tailscale_authkey".path;
|
||||
in {
|
||||
options.system.tailscale = {
|
||||
enable = lib.mkEnableOption "enables tailscale";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
useRoutingFeatures = "both";
|
||||
#authKeyFile = authkey_file;
|
||||
extraSetFlags = [
|
||||
"--accept-routes=true" # true is equilivant to useRoutingFeatures = "client" (breaks shit)
|
||||
"--accept-dns=true" # explicitly allow resolved
|
||||
];
|
||||
};
|
||||
systemd.services.tailscaled = {
|
||||
after = [ "remote-fs.target" ]; # keep tailscale up until remote mounts are unmounted
|
||||
};
|
||||
|
||||
# network config
|
||||
networking.firewall.trustedInterfaces = ["tailscale0"];
|
||||
networking.firewall.allowedUDPPorts = [config.services.tailscale.port];
|
||||
|
||||
# declare authkey secrets
|
||||
sops.secrets = {
|
||||
"tailscale_authkey" = {
|
||||
owner = "root";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
16
modules/system/udiskie/default.nix
Normal file
16
modules/system/udiskie/default.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.system.udiskie;
|
||||
in {
|
||||
options.system.udiskie = {
|
||||
enable = lib.mkEnableOption "enable udiskie for automount on nixos side";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.udisks2.enable = true;
|
||||
};
|
||||
}
|
||||
@@ -1,10 +1,15 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.modules.system.vpn-confinement;
|
||||
in
|
||||
{
|
||||
options.modules.system.vpn-confinement = {
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}: let
|
||||
cfg = config.system.vpn-confinement;
|
||||
in {
|
||||
imports = [inputs.vpn-confinement.nixosModules.default];
|
||||
|
||||
options.system.vpn-confinement = {
|
||||
enable = lib.mkEnableOption "enables vpn-confinement";
|
||||
|
||||
# toggle for mullvad mexico w/ openvpn
|
||||
@@ -16,7 +21,6 @@ in
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# Define VPN network namespace
|
||||
vpnNamespaces.wgmex = {
|
||||
enable = true;
|
||||
@@ -25,17 +29,25 @@ in
|
||||
"10.0.0.0/8"
|
||||
];
|
||||
portMappings = [
|
||||
{ from = 7103; to = 7103; }
|
||||
{
|
||||
from = 7103;
|
||||
to = 7103;
|
||||
}
|
||||
];
|
||||
openVPNPorts = [
|
||||
{
|
||||
port = 51820;
|
||||
protocol = "both";
|
||||
}
|
||||
];
|
||||
openVPNPorts = [{
|
||||
port = 51820;
|
||||
protocol = "both";
|
||||
}];
|
||||
};
|
||||
|
||||
# secrets only if VPN is enabled
|
||||
sops.secrets = {
|
||||
"vpncon_mex_config" = { owner = "root"; group = "root"; };
|
||||
"vpncon_mex_config" = {
|
||||
owner = "root";
|
||||
group = "root";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.modules.system.vpns;
|
||||
cfg = config.system.vpns;
|
||||
in
|
||||
{
|
||||
options.modules.system.vpns = {
|
||||
options.system.vpns = {
|
||||
enable = lib.mkEnableOption "enables vpns";
|
||||
|
||||
# toggle for pia mexico w/ openvpn
|
||||
79
modules/system/yubikey/default.nix
Normal file
79
modules/system/yubikey/default.nix
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
/*
|
||||
# to enroll a yubikey with pam (works like .ssh/known_hosts)
|
||||
nix-shell -p pam_u2f
|
||||
mkdir -p ~/.config/Yubico
|
||||
pamu2fcfg > ~/.config/Yubico/u2f_keys
|
||||
pamu2fcfg -n >> ~/.config/Yubico/u2f_keys (to add additional yubikeys)
|
||||
|
||||
# to test auth with pam
|
||||
nix-shell -p pamtester
|
||||
pamtester login <username> authenticate
|
||||
pamtester sudo <username> authenticate
|
||||
|
||||
# to enroll yubikey with luks
|
||||
`sudo systemd-cryptenroll --fido2-device=auto /dev/<disk>`
|
||||
*/
|
||||
let
|
||||
service = "yubikey";
|
||||
cfg = config.system.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.homelab;
|
||||
in {
|
||||
options.system.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
mode = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "u2f";
|
||||
description = "weather to run pam in u2f or challenge-response)";
|
||||
};
|
||||
lock_on_remove = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "enable automatic locking of device upon removal of yubikey";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
yubikey-personalization
|
||||
yubikey-manager
|
||||
];
|
||||
|
||||
# enable smartcard
|
||||
services.pcscd.enable = true;
|
||||
|
||||
# enables it for everything
|
||||
security.pam.u2f = lib.mkIf (cfg.mode == "u2f") {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
# selectivlt edit what u2f is enabled for
|
||||
security.pam.services = lib.mkIf (cfg.mode == "u2f") {
|
||||
#login.u2fAuth = true;
|
||||
#sudo.u2fAuth = true;
|
||||
};
|
||||
|
||||
security.pam.yubico = lib.mkIf (cfg.mode == "challenge-response") {
|
||||
enable = true;
|
||||
debug = true;
|
||||
mode = "challenge-response";
|
||||
id = ["<placeholder>"];
|
||||
};
|
||||
|
||||
services.udev.extraRules = lib.mkIf (cfg.lock_on_remove == true) ''
|
||||
ACTION=="remove",\
|
||||
ENV{ID_BUS}=="usb",\
|
||||
ENV{ID_MODEL_ID}=="0407",\
|
||||
ENV{ID_VENDOR_ID}=="1050",\
|
||||
ENV{ID_VENDOR}=="Yubico",\
|
||||
RUN+="${pkgs.systemd}/bin/loginctl lock-sessions"
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -1,29 +1,60 @@
|
||||
#ENC[AES256_GCM,data:b7E2U/jRfXEKulR/Pba0L4Aucy3MSUPj2BU=,iv:+KC+vfB2z2AIiPr5uIC4Pbfgc44GOs6SVRZW1v80hUE=,tag:kkn3UfJwdgxYERmfiMUmjw==,type:comment]
|
||||
blake_passwd: ENC[AES256_GCM,data:AfFql6/ghGhCDLOb4+QuAsDznz4hC4ilxZYCIH2sgBWX9tWXsUOgFw1k7CIhDoXIehz6YlTy0czekXPCqHL5gmIKRQTowU4svocw/Bl/Qz5CQ58RASB6YpnzOKTrwX7HCnu/ghpdMrcy2A==,iv:hMAkLcHjP0hiyCY4rhMU0Ae7jdYPa6MffEd2WGolbEo=,tag:p/6xmD8Te1RnFkp0zWw+ew==,type:str]
|
||||
#ENC[AES256_GCM,data:0HBVS2AYQ2VZXY4EbMLwiSjRNyWZ57bf,iv:20SLWXpbRTLk76g5mFrhg1Z9Qasv3NoSJbK/FOiIgtk=,tag:DbUffQwrDqzy2QO64uoUeg==,type:comment]
|
||||
klefki_auth_map: ENC[AES256_GCM,data:u8OBLtT/,iv:THW21BDyhyFIjcwixsAnaAODofxbuQZnpdgt9HGdDIg=,tag:zUvbOO8tLAnxdeMcWpvsdg==,type:str]
|
||||
#ENC[AES256_GCM,data:ZxHtUSuOy19M0EKoT5xltFiqRg==,iv:72PJL2eG68VC4wiJFo6wL0l7AaDIsge8l/D/ZlLOWWA=,tag:Q16ztObK2AnbCCS5mRgjtA==,type:comment]
|
||||
tailscale_authkey: ENC[AES256_GCM,data:SU0k3asrJd+WZ86VbC4w8TDJp+MqsbyagrzCfDcgTzO5yvBjpWAKbJ7A+VxgQvdu4+S2jMYbdrONPp3YbQ==,iv:VMYmGVk5GpUQApKKQYhdOw/cYCXrXxEZJJwHfQL4MjQ=,tag:7ruaoCDxuFQ7tE/JLJ37Xw==,type:str]
|
||||
#ENC[AES256_GCM,data:bEbCic+ZDAA5ieNedCbiVbJrse17,iv:UwRYlis6NPB/RUcv+YnPxrGdbIcF4hrNiZt19YvWZNQ=,tag:m6PVlzPNnahX7X7KzMUj7A==,type:comment]
|
||||
borg_passwd: ENC[AES256_GCM,data:XOMJtr+DRs7xn5Iclc49iTzK9cFJyc/fSXJjhdKa9jdN,iv:YB8z7zNYjh6NpSxQb1TfPxAYUdzThdVfNZIe6tO5grA=,tag:bO6kZ3cLJDL4IQoWmGvRdg==,type:str]
|
||||
#ENC[AES256_GCM,data:lS++LQwlDVP0aYcdaaudBkKxNB3P3UBE,iv:UqGcXcX/Jvf60o409Cxj7VJCDh63uUxy45PuZbHK2l8=,tag:OXdMwuJwdN8DQaLXACpcRA==,type:comment]
|
||||
ssl_blakedheld_crt: ENC[AES256_GCM,data:EvImZ3y5lrmD2P2Cehd4yAyranHRBkejbnad1qmH9KbKeLNFsTcqW4L3NDYydbKurWCWYa/jJAL/BwT2xmUhwdFlarCiTFGnLXxMFhd6Tq+5if8r6BfSLCCS4IXcXnXP4k96ZR2fdD+lnDN1ljb7pI5hekz+HoVwBoLVVrfvQvqj72Kr5rfm5ttLN21yfi5DbgfX7n9AO6X32wzpIAXxQaYIFdPpm12WMpEX+zfxjjcpOR+Xv8npbs4AlopFaZ1N8d2AlM19ChwTZm/Zmq3BQt5Z2bhGsQD/s357F5ofmSfQ8BGXdeUguLj0BtZw6zrxQlySmJMNroBxrQresE7cdeoeEagZXXxJd0S64HcvonV3jjp4s5817YWLxGD8rws2fH9Ci91DEMlI+4/U9Jb/fWz7nxXSMekpNkGRrKPm6L+3/dxpvbkv9UyQi3OVTcx642WYyFaZnP6J6qcbH+itwfuPE1Fu+fe9IlIbAopDrvau0CGisU4FhX+NYMEmFu6N/+unFyMpj9qsqS8UFAXfgvSPRQTULqcaaOK7MRVh3JGOfR9qnbbPjt+aJRrkTW7q/8OWcqvxLgPnZlpPkvsg9PjcZmwxV4ooh3FC85vsrEc8tEqzzbrSWrJRXpL2ZJxsO2AfpHICexyjJium2Dm0hfR9EP5b4ltzeqg0rBeczec7/Tckafy3cGk1jCkPoDYN857Kl6oHi/9TduYvqReKJTV8dLB256M3TBeAYNQypCGceemPtcYrAgG+yMC8tnR57k5QjXsCmT69fAlPibvZdHUxh6Hqlx9sj5WU1NhGRCQsAj362UzGsEcVoF5/zcXVf4i2yCT+axNRyK/JU4JW6GaldJQ8PV+ay5RhNHtErgP18IaY7RjwTA0PVd5G839qbHZlJXiO/EvqrVpuy7UthQlvN+9Y+YM5jQMi64ahEcdWXYSjhqnbh6cZ3xfOXK0egTpy1/xG+FXpFMIvqK2gPZrB1B1Wc0XSvpOBFxTRaWlfDYeVwDtw9QCbM/7jhD9jaopdhMoPH5J/guLxMhRtRw0CJUemnTX1KJ8dGpvDfaCdj+I7ptb7vQ0wAfU/ferpfLX07j6g8MMa4p9jzI9BtXyd9OEOtyFfV5X5Mls9FfhmNi4+ES8LmawsLiyptKKUA7db4GZ4CLJqeR3khh/sej/ESgeXTfLXlOQbIALOdfrPo1t0fDRlW0H42FhmyHeily7KCBFS/pcziTVkM1YPrfyCXH6p8hVBNJ/JYWlEoS5qAxfcXP6cS+/3L16Y5XEP2Aea02qhim02C3qIX+6CQAc5QmuMfl+itnmWdTdwpPzEwVExoUQLCNTU610mkkKtSdMe3aLzmMrfQskEwjMhfXCwVsO+HWugi7im5GAezs+3wuK8j4GYai2sMerKesl4mJXIZWTLJqG8Vj7yKMHJ5mCiOPPYQ3AL++s916kRu3gO1evxfzul7ndh1GypVbX66QZotV9/MN4wSGxw/RCRscZrM+XzmlrhiKT3uezF9KKiw9J1F3zDrtcjmIqll2WVn+U5uzPYEj6TeC5ty/q3OdhYY58U7qe84Pj5zq72bLegBMMK8sG685ylPWD5l79+3D+JGCbjRTwu2oNaIdy9wem0rl56YX+kcGQC2IQcWXcIDASVhAQjguTU/mmMzLNZb3effZ4ZNAmnWgra4hnjEqChuxKlEM7blm057K2G7HP/j82Xy9VsBOTTc0Q2KJZpdb9t+vfDUNJtNdog5w5SnObRqIkUdDrFx04tGUDp/8eqqSHZWZOLq+G4jzarn6YhvNpEote89cARCqdZGhREJFi+zeFWhguasltfSjXhQrYc2p46GlV4USKuWiyIUny5I5/HR2/0Ci5vK2wh1jZ+JC53sKxA3MHg5Udyqkt8tLK+5X5NL6F9EBCRSzCqXDCds6mGu26X5Qt10UZdLTxJs3M0x3bSbN1qJUnv6K0iKgAVw09jeXzKcVXbmFQUDJoVEErIcg1Oed8EwfJu274rF8Nfxh+29LE0CO3q/pR0P91eiUKLKK6oy9tpGnGrnRViAZS3LvVsNVdlWBSEm6WSiwM97hDH3CFqwUHPYzM830DZS6bfIL0OfT9lH5a1f7+Uywi3O3EaJaR0lr5esGJImOQG02yjCvqmdS+igFMKzdAyxQO1WSXDwHXZGTYZbhqyGYK+zc89lKdBaXiC91POQIiz5/xciXqb77YnXKeg4g==,iv:VQIqXN3r7DOVREX4fP5/OR8xECXLjYKfhd6XP3ghMaY=,tag:eVdyxrw/w5zBGxV6Tai2Pg==,type:str]
|
||||
#ENC[AES256_GCM,data:3G8XqUKua1QgUxv2YJkW0fDnQPX7+v8GDC9BHg==,iv:BkESkMmMalgesy9why9eaKkOOvwSsN2EhNCRRRmZNtA=,tag:x95zt2B2M19BkzeMpAlXIg==,type:comment]
|
||||
ssl_blakedheld_key: ENC[AES256_GCM,data:Jhb2yiIYlfJ8mewzohseWQYZ2pEYy8x2c9B6OH/P46roY2cljRJ3xb3e59cEkAoTvpuv8BE+fN94Zr+1BFjzsDrpf9YsaIXkH1j3wiAEd06G//KduSrJkNz6v4IxGHfASRCUE45xASvGXBWk24lUlOcsPQY7olncjdpqNQ5gxKGv1fYHfeFVgQkSZbhY87uT5DvuN2G1st7LX6cU5Fvs8GlMAKa5RhCKH1rE88wA3uNfaW0ffobmfQoUMhNlXfuIeOMw9HdYfpVxYCu5qlCLsqV/Upux8QGpfSdUnPUnHUAjdHpsU859cQjFGKaw0fpkUhLxh06z0UDUQ9000DDVYBfzmGVasSjwCJO0J1MbaZZy7Wv+XSgozl9FWeYEO+R7YN6R4K/rE2/HzxVVTmufIcinOH3oMPKrmvKFSNNCEIsDWqcGLtj5QFYxuK12Ra+rudJYPg6JnN3MYQ4W/Tlyy41zlwnayAp2xGowUJvfbxWkdsKtnY33NqRhPpM3vNWTgT+4t4HgikX1vaN5Cefre14f4wgn7N+CGCdsxrXMIfj5KL9GmdrWDtWFlkWlJtKti4AvJi5ud7iLhj31BrDRnjlNtPKMtC/YgSvVg0QxinlBAxtrovcujkd+LjNs7TvM3skUnXzU902gv+mGBce1WnywUYcUj1SLEo6qiimgiHSrk9zjLxoREWXpYILGTDY39pFQ8XnSFGaxTqcp/KvMiYlJO67qiQcKJscWi40HIkxL/tRiYoUKhGUnE3CTbvhfbDfjJkXr4vu5a26eZxDqi6xnvwF20fq0LgR9TN9VRL6v1/B+AH0O9uFceJSnKamq+N3bRFllpqkbZr7csQLRqb2UTbb03JOm1+y0dz7nJR7N4f07YmLPob8yYHjMlL9ge1kP9RWCVl9hL8hrzSavb3igzP841ckTyGX5u6v3HLssnSZb1XkBiv787/j+X/FZq7ojZu3cNBWQ+YnyRKS3RXFLDvrjGjfHhlO2loU2t4hj4YE5JLqxACLwSMcZP7ReJTp+qURLP1N157GiMItJAbKUAI8txtBV0ROcnBh8JdyYXZa5qqcP3FQrfB0HRWSWC3DWXlal44kW2tMfQdz/+pZwYhHR7L+1JpuLgFJ0N1iU3NePZDdXBY/MffRkz8JhsDCSK0yLa8hkshdIvrXB/gxS4pKbwdLUUkks3RZsLB++KOFimbC0OSkVVtsTtvvpIs3rOMHq1NDiFQghCAgjkDTq/t5wl7WNyHq+F8TpeBfTqB+so1RVJ36Ibv6BWN7+owlrLuYg+SPjW7I1EMm1wECvb+Sj9Y9WP0suexD/uqZkT0ku4goAttF2b0AU1QRtyrEPdV4fD5OtNqoEDWV3auXov0g6uJkva4Lv6KlJy3EFjOy3AvTWR3WX5+8bMUcKxa4Ehp348pfiaOBF46lMMIcWZWl5IIMQfrY7IkMuDxsjrbJy2FxQ0cPNTfrGlz/7BnqosCF2BFmIv7QuRC1HNsQn5a80IoHhGjlXXsgs+NN3Q1blDvQJBSETuB+bStoBpv5A9Ly6LpcQthy7r68815824YxJ+IWTSi3iUHFLdT2d+3s2UnLdLXaqrMt6bgCWUL/4vooYIO/GHU8/kFIbCKZ9kxixYOeMrv9caC+5iIDg2SjcR6XhvK0ZiDE09bkTD0p0/IX+xbYX2h6uVIgEcAdkLDGCKOl5V9aMSke/dhYQkbjSLj0wyWaLkRevSzKhJ2AYVOAche0D4UDTUFHG9r/pS0N8CG52SbsgR1JZyIMl4ja5kNZQJBA17N/YaIBNHgJhI5x/z6tWOSsKqW1M/U0QLCBkTFfl6KUk/WsgKZXqL6fFiOd02dDfSSyRZSqhELMD2oIjlz9soSDDPFaSzGbQS9lAR43dBuSeQHswymvUEAouYaoqf0mBEQ+BCS1oiqHOZRycFubRu1O8gu6snTeXiDwtqu/nWkcQ/s9SFpYI96loQqsYeC6kle4aMlo9/+Pb97zUmSc6BpimzIdrIk6pS9H/QrE7GTrOAjDEtqhbvwhuWafKTfMXA8pfcWTP3SwiVZI5DLxzOQcObDkUtUFozJpa5Ln8U6GNxFxnDXiiGj1VV87zyu8M6g9Hj9yNrV8A4SW3FtfhIc7A39U6A5GLmYWN6EnaLDoLKyOgJqUJIqLtzcve+TuT1tTbvbsKAl43Tr3UkTpz8t4FIaBW5GcOVuZ33kZyzJ/SWH5/N+msmEIWOxGzISvFdhooZEd2z+PFMuRo547tyTBOww37HZkaDSCnHKpZ,iv:T1sDL6oXItF2spTr4cbAjJ8WFdSHVN8cInElC5ZC2NM=,tag:OVJiimHRgHi4lJTELjx0iA==,type:str]
|
||||
#ENC[AES256_GCM,data:ztRwuY0mTMDmwV5HqVR7Dmc+dCWcrVRtWZGEL1abE/WUcA==,iv:mmaWfHRiENJUGNhyUBFo1z7PdzVPH1OUZrVhkce6KV0=,tag:GKEvT0qkzTtimQXDueKPdw==,type:comment]
|
||||
holocron_creds: ENC[AES256_GCM,data:2QXtXrN5w0UFn70GZOsYFPdtPwjLcuUdtkEam5aZ83N6LEDqPWJi,iv:kUS9pq5CX19vqHumc6QjY+Xpd4N+Ge7oCcQYtMFh+WM=,tag:IUA1ZVThF91EdHrwmS624g==,type:str]
|
||||
#ENC[AES256_GCM,data:VdbMrwGKUKNJHw==,iv:OLwBh6KQXR/H8eRgp/hH8k3QfIkK/ydL735kx/dpc8E=,tag:N+v+ym6RMbvW4IckbiLK8Q==,type:comment]
|
||||
syncthing:
|
||||
gui_passwd: ENC[AES256_GCM,data:CicGIe5dT8lJVchCcE4wg3E8va3RYR8d53MISkE=,iv:8ziDDyQvU8ABaKKwYlcHmvm8Qybk4G+q5F0Ghqluu9w=,tag:YlyNPE04KD3detL1QUTrgQ==,type:str]
|
||||
snowbelle:
|
||||
key: ENC[AES256_GCM,data:MrAc4RXi6h4WOboZgBRjggPNGUrQwM1Vu5N5aPYBxeBZPi2ut8OApWcA9apWzYZNQTFF5QCtCpG9W+1CLJRG701PRK1Wf01r5SDI8aIXkgc2MjXuzS/y/WIqWoPK1nmtjxTYqaDR68II2tc/P7hgtf2EwYPV2JP6v6cCihADOKvXW1pBxi9kMjZGcbY54IyUrOdNauDvaZRgCSP7xtg8aWf1FlmJbiQgMW2lK/f+8rc/3OGS+ieFt35h29Khl4rhuYGB6rgTwvDaWa9g60rPzVcg6tKw+Unef99pA+CQnhVJJIejKlC07pCdqdjCUc+w0oQ69cVoucWeHqlq3xA7IvYIGi9K+OFCLmsoqjMe/wUSC/r2s/nnqbXsgVx9j8j0,iv:2FoZwwzKUky02Z34KRVP/jPhOMXnLZh841+4lybsbCY=,tag:ZL5qh3OcFjiWgqtmTCUFkw==,type:str]
|
||||
cert: ENC[AES256_GCM,data:tvJX88ounzIzKmKcvEe0UtHrq51DMAIHGVZE2StqfNkn2QP+Er/geEh0wwmP9Q8+XBBjDT6oSAlWLjq6Tc1yYWSKju6Ig8GEJNDHL2UMVniBFzroSlO9hqZzbbNe1896WiwhhypvBoves7STTE7tJ2+Hzyss1BCYjcI+evGliJslq2nqxroMxIwBXfuDtxcTAeJ+SiKonY7W29NA05P1zYm6o6Td09VUS0cYWx2VUoP/8PMpeWLNciaHz8TjUeZ2Qob3pcNielu/VDqbunLvbFapqdV0hkl8gxgho+MmkC3+DXp/JDnG+vRm603wxqDECh6CNYc0CEXvM0/8gSXt6AkjATv6tBV98VeLknZkqVjBahtxrZuwquMuQbh1jD53RgsvnwB39FyFHZw29DGcUD0A7hIGnqSYVc2TXW+sgRxzXVFYsVrt1sWrYa2DpZT5zaFbps0dd194/j0SHOdf3p/4HF0GncWfTWLT89F/oAyJLio4X7yjES/DljgvmsrX0LdHnAYYAKDCWhZml3wSHBJ7Uvj1KiH2asxXkdiTPf8wulmwT+01hhBoX3QCkVYkdJpDbVddjLkwpLNyJATHctyuqzOdEMR4w5usTv9vKcgkMtbmxfWajb4lhjCpuaavkDUoI5h6eB8veXbZqAuX24bCvsLBWOVkg4qt1GGRqHx7+lfFanzMGyYYC/ufAXWD6eOOVsCjHJbHJoI16zq0HkfNpr30w+gO8hOyKgBP64anElzT3NB1sDi2GWxhSUKTDZ3rLsagPhZb3l3/u5SMf6lLWsY6IyFgPcVgY1snSOtd+PO9z9ipfyQZn4kKCtkNPPof8T58Qi7CP4KmVvbJsF67BH26SFclQLaJv5RO7e936vNwLrVhbyaclM0Vz6Y8wJvG4vW1Z4qPt6kP80NEATdrfwAr9nvZkb5rHqRWdxqIWSD5as+HPFzM/Mv0sBZ+B+CnsSv1btdB/iLacd032PGKXfZLxqGGOL1HIjM+QjSjaBTqrYcMke3GvnVfIujfdtcn9tOqGK+QYPS1CTYxWznmHloL2/WYwBY=,iv:qlIfrPxz7NvjkIXSkumfKvN0O1qq1S0T5j+37L8aReU=,tag:Qg8CYcDY/MaLWwNY566wBQ==,type:str]
|
||||
yveltal:
|
||||
key: ENC[AES256_GCM,data:unUnEeDhCqHUZCJtGCbj5rmrLx+9GiUTl75K3HdkI94YfCLNYCBACYu2v/7FbNIEsjVoQEA5/gKEcUHzVq6LaHM2w9GSo6tjkegdzTUgbHBJf4ssJ38z5rQkMc7tbzsA0NUHBPklz1eyjkW96HQPD0REcwA3CIc=,iv:PZ7vfhIpwPpMz4P04bewNhRuahmpukasgYb8fL/EJBE=,tag:G1HDyPAVSdm/fwqTXTT3PQ==,type:str]
|
||||
cert: ENC[AES256_GCM,data:yLq2dNjdMiRj4reyZWsSqZ+1rw4DTwKBZoQHzeKb8YBn63ub4TZPlnOjSTt2DwOQwrJDNhsaeGscZ6J7rLxF/rtH6YnR8XxQuOu/NNIcZ4m9EqhsXyznSx4Q+0gamUXujRgGRVH5FNrfiFoqP3VuNghoX+NLxfX0BcVruEjbmLUWVVzY0yS0ufzxegM8WFAxuKhcr1NlhBU65TxKUtbj4vcByzWHkfLGIb5ICnGeF/p9/FvpFSavw3nLdybDLJ6EKEeaxy6t984fkuotAvk54kLbF4yt0q5mjDxy0U6xtn1hg3x03IRAPjKDRdpDmzYf4XxykEb74JX9q2zjUhb2l1ORWcZu/uKvEiuZWDJRmJ4ypOiyZOCqTvY6s2iDhEjmMKxlNr2mhuz9Hn6b3KoQjePIEd1eS/VEmo09pEuUlhlAEziVcdnpeRyWlN2xpv4ps90gLxJ1Mj9nAZwRqFOQl0V4N5OBHEqMBE1nQv4afMpGX5QF2UotTpNfka+LdKwc1iHHtpHZYmG1/LVwz3jDv4XnVLdDWojFA/8eJIWVq1BsUTYSy+Q27bsoTX4iL0Y/OAHRzXZTqYc4aiAWJoaNTNgmagZ9C03SA6qePlGe/5azI3f54rC2m1/JDUtYW3IABHSFUaVnTdWnD4GDNSYRJIknyUwXR4sE3pRD979prmgtepOyETOAVgEeUVKz1leJZ2HyyhjFU41TL0IN/sl+YPD9bC3Nmw7OsxMFGPC4l5vn64DVp7HHRSKyJvZ5fG8s4nSzyZAKomkocOpKHEuQPyyerZpL1lne/m2B/y7/W2ouAGxcawZOSU6f74mn5wM=,iv:Ggag5SNUFkhMWS0u1kwkD5tGjiMv4i041bCESl5XOdc=,tag:pPISz0eBWzHcPHsC8dVG3g==,type:str]
|
||||
mew:
|
||||
key: ENC[AES256_GCM,data:8i2thp667lKEXR0cIaEOLHPXWlhFS38FvbtHgni3i0dTBx9DYtJbGogNaWMlA8r2HzBHkG3Jg0nJs7IOrJWugnGLNLbvhdsxBswEndOBaed4vq+SSN6ssxdjjyFd38wlIZNZsytjPFhyRgDLJ+0rftcIQXPjBhU=,iv:IZ3zWD/ZpalOzSAJQubo/y4LcEzHMEcl+C4GB3Q/nac=,tag:IKEwIkuvHE6qrUoCEqI2Ug==,type:str]
|
||||
cert: ENC[AES256_GCM,data:uvNZYmQnexXTr/Sz7vLQIJK93MmsoiJfCAL8/rLVQH0D+1nVaM472lqR5pP0qhLKuYhFUESxhAotVtqLpOWK1MfAxuk2RHv8mvbtIJkheRmsIWw7dAAABIkmgnelI03P2Tk2129I95vMM1lybu4W6m9VslwJF8X/4rCxshdbuz9mcjwxBpUEDr1V76DO3bgQUuPwizx17ON8gNd+NtRqPPaXlGrfLCFv1Fib3YFd7+WRkERki9ZO7Q0quY75G4Jseb28QaiM2BT7jfECJo4x7rMePMV303sIrF9paaUKTuSiCUsamLsi5Hwr907y2lHB9Gocwio7tnSRSRhHHcWLI8dQktzW7Flqs8+MZGZ1oJBQO7kQDefF1q4mddADimoqD9F1NsOiOmqqZRRB37alLGmRjeYBIlA6q/FgN9BAj9h0cG3oN1MUXPRGzDfggg5TLjBM2FbG/N3xgncZ2AzTPOcLtrtc0I2PYk3FFxgzpHWnjS2t7CQo/JxqdXbdy9nTHIqbrnKIQ/FtS7/p+cgQcU815UMsJm3qP+hPLCyNuziYq3Vt/X7C3eTnrqemXjEeJ/SJxb+Oul5GS1OL14dNsJllFNuj33Zep/hyQvHnf/HW7kXAfDqIP9zn85EFriAZEuaKwbHB2pkvbWKFxrpXJFhjnPFDKxGOjAmsLmil4paFKdt5hK7rp0mmoIMN+mMFbYx333llik0qk27yYTQwOR3eeCGqHODUU+izUT8NuQBezyxsEmEYu/YBcpatcYylwKgIFcC058oltsxlbxRg5Rrdk5FOqj7Uui0qwFXvYesz6Tiq/rGmcOPlcE5xw14=,iv:LePpzWGDTV1ONwt1uHUptMW1dO1SwwUKrtCEerc/DEc=,tag:a5B/7hmIxvLXU90Stcq7zA==,type:str]
|
||||
#ENC[AES256_GCM,data:A0ITyGOGMIoyVOcn5JOi1RAtqUM=,iv:+wWpmFbeLiX/Ae53pj0QmnYY3MEzOMib4cqbePUKtGI=,tag:JHXvrN4bOH+oD3Q70pUuew==,type:comment]
|
||||
pia_auth: ENC[AES256_GCM,data:rwAu4f5XVS4v4FCLj2zXAegIZeRPLIzUVv6TCrdfg9RGSDJYHgVAX0aFXCBQsDQju9RDycXmc9Id8IuyYN8=,iv:kEA4ADQyUI+zlQoZOKi81dw5BLE1oesqhVf6bfiLgB4=,tag:VHT2uPNW27F3KRM7ZhWdCw==,type:str]
|
||||
#ENC[AES256_GCM,data:7y1mtYNfbsagqtr66kOx2rinneEW3EZaCJIXzK0qjLX36g==,iv:8ozXuBYirLbKd8sCln2xv/WjhTojY85xU0cL5NVeMlQ=,tag:mclz0GfQ9j2EGWMiQ62QmA==,type:comment]
|
||||
openvpn_pia_mexico_config: ENC[AES256_GCM,data:59HQ3OZ0QKq92jI=,iv:DZTNvfi6kLXG7dsNkPcXUmXhAG2UdPZBy/L9eWNmRdE=,tag:ndxDDQNL2z1fjxFfU2VRwQ==,type:str]
|
||||
#ENC[AES256_GCM,data:mbIgMJBhL8nWJzl8q2dFL8XtO1Xa1Q==,iv:caYHYp1boK9wRgCcQe40HTWT/HxAIvYe+HyaruI53Vc=,tag:S6wowhAHObEcs7z8FimZ1g==,type:comment]
|
||||
wg_mex_key: ENC[AES256_GCM,data:vxDXixo6X6D33+p21L4hB0/yCH+TvMHZl991BkRsE/jdz7rzZuJF+zI7h+Q=,iv:8WR+feHXNUcat8DB2wY7wpos+P7TzgRF7rFD0fYosjY=,tag:p9b9ck0/VZjyLxtHut3n5Q==,type:str]
|
||||
#ENC[AES256_GCM,data:3ATkokBKeOp97uORzaePROrKKfG94ic=,iv:MNJRh6Vrso1heqNUJc0M4xGNcMLGwcF9IzoiQ5+SS+g=,tag:xj8Actwkirvq4GE+Ly1M9w==,type:comment]
|
||||
vpncon_mex_config: ENC[AES256_GCM,data:4i356X97sBoRliskmh5ewcEwZHkpo37IhPcemKVdWJgWFWtA+AhTeEo4KQ3dRA1H/n8VjVX7CKZKPDxpmHfcUlnTLT0agtOjjyjf60kWoL8noJqcbDB4wGiYT910rPToVnYMFk0H2lerYp+/n2bhg8BHxn++VlPOOZsgla4El+FNXUqhScpAawySPSF36ocdRJ3r3DuflIhnTBXxSZukMf9Ux1uaFldSG7KasCQlStKy9O2Odd2AvAuGXOHch5KecRPT3WnonQ8oDJpuxbeaosLmtJKHL9oeXHPId2Unc1GNoOpnDC3Y/xGnrPb9WFXWYOSQ/1A3mNKwnVq0FEhluVbqodES4PVIlCS0koiQJq15P15G2z0jO+OhAQrRI5vn3Fki5A==,iv:tQvTpzhl7F7niigAXl61FMHbg6QqI2R7yGD/C2lwOR4=,tag:c+CVLd6lGrAfm38pFXOXTw==,type:str]
|
||||
#ENC[AES256_GCM,data:CO5nrcDbgymnEmCvuTexOBEMncuNM5lQ,iv:6HrxqSN6e7ODuz09MIFgPbIqDCKQySRDaKk5Wdu4HoQ=,tag:JBRjZeEdOg+trohfanO6Mg==,type:comment]
|
||||
vaultwarden_admin_token: ENC[AES256_GCM,data:G1v3N064ci0Fw5EtTzaryailWpsv6f4w6eoHp2vjXIBtIlScdQk1Q0W+eDNRk8Wr2C3ysTXQNbyYismNsls+jeS3W+YqkKL4fnh3a5UTzQrMqvaH11n3ak0X9R9vmt+ZJXBrUrAOKJ6RPHJJSWenhjDB77kwEdQ=,iv:f8X+x/AdmZ3b3dtcSFrxGgA2tCgDRpgddjlVu3mdCmM=,tag:c0MXljVvhwOdvrb/8hWlsQ==,type:str]
|
||||
#ENC[AES256_GCM,data:2ESzSsQZqKdjD7OXN8ZPThj6g9acJREe,iv:aDFPB0vs8NNo8ExLcJw7qtQvWbCb1XK6TJrHSK86qss=,tag:z+dypHAGUjEXP7Y9MHYWwg==,type:comment]
|
||||
gitea_database_password: ENC[AES256_GCM,data:nhFn0/G7gW5rk996OZzlcTt7T9KMbP8MNM+ReFC8w1H9ZqBSJUbs3K+n68uQVrkOVSXE0cKpOR1VbQ+i+46z3g==,iv:bT4GRZZ83v47/EmeV2KaUFo+4qTT4T2AktFUpPiZdF4=,tag:OC9TInkAr1egM+xnBDizxw==,type:str]
|
||||
#ENC[AES256_GCM,data:nbB5Cd7i/KTMCjCzcX8o1sxREZQ/gLAG,iv:iyuO2erxdJM08WHJBjKuNIXYxVhH7rfyOLTcGCcGqNQ=,tag:UeDszimXv8kQUmDetLeFqg==,type:comment]
|
||||
mosquitto_password_file: ENC[AES256_GCM,data:7ifs2hGnFQSgJOAKpN0usfiaqLjj7Rjb7zn1/qBDbqEi5hV0JfUncZGorBivR/+kjXHQO6nxaHcKqYvPedNdJ7Qy4/uil/xwgwSmzcbisdVYkhd2pf/N34EQFxmqohud0aTH9V47QbgTdrUPfvsiL+ljLvLu4w==,iv:z7YPIfJHHaLOJrDVnMQhgcMzYAPordFR11kHRAzZqYU=,tag:LRddczdvy01YTm2DFDgSJQ==,type:str]
|
||||
#ENC[AES256_GCM,data:HJ81OxRD2xtNZKv+8oDqiT8mYpv45JMvjxU5pdmEKzl64SK3lQ==,iv:wStoC6XaZlvRPfbqti2CUbPrOOTt4KktaUp2ecVrggU=,tag:isOwKfNdQZAM+E8YQXBSFA==,type:comment]
|
||||
velocity_forwarding: ENC[AES256_GCM,data:MUNhW3q0/klK51k3,iv:dGT5N+IrZfBxMIwa0mUrIKF2HJvx/uZ5o/ps6bgDNOE=,tag:KNY2LKwmmnCdWqRnxSKctw==,type:str]
|
||||
minecraft_recpro_db_passwd: ENC[AES256_GCM,data:dPAkdEX0hBigo/lND2r3ShxnS4Jc5wTI2ShcKnvjig==,iv:WjPugYspUvhy6TAh5UF3etvxTZjAPe3bkgFxIkh6FDw=,tag:h9LGoxp2x8PHxcP8fEkSlA==,type:str]
|
||||
#ENC[AES256_GCM,data:nbB5Cd7i/KTMCjCzcX8o1sxREZQ/gLAG,iv:iyuO2erxdJM08WHJBjKuNIXYxVhH7rfyOLTcGCcGqNQ=,tag:UeDszimXv8kQUmDetLeFqg==,type:comment]
|
||||
mosquitto_hashed_passwd: ENC[AES256_GCM,data:k1Lnr8ZTDpzXMoRmRH61X41boX/D8Rm1KPh7x3/IHFo+XKIOUQns53iA+7e7Ohp8uWSthDlOk4SlRvTXdUNiEz7Zmw9LYwy7BHbwpNo2pFApAye1ORPrMrhMUkUfgBgc8oqPPyRXmmrOAFp6GBbRhg==,iv:D8wQL9iF0rqOte5X24kDTVjYUJXbZSLz0Ykbp0HqmYo=,tag:RUCgO1uKPIdumSo563cg1Q==,type:str]
|
||||
mosquitto_passwd.yaml: ENC[AES256_GCM,data:9xwHiUaQ6zG/4rkRemXtbRJ/KEV4yajqyYlcXRR1eAQ2XijYOzitPjt53h3FPqp5rxl6dJerXNH5CiZZK3t1l339NxNseJFGVmIHitWJxNmGJMlG3M8r8Q==,iv:C6WWZuVkYaasB2pol3uf4Mc3d/lDEgt2pKX+dHl/Cr4=,tag:jYTC6RKF2TzDSwSUh6D8zQ==,type:str]
|
||||
#ENC[AES256_GCM,data:zmSByl0De3a39qLbS99oce7ORe2BBoPa+3I05/YYxL7iBeWCP3ZK,iv:6nUTBUFpNK7Mttckqu6Wk/QJ5cP4+iL+EH4ldaIuu9s=,tag:pc5UtjbNPsVOEMCdLKgGMA==,type:comment]
|
||||
#ENC[AES256_GCM,data:ZWlAWAthigdTlfHrQl1x8eSj+gv4Gj1poZfPViu1mVz/ZmUJFZyCSkdIg0CPdNNF38TE0iabBk+o7aHkFmIFz18hjVYAk4M2E034qg==,iv:jU+2E+XAILgFNyMkGZ1CMJ83q7V/yyEJwHXWw05RlHo=,tag:n8w0/ktmum5P31vMWJVxgA==,type:comment]
|
||||
postfix_passwd: ENC[AES256_GCM,data:3ndIsTGPyAQELM8lptBK241a3p77fNijXma4souFKnyrkLBpZ4OP6KWuldFlWySpSG7Yme0by5gOzg==,iv:nYuJKeY4H3OfQleLo7gvheT5JHgXW3hGQvjHeEEN260=,tag:q952E/0QLC49O5Rwua0RWQ==,type:str]
|
||||
#ENC[AES256_GCM,data:UcpnHZj5xr8P64PzhWVKbFy8pvFM9GCz2mDoW/6iRVqgLTL0FSn6KXep/kfLEnYiqv5ZpsVZjjXsbI5VRJfBo7w4kzX661oDU8323DfQHDkbo2g=,iv:nEApgutl5kjfZkwi9WTOwatraM3+TQqFgk5gEMw0rwA=,tag:Q4gndL+6q7jHN02QCpJDjw==,type:comment]
|
||||
#ENC[AES256_GCM,data:3oMbbBSrbjrqsdiON1ENB8JeKW0=,iv:+/eL/51OA+VHbkWWSNzQId5BlxnMm+5NBA0uKw010Tk=,tag:vBJpCYmvFivBYIKatDWgHw==,type:comment]
|
||||
copyparty_passwd: ENC[AES256_GCM,data:I3UYy4nJ0B6RnIp661O0VVqEmxloxxcroBKmNFcgoQ==,iv:sWkPfKqomrNaYFZbn+BeQEugRMlaqi1qJhELqfsGCik=,tag:Sgz56ZW9EY49zfwFDN7whg==,type:str]
|
||||
#ENC[AES256_GCM,data:3ATkokBKeOp97uORzaePROrKKfG94ic=,iv:MNJRh6Vrso1heqNUJc0M4xGNcMLGwcF9IzoiQ5+SS+g=,tag:xj8Actwkirvq4GE+Ly1M9w==,type:comment]
|
||||
vpncon_mex_config: ENC[AES256_GCM,data:4i356X97sBoRliskmh5ewcEwZHkpo37IhPcemKVdWJgWFWtA+AhTeEo4KQ3dRA1H/n8VjVX7CKZKPDxpmHfcUlnTLT0agtOjjyjf60kWoL8noJqcbDB4wGiYT910rPToVnYMFk0H2lerYp+/n2bhg8BHxn++VlPOOZsgla4El+FNXUqhScpAawySPSF36ocdRJ3r3DuflIhnTBXxSZukMf9Ux1uaFldSG7KasCQlStKy9O2Odd2AvAuGXOHch5KecRPT3WnonQ8oDJpuxbeaosLmtJKHL9oeXHPId2Unc1GNoOpnDC3Y/xGnrPb9WFXWYOSQ/1A3mNKwnVq0FEhluVbqodES4PVIlCS0koiQJq15P15G2z0jO+OhAQrRI5vn3Fki5A==,iv:tQvTpzhl7F7niigAXl61FMHbg6QqI2R7yGD/C2lwOR4=,tag:c+CVLd6lGrAfm38pFXOXTw==,type:str]
|
||||
#ENC[AES256_GCM,data:ep/Z5O6RNFwTd0I5hvtk5DP9,iv:M7sclKcTR+IfCEsvz0lZaoZBRZlQsN/FhwuzFNXgVew=,tag:Ddo3Qf8tMBX9Amt7C9m5FA==,type:comment]
|
||||
klefki_pub.asc: ENC[AES256_GCM,data:lGfgwhgn2xCb1cNTo0nMP8R3KSDiEn0/k6neDE2dv1DynvXsHWmZSXED6VWBjY3uMU3YtcpXGCtxTU6EiaRKiGnhxslQlBiSypAnXHeh55DZJMJJ/JM7+BCtr33LY2lusF9/aAuKO9tbdpGmu63s5ItZ1/9zMoCJwBfpQZgY2HzZoBhjwqYu2wSkOOVAMjq+jXET7nASieOZXmpQq2uDepuEDa8MP7d6G6kV2KYJPdLYYaY4U2eppEr7ALhhJidYm3P38W47JuLyu/2raG0AY2uDtCQw9d16BcJO3au+T4B4mHzPg1/cPhQ2X4dHTTGHjRZ0sT95DrEYYmcwWVKHKyiuL8WPtQmF0QBfCOPczwJajJejB4DbxEW8U2kuhuoBWr7wZe4y/nbW2hB3pcMYYXc0EXen74IttiUrvksw+hbkLaZDCJgG91SOlWSwI12UlDrJJSzOYm+ODWqK+bKyqAafQTL9xh5heM3nQlR5G6/A/8UG+0q5ZDL+IxJwe+EffJNwrL1mn4Rc3qx068udMJC+qzmft7Ljey7mfoIiwepITpii1IA/CtuEqtpe4I5MUemQ60qAw/PoVbmD8zhOcnRHCBZtQ394I5vMo1qR2a4KeBICexx3IAjpeAQYI3+MAgo/bedqpklLYjbxpv37XwinoLj9ew4hKSjAB1wRRZlswmk+GD4XKlVo8eu88RCXYrsZ2oaOD4qxrtbc7+skGm+EqxL67nLW5n9bSC2u95bFJ1386teSFhsJL9w3EFiBlQRtm5tvee/ipmr6D2W7SyfCnSxImPC4TgTwkAXziQ3XtsUtGqj0Tv1HGayaAQpYzlJaPzf7h8oanH1VaA+AgRq+RY1OjLZGHEz37jSbqhWOiIWxwJ7qFaqGB90cHq3s07qcWrDl2wUawFLTXavZ0IF3gj9KnFSIzW3+ANvedUCXOjai+zOKmpxVFZ4Bi4W3Dcbl9B+qa0Ly0NIgldi7PmqEvL3V4FnJs6WnwdagyhXOzdlKVlrAgGluucgqBpBZZfpN6uB+tdkbrqzsdMbr+H9Hwk3RUxRzAK9k+J9WRgY7eMazH0najJ1PYh9/UZJf0DKWRi2vZTlWW+6ZruJWTohOKm+7MCgvMEttIpNQfvK6+cq7p3vwPe+pmq0DznNg4LO7Uu3cXKq3zHjl08KGE04KZyfoJuZPr+XrF91AywZ03HlT2SBBaZtFld1VapccgB5DqgE1JfFg+TS4is9a8G52Ad9yh/abUmLohsnUpGdYMaj/1FmhSLM7ldHeub8CmL2vKW4f/JTuqmOxq3X5RA+qw5f946ekUz9ZF8EyGvNwaRZ2p5m0MtXQG2IKp8Q61aBSpqbMwKzTW93VycEn7L5ZsoV5eYo0rC4PMawGkfgdNzBpq4NL5bNB82l6qHnWqU7jXh611/ZV4ueX2MLSB3cyhnaFxsH9bat1jGDtUl5umNWNtvN6rWBVsClmYfBLSUCEyftGPlxzAOy6vRHGxAdCNdoiTRGgZru3aYyW9l5XhYH1aZ+dOlTOwngaqqIb3kZoPzcc9xCeZ/I/N6iVuTUI69us8y3LVL6qKa6az5zTTgumoFB5kMugPtumS1U9hzhLtm9+hY6yZVgYredgAwVVIviMAqFFZztFkPiskcwIdrPhXzoXwfuBWDaq+dF9nykjw1F9U2gyDU0YhEOtSmdIWoIma3OmdOZ/h/JbWNrwUoAirmBmWIHQTmA5Ag==,iv:btQ5xmt/AA9vW1njJH4Inj6YmOBx6pGbHbsvCMbg7fI=,tag:DuQ4Wy9wX3mPQAVLLd6t1Q==,type:str]
|
||||
#ENC[AES256_GCM,data:7V0L0832xewUXU8/Bq469w==,iv:9bCzEpUcNx6qnCMomFweXgYmWwSMzdffDikjA22xu6E=,tag:F4S80e/EPXA0tS20KFRbXw==,type:comment]
|
||||
id_snowbelle: ENC[AES256_GCM,data:MAw5R2fqVIctN7fB/d3hfCU7W3sxvuy2O3w3n0vD8FxK1DAhqoROlVv04joV1a+U1hof57TYc1cN2ng9BRWxadc8ZIpWakokZYVI0dUG05/hPMyxctWPkOiDd5909aaNUFC2G+Y/VrgAemyrB+AlQgokV0U3fiz+qjg055fzO7ypaeM8okON6rBnigfwetmSm60MxpdYrVlxVaniDVvKKUYZjpHU8SZ+TYj6Jmm/bVuKWOJ2DXZbmM0CeKeIgnA9HML1wSXojMv2IMGulxq5mmdaiiJTPoL1q17OA5zZkkVW3Dx1y6SbEeBAQTPG32RHseAxXK6qdU6lftRQZKyivuyjdCVfBBw/VzqTxbWjSXXsjDdK/Ti09051w6znA1uvRX65XsOq6zPKt4BNwR+yMDF+xR9AElBTHES/TDf7TRc5YDyovlH2PhGNg12Coy3zfb6WESLyaz3/GYZxF0IjvBnDkN65CRjstut0CgKXcWY8x+CuKVysU+U4c0A2ucDnsf3HuITrdIufhAwRNNZMka7LWVsaaR/tnvcf,iv:agf/LEjohw1XAXsOJJ78kiBVJnTT95IUmWzYUujSlJI=,tag:a55o9L85a9Z7gG9s5BEfIw==,type:str]
|
||||
#ENC[AES256_GCM,data:ozhgyE+IyqR10KT8vI9x,iv:+ZOTucRlCZRQ9ZbxZgySPMOJ/qU4gXbhSyLAMgt4QMs=,tag:mQ3X+dqCet1Yk1gZ5pZ5gw==,type:comment]
|
||||
id_snowbelle.pub: ENC[AES256_GCM,data:rQ32bqwknbVssJDN4TW72YrusMPQJRFTfpoH2M2ELsAf3DkXtchGwOSjEbeR9ezUgHkTD96rFm5JvjDFQukAOpBHfMP5aRVy6RjTtb8j7aAD+EGUEpBSAVspZKQAWAqyDQ==,iv:8bEgvJgWpu7QwsrWhkjUw3GtRI92Pn7TT0rXCQ/i2Js=,tag:EnUehKMncN5v4dZZ/es3Qw==,type:str]
|
||||
#ENC[AES256_GCM,data:lS++LQwlDVP0aYcdaaudBkKxNB3P3UBE,iv:UqGcXcX/Jvf60o409Cxj7VJCDh63uUxy45PuZbHK2l8=,tag:OXdMwuJwdN8DQaLXACpcRA==,type:comment]
|
||||
ssl_blakedheld_crt: ENC[AES256_GCM,data:OPrDCh56XdRLslAcx/vw9l7gvc42no+QzB9tVSLHtcHbWWqb+hefvAE6xnfMLlt5+BRuAJRvspA6kx/WfagjFuN7q3HAHPt/FcfZPCYZNT5wXZH59wtV8JkVtLKnCxqSUXrah9a/WrHkU7njzoWql53eoAXEt58mvxyxZihqZd/uwinZt/T4QsevmikIsB3LB7AQtUHfsHd13ZFAaGiA+Mnncdl6Nt5s3U4yTuUxhfmYwr2cuyL+Li5eNzdO2ZooXBySdp4Ym03rpBERuh0U8a7NNj5ZaoHW1f0AyFRRKQ7RIHHyhQNC6hL2eGqsv+hTkJCJKxOCYKW1cF9rDt6bueKAm7zk3RTw0Sk7eXaOoqulCf8vBcMf4ckfH5mFVUpSHuwc4lfIZExjggn2i7Bu7xGIOLqC1RL4S5cuhLGUxzgvCiKMcMmaZZcT+fZa5wiHzv2vaCzXuYRb1rNi0xoiAZcL65yIV0NGtP0mOFygdY2hI4R7itbcE0MGIbwdOuWkCRs19WVFchNgcV7GnZBUVKAbhFXq+GilWLufODJr4Zxc1NpxRjG4flWQl3A3jGc4+tW5Infa1n6XPmhHz6JjyPE2mVbLq4JORPHeMcN4Wbckrmio0ruJu5rV9J95HYceXJIF2dw7AgmaWEX67JCHJPbAg5n4zRrfraeMwKB7XHTMglTLbyQsw7zkqzGDpT6ztOn/uCtErEmU0LSlIcOzz8WdGnnWbReMLiUfrQwuKvJhwOpcr9t+FVAtDyjyZhL/PTDy4/qIjQNPwBiVMKzv1CV/eA1WHcYKb6oRvP2TAlh82mA5uIE1jqY9QXg1cfMl2ncnsHnv3d1iFHy3OxvmWwvve+1zzJ2jubh+1ZwKAjP/9UEq9eldyFqC86qYKYGXec5j4Q4QGrMN4AiObVI/yDnRdeWal8jM8p5cz56rgBesDX7/ljR5wjifdQ5s4Iao2exPrHAWtiJHWE1i4R1g4rB+h8piu4feZXiPh3chdxrUrxCaQK0N0nOkN6+F7y8rbd6egk9Q5xvjNlJGzJGiSQ9xhDYmnPZtUTWXL3KioIPwy2/yh+lpkG/JrUacgc+HaHO+DsXs2NhlObrcswo4zmZ1eEckwFSpl1iP5ABHTxNVY0V6pdj1+7YyB+wav8tlVfguyxLf8JV7dqVnADCV+R5D5rBikmoJdjgdZwNxO0QBaZFVLeaCSgoCVEfvSPFtL9cMnEhLhdtw+k3U53+JJYemRfdh48DAM01Na2b9q6Ey2R6YrqtONVIauMNAaKXOeaJCxJhYVBqB8yNiAOOhyJ/Wvzq/CUM1QsXHQvwbndAxmyeFc8XSo7HZZME9m11fNvcEdWfdm63BpwkrHKPzQc7sR6tKeMy7l48f1baPTNoevEd0vFeURHoOggrnyBeO4q8YdLCderFmsSOzyDP+KjDxwTE6u+4P2xMXfnjwTpxLZInV+sNPsgaMj/bBeOJr7m6IN8N3/jxgPiBTGMObiVCIzhXL/VP352xc7Vbh5ZjMvuXQIPWCodPjWV6kcK8EvanN/l0vbDh1MxMAFiqj6tRHUfB0Px0JiC263kR0vzEDI1K6qEfPmPjA8TiDo1tK,iv:qdtzMcF1iELnhrCs3SboRcAsnw/0WgcUpWWHzKHNEYc=,tag:TkUMk8Wp2OTQd8CRtS07Wg==,type:str]
|
||||
#ENC[AES256_GCM,data:3G8XqUKua1QgUxv2YJkW0fDnQPX7+v8GDC9BHg==,iv:BkESkMmMalgesy9why9eaKkOOvwSsN2EhNCRRRmZNtA=,tag:x95zt2B2M19BkzeMpAlXIg==,type:comment]
|
||||
ssl_blakedheld_key: ENC[AES256_GCM,data:JCjbKYU6p7CTMtnWotZWBvW7vmLQ9MAP3bejcOteLLFLDZfmNguqA5h/8s0wLbjGnbGiNnupkvyWPCkC4xhO+fVq9Jzl7+YPEZn3uKjG7vyLlbVhLsmv3BleR01jddEJv+2fn2QztP3CfbocPHm2QaQhCqgfxxvcSpy0SlN3IOKckQaQB1oDJB+nHndPLN5VGwABE+b4x1AoYltfoFvNiGam8xXu31ENOz0WPVzi0Xmw/noVoS627BK/P+ISC1KP/iGuyRiWVmF2P8dN2oAtUarC2JV63/HevmN225pszBIyEeDta2Wv2QCNBYzUsDr5NA==,iv:fPuepEZUNjGWekTCfROyMoPdsioissEqvR2gZu+2NAQ=,tag:fVPI22eUYXOSI2A/MSbsEQ==,type:str]
|
||||
ssl_recpro_crt: ENC[AES256_GCM,data:CiD7qdfWzi+7iA7qCD+w3UJdpxZByk2kmpw8YW7K3C7ODuSLXPfw1tLLunN6S77M7hazgvSDVsBEOWlS6plACus6iHmm77yvpzwScv/sTpvWiMpJDmX8svrr4hg13eXSg/8h4Z9DdyxoeMgF6CWXnUvmbgauB/CRyaD9PzeKq6amL8EofneueJ0Y/1/NCxTX6mn7XJHELev9s6yOwW2nICIT3jnfpoh1M2rg4c/Ys58od/iP/FBx0ahBMHwyw4n57Jmt93xAFZH6YRaDfU7kpf3JFKXBTZ5+penOvUjtEAJzDhzrErqkPqOensWch3T8n1i4ILIqWI4myYrncbeaDl3/NuK2d4HOEiqVu8RcBP2tbBSriiDnoO8/0JQrkIbVvxEhZ8/HWJp73nx/Y9Khf0kh+y1ulIotNvTwIAgvPntSQxlC6fZWPOFcQTsZoKgvR4NiBToheqYrpr37WHAQ28BhnxVi93O2t20W72sTgGpslmpxGjuS6/OVY2Cs6HLznjnbzW1DK6QNu35nHRIHk9xgLsuKf9jFO05Gjo/ePGbJle24mLAbjZxYV/jkU6+w3SuvTK37Y1YBZ3O0aVyqThE9JeRiQ0Xd9gUkt7BtEq6rxrMByYa3S5d0PiCXsR2tlntkjVREJHZQMzsIbsPyowiD2wdGMFvjMSldQVkjrNaH4eKlc5CJpe8/7xbFeXtU1TdUA1aaJlxIMrExX5kbJj+qoNxJyymtQ0Xs+G330aAz1IIAswbrcx3KakajGKV8XzHugyqj5tD00MQYHakhWtlm30Iy+MsNn7dUpApoHxwgXfzH1T57EUN5yaR6YDgYvOs+guqjQcf/3Q7Fqd0IdR1c1aHFOiKDKJ7mgcTRr/Mmzao/RC5TpgU4IEiAB2Xinhyu+g6CT/I3jetQzsC80Kc63oXqRSC6sWURQyQ4UxUtGET3wZ6Uq0KYK8ce+Enphj9RPA29XmFJu1x6hxcBHAyZVOawrd8lTpG+x2vxJ1wAyjrUwpKKVLlToHtzCmp5UUEs2MsRd8fto+NKVEMbOSUnu3t+OHf9Cak4mvj6QFO6Q506Tp0btlPtQMm7MZ8ONFHBRWZTDIH3iI8eiGXqfDSnVDFMoDnOLaK4N+3U39Qtpc6QmN8tQ6K1af+c3+4YQHgWK7zJw/sfIq9YZXn2EV3r48daV5Bf+rihVVy/tbhZxQeJAJC72tWF7f2qQphocPakW6q7sZwQ1q5PyzNBgVeLlIAbbaLZ7oq2im9Ateobc27aApXCLIz8tbxDyOKwSCtRG+63kXZ6Mgiv5MXfHKHulC1rTHi5JA1pN1lIMe4ML1GsyqJSutJ91rVo3/skk4RNSaJUsu79lT3U6uIzBa1jPcaPaxQI6tlVuxUabFfU1Lx2e7EZMFT61b6XRhoT3VRPvJXBsNtXayieKPMcvY2i1PNuL8XdQOkzNPlj1OkigLDGrvyVHKwhinBl+nN/KkKbXaQ1Mt6OZoXVvzWggGYgHgDuyTbJa1oa5HnszZQyzhUhewHbSeGdE+FRDZigWEqoYY63UdlLc0juInSSkroN+vqzsCeQ0JspIEBcUPwNy9DH8TrKfMJyvBdSnTbchwKjC0zqjW2D3lVAAEIF1mdBdG/2dDacbBp3BNHpRu/cLA90YTt8NtNq//lYRrGO7eCl1vywuVjjmXbLN5aDq07HkJCi2cBtsp0Cioqd7Wblmad5iTcdBz5jz3j8Th8KA6RT9vxtXHL9WN0gKpdfx+WsDy+ww7D6erTUuz2RzHHxFEq4sqp2SGiwj4/uADdY9/SOARqTWbhdiq56xm9BzU3hm8R48mahHMKW9pjoUODT7IA62j4guHgtrEMwYPI7yXdvGEgA4Vx7RiW1C7xE6kiUavONoa49sLFsxZCcfldLFQYxrxEi3HIN9dzQu81e3gvPzPbHDYxe6enurrl/Mg0n+3yJp7wIYt/lzjoc3sO+XdKTXpmXfqEpUfrjXwzadYgAf/UJsgnKAeTDhaJ5Si9rQUL4vxjSKCbN2mAEaxmvQkOeKm/Y86QvrTqu7AmR9gtw9nflgbjyWqSX5OOnjSB3ZCSQx7WmBY/ri9Db7xlDxQjSH2PBhhh21fh1SHbKiAbl6M5vSduVwxpfb0O7l5TrzF7fMl7EWQufAvI4sFV5t8HhRXO3xLRhoBHZOR0JkMrvZcPHlvsbB6YfcbTCQb6RePnxOoOXwcMkw5yZVA==,iv:5KucKtHOeiviRb8AIhF54CuFx/RxxYifrQP2vvIr0zk=,tag:r5pvRK0BAO9nkgFPPUSMMw==,type:str]
|
||||
#ENC[AES256_GCM,data:3G8XqUKua1QgUxv2YJkW0fDnQPX7+v8GDC9BHg==,iv:BkESkMmMalgesy9why9eaKkOOvwSsN2EhNCRRRmZNtA=,tag:x95zt2B2M19BkzeMpAlXIg==,type:comment]
|
||||
ssl_recpro_key: ENC[AES256_GCM,data:ev/g2sKFia5xcgZQ3LsfT0H9AaShYwxglzZadBhvknzFVwWxXGmGfHgKD6GM01fCIFOpB2pPGiiOTpgBh2xoRnPmivsApWoxxXgdVfzEEVbuB5pHAJSHWX5EUEqeiTz83zfbJAC5FZFwlIEQTL3YiPhRzKRWwEpMyYigsZmUAv3970XlDTAxDRgaPc4eHFI2ZrEXGmevnBoHOQPwXi+JCHqSCyhbPnsuU1InIcp4PMlX4/K+WknDT0HaLonIVXds237E8lOCJFAo4Ow3/zHho2B/tBZeqcHHf4P49SaSEO1CSCzTrW+1N1n+EsPo3PPld7AZ3klnsiKltorO18GM+2L9KGg6LbTiWm6FCOk2bMIFg9q1b183SSzeDx9CzhoXefsweMdn9BFBF1BVUObHGgYE0dpme20S43C+NVTeVt9+gjOEYysx/II8m1ui0UzpW+kYRdMLFjepYHlIZRA/jUEfdVssqKsX492n9bX5TRPc/9LN/o6oDg4CZjZXPILjD+Cg1NOW5ZSJrKvbFGRVNVeVlC5+idUqnaKP0Jh6nG/8niEBIyV51YGy6/ukruHyjMiH//iG9oE2xfLwjQGTUKhERxYgKOnisHkH7b7feTQBq926BgtWP63zchkCYz9sQTh8LzmfitXEBYUpRvDdxlnZ7m6I1ssemY7bFCnx2rZEpHRg9LxDG+UNgiODwm8YvXQbL7z+DPSVzG5QdRbhlS+deYMjquLBvWpMfUrJ8HxurLyvcZiTRqRSBmhlc+08Y3/j0RaSfmDdtId0HGKvokSoB7daMpgfKeZs9ddpvmEVYto4bER0Y2xfumgUq/VuhSR/H6KhuR++8JSnDZxPS5WtoH3eVOXrDIRKadiwYzx1r9dhek55iVLZ7uF/YGhxS4DD7gFsJJk8/usLnu7PM2UsoPhfhg69CrigFZRa6I1qdPSon3ODYxlJt1KVLgyNkJqjG06t96i3NcJaIm5tZNsGRDKrU8Jh6EiSzCquGOy4oblpE7lCdK5mlHXL5a0WRiaWTUqo27qTGT7o5jskXHQw8X+/iTP6LO8GpDcL/YCpF/HpV3JiuHLifJoV3u6Cj5qFyCfxF6k7h1gXUZxdMtovpicbzHeJS+4pAnrdR6NmavjlBKDZFRa6cUY0011ZuA4HYm4SdEPTCyEzOLNsmx4iwNao/jH1sPb6hQxfQrI/2xbKJYLeGJBDagCjEOB+bo1sUaTepDVSHAGUVpb6ZdW98AUs+zOiKAhE19H1NRuRRQcyq+6fMFh1+qyIoIELiJNlKcTjv53r30gyvnbz+FPLWqqvskZhRnwrF5JFFqwZ8Rkt/sS8TCQVT3ZGfOHF3J6yApb9GKQVu3D45efUePaPrGHVtWdJmQRVpQNKDAYoxOWT6yMhHH96juDh17QrqSvD6M+NqydP2K4q6zQE4rfSkTz9xPR/O7SvLUIZ6jDKj7TfNqOIpqVLaq8wiSPB3MW75RZKiGqcyH4aiEDgpYJRatF3+qZPx3zyUD8Oh5teEWya/HdqqW24a8FdmuQvdwE+ksCpeMJrVslQNDWpwpmRgJe3Nal7/qhdxh92WBSSteHmRSoFLKDwZAUa/f6Np1SXR7sc9fNeIggDvv3Ctx8LrUWpYTae1iGcaa8bwMPiwYXs0tLF+wmQHSypcMdl9CH76jhBRM+8cBzshiCISzJ4xrVUi91or5eOtXHaUM9BOqVZb1uykU/mkWWGQqdzo5Ng9POWUBxLvR4JywSVo4BaDawRykevOjM8JZFGYLfyOk45+MRRuESJWYnjf6P3V3f8l5Ai3SL0g7q/BImZ09iC2jTib8qlRrLMMJ+OQqx45TeCwicBnmV2hqz77KYvikgYLpYQUGkFKcqpP17nXKajbkvEP+2pIQQp6GRptp0Q3TvbOSZSvBJCmr6/6AQ2EXxTKMS2caUsw2bH2btkk45epPKJY1Qg1QOcjRwCUzy0ametW85M+5a3TSKjYAT5lNDb84q2mdMwy5giSI3iglUemcNYFurVlgGcY2CJJw6xi6UiqaqGIEhU9Sn9ns0cHejtu5Uoy+jxyuNaHyuH/f3pB/jdkCzkyTrxT4j5Lpdu6+Le4MdRbn+FGVtopn0LuoqHG8FhourPmpkQxdwA2Yq9glf9MuqiHz1aDri5rDQs/fdCYffvTxEEkZMvYdNIL+m/9talRX7wS1CffCqUrglcfKZxsbvPY9pK9YSxhOmtyZ/vyRBAMlA8Daz0o0mV7czV35tTPPoD36pgo04JenFRaKopwgyQ,iv:682Ok4M7ptRiWBytvbbiDyBCKBdZ51AIn7VWA62GdBk=,tag:UWsWZnDZ10dMF2vAB8V8tA==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age14gfh682a7m7jfp3qrulql03x5rs7yedwmxwksxrrmgjsunstyuksqx93pz
|
||||
@@ -35,7 +66,7 @@ sops:
|
||||
U0tmdFBuZnJES3piOTZNV0VKQmQ0eVUKCWRQ/flLzmpC64WyLoipklZBmrkpYiUg
|
||||
PRu+itNolpPTHm96pe+P93g2iP0wgekG0cX21wkiU2xaLF3dY2FEIA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2025-10-10T06:58:16Z"
|
||||
mac: ENC[AES256_GCM,data:esDQXPJSwUpChIVfcXJe5MVFI3ZJD2APDbOcfw5amo/PYB1QbbNS3W63heEmyVK8CW/UXSeeepfzlnk0kyneDX+v1ANP6B5+LLlpuEbjb4vKxZvo7C1xb5dGqzG7aizXjs83k/vZTwXw9/4AgQUQq9gL9ZI1Bmgk3yNvzctLU4U=,iv:IMO35FHjrhFoLu1TE1f/3PJOVGhe8Hwcr0CzsoJMHiM=,tag:L1ibIfAfYE9K+lKiTxsofQ==,type:str]
|
||||
lastmodified: "2026-01-28T21:02:05Z"
|
||||
mac: ENC[AES256_GCM,data:b9aX43ViObNX29DkVNHtwkQRm26PRe2rZYhDnL1ZYLLWyaO3OGP9+rM4vHT0lyuowQ6+Ur3IMPVpUSziXYLh3mtxr0hyYy5Y1miBuIxXYLBi3oLRTW1TgZdklzFDVL3c1GT4lXEh4q9KG3dP64r9/8dvjO2iRIosZ93/l0pIi3A=,iv:/gdNfVy8UiQsIRAHh2jiha5fL+wmfgp0srxt17Ry4Xs=,tag:YdVbvpBnQSaIarGIfiTzKQ==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.11.0
|
||||
|
||||
BIN
users/blake/assets/icons/alert/critical_128px.png
Normal file
BIN
users/blake/assets/icons/alert/critical_128px.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
BIN
users/blake/assets/icons/alert/critical_32px.png
Normal file
BIN
users/blake/assets/icons/alert/critical_32px.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 723 B |
BIN
users/blake/assets/icons/alert/critical_64px.png
Normal file
BIN
users/blake/assets/icons/alert/critical_64px.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
users/blake/assets/icons/alert/normal_128px.png
Normal file
BIN
users/blake/assets/icons/alert/normal_128px.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
BIN
users/blake/assets/icons/alert/normal_32px.png
Normal file
BIN
users/blake/assets/icons/alert/normal_32px.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 693 B |
BIN
users/blake/assets/icons/alert/normal_64px.png
Normal file
BIN
users/blake/assets/icons/alert/normal_64px.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1 @@
|
||||
background
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user