Compare commits
629 commits
e3f09e9981
...
b826fe24ea
Author | SHA1 | Date | |
---|---|---|---|
Simon Bruder | b826fe24ea | ||
Simon Bruder | 9f7355f97c | ||
Simon Bruder | 342d537621 | ||
Simon Bruder | 0de6be12f4 | ||
Simon Bruder | 964b34f321 | ||
Simon Bruder | fae6a08b6a | ||
Simon Bruder | 5d5a30a72b | ||
Simon Bruder | ebd1353bd6 | ||
Simon Bruder | db7efe7d77 | ||
Simon Bruder | 4f042f7dd8 | ||
Simon Bruder | a7724d2713 | ||
Simon Bruder | 8748cfdf11 | ||
Simon Bruder | ac22d1bc39 | ||
Simon Bruder | cc9fbf8d37 | ||
Simon Bruder | 0baeb59b38 | ||
Simon Bruder | db5e4d212f | ||
Simon Bruder | 80ee98058e | ||
Simon Bruder | 07142b8114 | ||
Simon Bruder | e8e43b70ad | ||
Simon Bruder | 7376e600d7 | ||
Simon Bruder | 23b63fcf4b | ||
Simon Bruder | 540f89bff1 | ||
Simon Bruder | e64480c820 | ||
Simon Bruder | 6eadefd6fb | ||
Simon Bruder | ad8eff91db | ||
Simon Bruder | aba6be5002 | ||
Simon Bruder | 06a464c182 | ||
Simon Bruder | dde4275f0c | ||
Simon Bruder | 65a37c5703 | ||
Simon Bruder | e1cda094c0 | ||
Simon Bruder | c55bc54b35 | ||
Simon Bruder | cbde39cac1 | ||
Simon Bruder | a47e41b9a2 | ||
Simon Bruder | 76479d0b37 | ||
Simon Bruder | 1b8f16e88a | ||
Simon Bruder | 95fdbc6b25 | ||
Simon Bruder | ac85009184 | ||
Simon Bruder | bc862642d7 | ||
Simon Bruder | c7ccd022b7 | ||
Simon Bruder | 1a515ed9e3 | ||
Simon Bruder | e55094d898 | ||
Simon Bruder | 2fabf49a06 | ||
Simon Bruder | 398ca91aa5 | ||
Simon Bruder | 6e9c04e52a | ||
Simon Bruder | 5a75e8e443 | ||
Simon Bruder | a9f0b42f2f | ||
Simon Bruder | b87209cd06 | ||
Simon Bruder | 505697715d | ||
Simon Bruder | 349b72c1d7 | ||
Simon Bruder | 88ba5dd485 | ||
Simon Bruder | 986983f1ae | ||
Simon Bruder | 5b8f759519 | ||
Simon Bruder | 8d789fbba3 | ||
Simon Bruder | e6f9ea1c67 | ||
Simon Bruder | ab793631d2 | ||
Simon Bruder | 2c160661ec | ||
Simon Bruder | cc8727fa80 | ||
Simon Bruder | a9817baee9 | ||
Simon Bruder | f17dac8f50 | ||
Simon Bruder | 312f2ba627 | ||
Simon Bruder | e6c1a105d2 | ||
Simon Bruder | 5517a5a3db | ||
Simon Bruder | df865ebef9 | ||
Simon Bruder | 7ad9d52864 | ||
Simon Bruder | 4807e930e7 | ||
Simon Bruder | cde1a05fd7 | ||
Simon Bruder | f9fc9691a8 | ||
Simon Bruder | ce6885abca | ||
Simon Bruder | 427361df65 | ||
Simon Bruder | 9588343b6e | ||
Simon Bruder | d394b1f802 | ||
Simon Bruder | f2d9a44800 | ||
Simon Bruder | 1df9a87520 | ||
Simon Bruder | 7b9a52e37f | ||
Simon Bruder | a220c7f9d9 | ||
Simon Bruder | a624378478 | ||
Simon Bruder | 9bac0b95ac | ||
Simon Bruder | 882f85cecf | ||
Simon Bruder | fc7bfb5b5d | ||
Simon Bruder | ac92017f96 | ||
Simon Bruder | 821367af3f | ||
Simon Bruder | 58e6cad052 | ||
Simon Bruder | f38ab1834c | ||
Simon Bruder | 43067ad796 | ||
Simon Bruder | cc63ca0e9a | ||
Simon Bruder | 2ef9d583f6 | ||
Simon Bruder | 66f534157d | ||
Simon Bruder | b8735ee4f1 | ||
Simon Bruder | 60b0dc9c74 | ||
Simon Bruder | d22183a8c2 | ||
Simon Bruder | 7e3506adde | ||
Simon Bruder | f4bf1ced57 | ||
Simon Bruder | b1f4b8b4b5 | ||
Simon Bruder | 65aff69a90 | ||
Simon Bruder | 9deb6c5656 | ||
Simon Bruder | 4379c72a7e | ||
Simon Bruder | 4e7aa88c42 | ||
Simon Bruder | f92ae65467 | ||
Simon Bruder | 13663a4297 | ||
Simon Bruder | dcdeece6a2 | ||
Simon Bruder | 817d9dae20 | ||
Simon Bruder | b443554c41 | ||
Simon Bruder | 31de6ec858 | ||
Simon Bruder | dd93cf13a2 | ||
Simon Bruder | ef9a022d56 | ||
Simon Bruder | e35795ad98 | ||
Simon Bruder | 58e18ebecb | ||
Simon Bruder | 6b08a8e1f3 | ||
Simon Bruder | fc1e8540e4 | ||
Simon Bruder | 718e44402f | ||
Simon Bruder | d6fd45cd57 | ||
Simon Bruder | ee390f869d | ||
Simon Bruder | 6c22848c85 | ||
Simon Bruder | 259969f2b6 | ||
Simon Bruder | 0ff89a0f6f | ||
Simon Bruder | abe078a914 | ||
Simon Bruder | ec0a8dfa49 | ||
Simon Bruder | d52084a79b | ||
Simon Bruder | 2af32e4932 | ||
Simon Bruder | 76afcc4127 | ||
Simon Bruder | a9a3c74f4a | ||
Simon Bruder | 4afbf1c24b | ||
Simon Bruder | 716acb8754 | ||
Simon Bruder | d44db0d505 | ||
Simon Bruder | 171695dde4 | ||
Simon Bruder | cd2295ad7c | ||
Simon Bruder | 9743f7050f | ||
Simon Bruder | 9c98cf0be7 | ||
Simon Bruder | 7886cb249a | ||
Simon Bruder | 0e2c6a351d | ||
Simon Bruder | b5782f633c | ||
Simon Bruder | 15d6c54900 | ||
Simon Bruder | 31cec022e8 | ||
Simon Bruder | 7a08083af1 | ||
Simon Bruder | dec3f07ca4 | ||
Simon Bruder | 00ac4f251c | ||
Simon Bruder | 8bf63db6e5 | ||
Simon Bruder | ae8effee39 | ||
Simon Bruder | 0c4f9a7d73 | ||
Simon Bruder | bbabc80140 | ||
Simon Bruder | 59655fd1b0 | ||
Simon Bruder | 400893b168 | ||
Simon Bruder | 2a4cbe6ffb | ||
Simon Bruder | 050359f8ee | ||
Simon Bruder | ac03369ff8 | ||
Simon Bruder | 7f4d0903ca | ||
Simon Bruder | d1000ee78a | ||
Simon Bruder | 275b784c09 | ||
Simon Bruder | bd20daea28 | ||
Simon Bruder | 5c0d4439e8 | ||
Simon Bruder | 9190c83c97 | ||
Simon Bruder | b3f106010a | ||
Simon Bruder | 79636d081f | ||
Simon Bruder | edab69554d | ||
Simon Bruder | 7db9922dc2 | ||
Simon Bruder | d46eca0ab0 | ||
Simon Bruder | d840d4c227 | ||
Simon Bruder | 1730681386 | ||
Simon Bruder | a94fd4d505 | ||
Simon Bruder | aceeb7c35a | ||
Simon Bruder | d621e84a00 | ||
Simon Bruder | bbda930013 | ||
Simon Bruder | bab6c5e5dc | ||
Simon Bruder | 0ca3062e69 | ||
Simon Bruder | 0d9ec3383e | ||
Simon Bruder | 2c3e65cf5c | ||
Simon Bruder | 37bc221e0c | ||
Simon Bruder | ccc0d60d71 | ||
Simon Bruder | 77eab2497a | ||
Simon Bruder | f6d9bf82db | ||
Simon Bruder | 65dcb3051e | ||
Simon Bruder | a5fde0764d | ||
Simon Bruder | 8c5a0e8a38 | ||
Simon Bruder | 9f4ffa5932 | ||
Simon Bruder | 74955039f3 | ||
Simon Bruder | 29f0a5017f | ||
Simon Bruder | a0e52ea7b6 | ||
Simon Bruder | 1aa325b1ec | ||
Simon Bruder | c0493bd3a5 | ||
Simon Bruder | d76c299f6d | ||
Simon Bruder | 9aa7d4411f | ||
Simon Bruder | 64a682a836 | ||
Simon Bruder | 9832f10d03 | ||
Simon Bruder | 15fdc8756a | ||
Simon Bruder | aed5d19be3 | ||
Simon Bruder | 71f6aed0b4 | ||
Simon Bruder | d564735b4e | ||
Simon Bruder | 5ebd71d1f3 | ||
Simon Bruder | 95b65c5d15 | ||
Simon Bruder | 54242cc943 | ||
Simon Bruder | 2b9bb92757 | ||
Simon Bruder | cb3401ff87 | ||
Simon Bruder | 552c4d3b2b | ||
Simon Bruder | 839fb8e514 | ||
Simon Bruder | 49aa48366a | ||
Simon Bruder | 3acc1eb0ce | ||
Simon Bruder | 821a352c49 | ||
Simon Bruder | 46afd7123c | ||
Simon Bruder | 6ac026a535 | ||
Simon Bruder | a1facf530f | ||
Simon Bruder | e5d82f7087 | ||
Simon Bruder | 14999b0f92 | ||
Simon Bruder | 971fda90c4 | ||
Simon Bruder | d20afbfe4c | ||
Simon Bruder | 7b473dad3a | ||
Simon Bruder | 1fcecb1f64 | ||
Simon Bruder | 8b9eb54806 | ||
Simon Bruder | a90fef89c0 | ||
Simon Bruder | 42a83bea7f | ||
Simon Bruder | 32b18bd005 | ||
Simon Bruder | 4fc2015ee9 | ||
Simon Bruder | a67ec1b22f | ||
Simon Bruder | aef0baf527 | ||
Simon Bruder | 11f7ac50ca | ||
Simon Bruder | 0c74cdbbdd | ||
Simon Bruder | 8771faa93c | ||
Simon Bruder | 11ec0ab428 | ||
Simon Bruder | 376dfa37de | ||
Simon Bruder | 5ee7108bd6 | ||
Simon Bruder | 0b9c9ea047 | ||
Simon Bruder | 8dafa364e0 | ||
Simon Bruder | 5e4d888da7 | ||
Simon Bruder | d0900f1cf8 | ||
Simon Bruder | faf9a044fd | ||
Simon Bruder | 00a919d6d7 | ||
Simon Bruder | f3d958c1a9 | ||
Simon Bruder | 34badc3638 | ||
Simon Bruder | 0d08f9c6db | ||
Simon Bruder | 4556ec6c73 | ||
Simon Bruder | 80f23f019b | ||
Simon Bruder | 35e6bf8185 | ||
Simon Bruder | c09d54513b | ||
Simon Bruder | 1dcaeb0aed | ||
Simon Bruder | 16d6aa2aa0 | ||
Simon Bruder | b26b004392 | ||
Simon Bruder | 6006e2cb46 | ||
Simon Bruder | ce6e2660d0 | ||
Simon Bruder | f546f737fe | ||
Simon Bruder | 2d0a2b7316 | ||
Simon Bruder | 7fdc470595 | ||
Simon Bruder | 7959abe5f0 | ||
Simon Bruder | 3c753e8852 | ||
Simon Bruder | fd37161a78 | ||
Simon Bruder | 12e24d0761 | ||
Simon Bruder | 298ef93ed5 | ||
Simon Bruder | 9ce76f591f | ||
Simon Bruder | 1de4af389b | ||
Simon Bruder | a58aa3ece4 | ||
Simon Bruder | 4d77cba8dc | ||
Simon Bruder | d863586f23 | ||
Simon Bruder | 20117566de | ||
Simon Bruder | 8442afae5c | ||
Simon Bruder | 43722b1177 | ||
Simon Bruder | 80e68848c5 | ||
Simon Bruder | fc6c997575 | ||
Simon Bruder | 02f2138294 | ||
Simon Bruder | 0ab3260240 | ||
Simon Bruder | 71a5ea7a0d | ||
Simon Bruder | 85a102f53c | ||
Simon Bruder | a8795cf97c | ||
Simon Bruder | e1b59d57ff | ||
Simon Bruder | 61d47861b5 | ||
Simon Bruder | 5ff547399c | ||
Simon Bruder | 97bd12353d | ||
Simon Bruder | 621d209680 | ||
Simon Bruder | a6ddd29a1b | ||
Simon Bruder | 2aa489853f | ||
Simon Bruder | 5d1ed0d770 | ||
Simon Bruder | de67fd9d63 | ||
Simon Bruder | 387947191d | ||
Simon Bruder | 740bffae9e | ||
Simon Bruder | b44acc2ffa | ||
Simon Bruder | 92772d1cc3 | ||
Simon Bruder | e6a0684bfe | ||
Simon Bruder | 80f33f9095 | ||
Simon Bruder | ce57c9a62c | ||
Simon Bruder | e4b10573d4 | ||
Simon Bruder | 8259b1455f | ||
Simon Bruder | c0efaa02ba | ||
Simon Bruder | e0efa77520 | ||
Simon Bruder | 44cc17db53 | ||
Simon Bruder | e94d0227fe | ||
Simon Bruder | b0d6861825 | ||
Simon Bruder | 56b9c6c37f | ||
Simon Bruder | ac81f66237 | ||
Simon Bruder | a196059da6 | ||
Simon Bruder | 4013206449 | ||
Simon Bruder | 6f31ded457 | ||
Simon Bruder | c918486622 | ||
Simon Bruder | 0fdfec4385 | ||
Simon Bruder | ef9731a080 | ||
Simon Bruder | de3f8f8909 | ||
Simon Bruder | e9dc4601ad | ||
Simon Bruder | 9025dfffb5 | ||
Simon Bruder | d3d41da2bc | ||
Simon Bruder | e80a0b0c07 | ||
Simon Bruder | 6492ad2d4c | ||
Simon Bruder | 91b3e97e48 | ||
Simon Bruder | 7d7da189d0 | ||
Simon Bruder | 6cb59d0149 | ||
Simon Bruder | 54288988de | ||
Simon Bruder | 091f6b0e14 | ||
Simon Bruder | ad0748ba1b | ||
Simon Bruder | 7450828b63 | ||
Simon Bruder | 10a63f585d | ||
Simon Bruder | 36c0c67e36 | ||
Simon Bruder | ea45b45c60 | ||
Simon Bruder | 0f135fc87b | ||
Simon Bruder | ab4ef486be | ||
Simon Bruder | d64f4a8741 | ||
Simon Bruder | 71209d0cc8 | ||
Simon Bruder | 652cdbd975 | ||
Simon Bruder | 004a879f46 | ||
Simon Bruder | ef2f20ee3b | ||
Simon Bruder | b0754833b4 | ||
Simon Bruder | 961b497609 | ||
Simon Bruder | 9afeb8527a | ||
Simon Bruder | ef78d4ec8e | ||
Simon Bruder | 0ba5f8c6fa | ||
Simon Bruder | 4af6a8fce1 | ||
Simon Bruder | 1562a38fd1 | ||
Simon Bruder | 2c8a291ae9 | ||
Simon Bruder | 531060668a | ||
Simon Bruder | e10394cd99 | ||
Simon Bruder | be8c942150 | ||
Simon Bruder | 7d4f84eda8 | ||
Simon Bruder | 9f70024257 | ||
Simon Bruder | e629ad86fb | ||
Simon Bruder | ebeba7c6fd | ||
Simon Bruder | a861fbd725 | ||
Simon Bruder | dc1698ffaa | ||
Simon Bruder | d72ce259cc | ||
Simon Bruder | d2d2a7234f | ||
Simon Bruder | 675f55e61f | ||
Simon Bruder | 7a5d16106a | ||
Simon Bruder | ca2136ef04 | ||
Simon Bruder | ec50bc210b | ||
Simon Bruder | 26f7ef981b | ||
Simon Bruder | d3ec5f4ba1 | ||
Simon Bruder | 9bbc4a2f7a | ||
Simon Bruder | c3a3d8a12a | ||
Simon Bruder | bb487bd528 | ||
Simon Bruder | 2bf9577b61 | ||
Simon Bruder | 10ced7f2bb | ||
Simon Bruder | 54610a130a | ||
Simon Bruder | d19bfb9c2c | ||
Simon Bruder | 440fc97f7f | ||
Simon Bruder | 51f814c70d | ||
Simon Bruder | 8a5a5e9a1c | ||
Simon Bruder | 8e02008cb4 | ||
Simon Bruder | df6c74819e | ||
Simon Bruder | 0bb095a2bf | ||
Simon Bruder | 09618443eb | ||
Simon Bruder | 84c72583fe | ||
Simon Bruder | 400b55a293 | ||
Simon Bruder | af036e88db | ||
Simon Bruder | d704dab620 | ||
Simon Bruder | 5b5bf546b3 | ||
Simon Bruder | ef790a285a | ||
Simon Bruder | 236ac3488a | ||
Simon Bruder | 267eecf000 | ||
Simon Bruder | 0ddb38e8f9 | ||
Simon Bruder | 36da32ff33 | ||
Simon Bruder | 1674ee980b | ||
Simon Bruder | 4c60f99b76 | ||
Simon Bruder | 7d19c9b039 | ||
Simon Bruder | 36111cfd8b | ||
Simon Bruder | 8a339c51a2 | ||
Simon Bruder | 78f4579556 | ||
Simon Bruder | 85546a5ab7 | ||
Simon Bruder | 4d6530a56d | ||
Simon Bruder | 7fd7f98708 | ||
Simon Bruder | 5de2acd1f0 | ||
Simon Bruder | bcee4c3243 | ||
Simon Bruder | 11affcf8cb | ||
Simon Bruder | 08b8fce2d4 | ||
Simon Bruder | 4b81f9163a | ||
Simon Bruder | 3e9593eb78 | ||
Simon Bruder | 7f5bf88fd7 | ||
Simon Bruder | ce62b43bc8 | ||
Simon Bruder | 5376c2994f | ||
Simon Bruder | 9d27b71588 | ||
Simon Bruder | bd9f25c995 | ||
Simon Bruder | b51bff724f | ||
Simon Bruder | 4af55ba3e9 | ||
Simon Bruder | e070cb9107 | ||
Simon Bruder | 438fad34fb | ||
Simon Bruder | d09fb92fac | ||
Simon Bruder | cd30750fdc | ||
Simon Bruder | 942a5ffb04 | ||
Simon Bruder | b9abd825cb | ||
Simon Bruder | 6cff58fcb0 | ||
Simon Bruder | ec09bbf6c6 | ||
Simon Bruder | 6af6e2b2d3 | ||
Simon Bruder | 602573cd34 | ||
Simon Bruder | bb8c54065a | ||
Simon Bruder | 746581ceba | ||
Simon Bruder | bed82e297c | ||
Simon Bruder | 62a17a54b4 | ||
Simon Bruder | feb82fca2e | ||
Simon Bruder | 5d31f32df8 | ||
Simon Bruder | 5dff1a426f | ||
Simon Bruder | 8d9e3af211 | ||
Simon Bruder | 07d4260b95 | ||
Simon Bruder | 4ece15d0f6 | ||
Simon Bruder | 596b65b153 | ||
Simon Bruder | 68fbc9e185 | ||
Simon Bruder | 9dbd7f9c85 | ||
Simon Bruder | 4a8a7e0a4f | ||
Simon Bruder | b595aceb7c | ||
Simon Bruder | aaaeb56f18 | ||
Simon Bruder | 41f8d468b6 | ||
Simon Bruder | a102f691a6 | ||
Simon Bruder | d253f74a06 | ||
Simon Bruder | 5c4284d68c | ||
Simon Bruder | 6f20d6300d | ||
Simon Bruder | d9a04d1f60 | ||
Simon Bruder | 97974a9616 | ||
Simon Bruder | 4e3c1ad6fa | ||
Simon Bruder | 3b96a823ee | ||
Simon Bruder | c26539e607 | ||
Simon Bruder | 37f95b3d79 | ||
Simon Bruder | 1b08afd515 | ||
Simon Bruder | 0212f2adbd | ||
Simon Bruder | ac7e1c1123 | ||
Simon Bruder | 891697f80c | ||
Simon Bruder | e186893654 | ||
Simon Bruder | ce7425d8c4 | ||
Simon Bruder | 94b2746018 | ||
Simon Bruder | 2897451a65 | ||
Simon Bruder | 8b1b969aa9 | ||
Simon Bruder | 98a4f345eb | ||
Simon Bruder | 0ae96653a5 | ||
Simon Bruder | 3b6a9dfc40 | ||
Simon Bruder | 6459a2a7ef | ||
Simon Bruder | b6297d0153 | ||
Simon Bruder | bc2851de6b | ||
Simon Bruder | 9be9148da8 | ||
Simon Bruder | 15075a818d | ||
Simon Bruder | 2d74dac8c0 | ||
Simon Bruder | a32b45ebb7 | ||
Simon Bruder | e94c72e42e | ||
Simon Bruder | 1521f10806 | ||
Simon Bruder | 50f0968738 | ||
Simon Bruder | 5491ef4817 | ||
Simon Bruder | 2484140e59 | ||
Simon Bruder | a7ad88a5ec | ||
Simon Bruder | cb8a8f3c8d | ||
Simon Bruder | 55099f1884 | ||
Simon Bruder | c8b7a9c8e9 | ||
Simon Bruder | c1992958bf | ||
Simon Bruder | 90c2ab9d0a | ||
Simon Bruder | 9f8c80029d | ||
Simon Bruder | aa6458f4bf | ||
Simon Bruder | 57de9427ea | ||
Simon Bruder | d2ee32fdb1 | ||
Simon Bruder | fa1c274248 | ||
Simon Bruder | 5e8fb02b78 | ||
Simon Bruder | 58c72c3200 | ||
Simon Bruder | 320f438d02 | ||
Simon Bruder | 8a0f3c5f6b | ||
Simon Bruder | 187cc904bc | ||
Simon Bruder | e723e75ca8 | ||
Simon Bruder | 08d65e5ae5 | ||
Simon Bruder | 041262fc7a | ||
Simon Bruder | 9ec9b078dd | ||
Simon Bruder | f7a27d623b | ||
Simon Bruder | 33ff48da8e | ||
Simon Bruder | 29af8010a2 | ||
Simon Bruder | 7cb3142526 | ||
Simon Bruder | 470ade7e2b | ||
Simon Bruder | 3b2f41f18a | ||
Simon Bruder | 168e492c12 | ||
Simon Bruder | b55144906f | ||
Simon Bruder | a3d1fa50b1 | ||
Simon Bruder | 9b9f574d52 | ||
Simon Bruder | 5df5cf4068 | ||
Simon Bruder | 57652d8a79 | ||
Simon Bruder | 966667b87f | ||
Simon Bruder | db54dfaed1 | ||
Simon Bruder | d6bddf40c0 | ||
Simon Bruder | 429144166d | ||
Simon Bruder | 3a5568a136 | ||
Simon Bruder | a3c954fa01 | ||
Simon Bruder | 922a359497 | ||
Simon Bruder | e0d50e0435 | ||
Simon Bruder | ee31882b9a | ||
Simon Bruder | 515939677b | ||
Simon Bruder | d73da1a131 | ||
Simon Bruder | 3da67f7576 | ||
Simon Bruder | e8626ba27a | ||
Simon Bruder | 0c081d9805 | ||
Simon Bruder | 786edd1caf | ||
Simon Bruder | 07f152cb20 | ||
Simon Bruder | 878bdd30d5 | ||
Simon Bruder | d1cf0f698f | ||
Simon Bruder | 70ee44fbc5 | ||
Simon Bruder | f388995ef6 | ||
Simon Bruder | df303dcc2b | ||
Simon Bruder | d239f2ad5e | ||
Simon Bruder | 442297ec85 | ||
Simon Bruder | 724bcd31c5 | ||
Simon Bruder | b6e2d2f347 | ||
Simon Bruder | e72d225a0a | ||
Simon Bruder | 3ddb86d504 | ||
Simon Bruder | 542a89ef57 | ||
Simon Bruder | 65931f8b85 | ||
Simon Bruder | cbf2536e32 | ||
Simon Bruder | 270f20d05b | ||
Simon Bruder | bdda31a807 | ||
Simon Bruder | 4d474043a0 | ||
Simon Bruder | da6788d036 | ||
Simon Bruder | 380c5b0ec5 | ||
Simon Bruder | 4923f70389 | ||
Simon Bruder | c0a130fa59 | ||
Simon Bruder | a962fea3a8 | ||
Simon Bruder | 05d2529db7 | ||
Simon Bruder | 2bbe4e715b | ||
Simon Bruder | 57403a2d52 | ||
Simon Bruder | ceda178acf | ||
Simon Bruder | e17aa4bc6b | ||
Simon Bruder | d8f75f167a | ||
Simon Bruder | c7349c4939 | ||
Simon Bruder | b3cc7cf907 | ||
Simon Bruder | c0f7daa411 | ||
Simon Bruder | 081e731be2 | ||
Simon Bruder | eccea38759 | ||
Simon Bruder | fd11348b56 | ||
Simon Bruder | c30776cea6 | ||
Simon Bruder | 5c27e0d423 | ||
Simon Bruder | 9c19647e76 | ||
Simon Bruder | 90feb2e3be | ||
Simon Bruder | 86348d4c60 | ||
Simon Bruder | 8392b9937a | ||
Simon Bruder | b2449c3fe6 | ||
Simon Bruder | 83f1c69713 | ||
Simon Bruder | d7272e9db3 | ||
Simon Bruder | 6a8904011a | ||
Simon Bruder | 3934c84644 | ||
Simon Bruder | 209ba3c5f6 | ||
Simon Bruder | c77328af22 | ||
Simon Bruder | f03c1daa31 | ||
Simon Bruder | a745d7353e | ||
Simon Bruder | b855ed533d | ||
Simon Bruder | b3d28b4752 | ||
Simon Bruder | 1103dd5000 | ||
Simon Bruder | 0ecdb8c4f7 | ||
Simon Bruder | e73aedb584 | ||
Simon Bruder | 9570d63d15 | ||
Simon Bruder | 13a80e122b | ||
Simon Bruder | 790c4d03c0 | ||
Simon Bruder | 2a4e358502 | ||
Simon Bruder | 13876617f5 | ||
Simon Bruder | 785bb2214b | ||
Simon Bruder | be7e67cf1f | ||
Simon Bruder | c921c2802a | ||
Simon Bruder | 5dfe492baf | ||
Simon Bruder | 65603effa9 | ||
Simon Bruder | 94f3aae5b9 | ||
Simon Bruder | e0ef586e5e | ||
Simon Bruder | ceff40f84d | ||
Simon Bruder | 0ec1fb5257 | ||
Simon Bruder | dd93b4c748 | ||
Simon Bruder | e21c769524 | ||
Simon Bruder | 16c710d4a5 | ||
Simon Bruder | 27285a098f | ||
Simon Bruder | f827456d0c | ||
Simon Bruder | b00498f23d | ||
Simon Bruder | eb97e936ed | ||
Simon Bruder | e8a6110521 | ||
Simon Bruder | 1a7ef37376 | ||
Simon Bruder | 474cc7d0f7 | ||
Simon Bruder | 8689ace70d | ||
Simon Bruder | 3fc9846bf7 | ||
Simon Bruder | 3ba514c502 | ||
Simon Bruder | 15cdd42845 | ||
Simon Bruder | 29c6d37142 | ||
Simon Bruder | 8c92c1b792 | ||
Simon Bruder | d6d2857322 | ||
Simon Bruder | 78c9a2cab9 | ||
Simon Bruder | bd8b809486 | ||
Simon Bruder | dde17cf4ec | ||
Simon Bruder | b8601e6fd3 | ||
Simon Bruder | f7287365ff | ||
Simon Bruder | 8037f5eb5e | ||
Simon Bruder | 1bf141ce03 | ||
Simon Bruder | 75a91e9116 | ||
Simon Bruder | 9b5a991074 | ||
Simon Bruder | 34ec244fcc | ||
Simon Bruder | 62f1dbe30f | ||
Simon Bruder | 9c62905442 | ||
Simon Bruder | e45b18abd0 | ||
Simon Bruder | 335f2908e7 | ||
Simon Bruder | 5ed071c0ed | ||
Simon Bruder | 998d47fd1a | ||
Simon Bruder | bfd192b2a8 | ||
Simon Bruder | 1437601d5a | ||
Simon Bruder | 6a114a6b7f | ||
Simon Bruder | 520d750404 | ||
Simon Bruder | d8514ab12c | ||
Simon Bruder | 43fbc20020 | ||
Simon Bruder | daf867dcb9 | ||
Simon Bruder | 34c801c7e9 | ||
Simon Bruder | cce86ac2c9 | ||
Simon Bruder | a02d3cb883 | ||
Simon Bruder | f211bae4e2 | ||
Simon Bruder | 3304c8e62e | ||
Simon Bruder | ebddfd35ba | ||
Simon Bruder | 1a63539df8 | ||
Simon Bruder | 4664265bb0 | ||
Simon Bruder | d61fc70f23 | ||
Simon Bruder | 82d5a24dfa | ||
Simon Bruder | 241bc188cb | ||
Simon Bruder | 05a72217aa | ||
Simon Bruder | 55fb2cfdda | ||
Simon Bruder | e7c6406820 | ||
Simon Bruder | 204962d0f3 | ||
Simon Bruder | 67fe507a2d | ||
Simon Bruder | d6df163d2e | ||
Simon Bruder | 603a006df8 | ||
Simon Bruder | bcbd5e772a | ||
Simon Bruder | 617fc28668 | ||
Simon Bruder | 5ecebf4435 | ||
Simon Bruder | 428e8103d9 | ||
Simon Bruder | d8b8e5de93 | ||
Simon Bruder | e5f90116e8 | ||
Simon Bruder | 64ef37badd | ||
Simon Bruder | c1283b6ffa | ||
Simon Bruder | 80cae99fef |
Binary file not shown.
2
.gitattributes
vendored
2
.gitattributes
vendored
|
@ -1,4 +1,6 @@
|
|||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.svg filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
**/secrets/** filter=git-crypt diff=git-crypt
|
||||
**/secrets.yaml diff=sops
|
||||
|
|
48
.sops.yaml
Normal file
48
.sops.yaml
Normal file
|
@ -0,0 +1,48 @@
|
|||
keys:
|
||||
- &simon 47E7559E037A35652DBBF8AA8D3C82F9F309F8EC
|
||||
- &nunotaba 8C5091AEA213FB0642BD46F943EE19743FAC1D5C
|
||||
- &sayuri 17FEEBB45E4245330507C960653378F10CA6E00A
|
||||
- &vueko BB046D773F54739757553A053CB9B8EFD7FED749
|
||||
- &fuuko 2372651C56E22972C2D9F3F569C8187C9C43754E
|
||||
- &mayushii 23EEDF49AAF1B41DCD1CD10F44A37FA8C15053B3
|
||||
- &yuzuru F4B5F6971A1FAEA1216FCE1C6745A652A31186DB
|
||||
creation_rules:
|
||||
- path_regex: machines/nunotaba/secrets\.yaml$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *simon
|
||||
- *nunotaba
|
||||
- path_regex: machines/sayuri/secrets\.yaml$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *simon
|
||||
- *sayuri
|
||||
- path_regex: machines/vueko/secrets\.yaml$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *simon
|
||||
- *vueko
|
||||
- path_regex: machines/fuuko/secrets\.yaml$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *simon
|
||||
- *fuuko
|
||||
- path_regex: machines/mayushii/secrets\.yaml$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *simon
|
||||
- *mayushii
|
||||
- path_regex: machines/yuzuru/secrets\.yaml$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *simon
|
||||
- *yuzuru
|
||||
- path_regex: secrets\.yaml$
|
||||
key_groups:
|
||||
- pgp:
|
||||
- *simon
|
||||
- *nunotaba
|
||||
- *sayuri
|
||||
- *vueko
|
||||
- *fuuko
|
||||
- *mayushii
|
133
README.md
133
README.md
|
@ -1,17 +1,45 @@
|
|||
# NixOS configuration
|
||||
|
||||
## Structure
|
||||
|
||||
* `machines`: Machine-specific configuration
|
||||
+ `README.md`: Short overview of the hardware and usage of the machine
|
||||
+ `configuration.nix`: Main configuration
|
||||
+ `hardware-configuration.nix`: Hardware-specific configuration. It should
|
||||
not depend on any modules or files from this repository, since it is used
|
||||
for initial setup.
|
||||
+ `services`: Non-trivial machine-specific configuration related to a
|
||||
specific service the machine provides.
|
||||
+ `secrets`: Nix expressions that include information that is not meant to
|
||||
be visible to everyone (e.g. accounts, password hashes, private
|
||||
information etc.) or secrets for services that don’t provide any other
|
||||
(easy) way of specifying them and whose secrets leaking does not pose a
|
||||
huge threat
|
||||
* `modules`: Custom modules. Many are activated by default, since I want them
|
||||
on all systems.
|
||||
* `pkgs`: My nixpkgs overlay
|
||||
* `users/simon`: [home-manager](https://github.com/nix-community/home-manager)
|
||||
configuration
|
||||
|
||||
Secrets are managed with [sops-nix](https://github.com/Mic92/sops-nix).
|
||||
|
||||
Machines can be deployed with `nix run .#deploy/hostname`, LUKS encrypted
|
||||
systems can be unlocked over network with `nix run .#unlock/hostname`.
|
||||
|
||||
## How to install
|
||||
|
||||
This guide describes how to install this configuration (or any NixOS
|
||||
configuration) with GPT and legacy (BIOS) boot.
|
||||
This guide describes how to install this configuration with GPT and BIOS boot.
|
||||
It is not a one-fits-all guide, but the base for what I use for interactive
|
||||
systems. Servers and specialised systems may need a different setup (e. g. swap
|
||||
with random luks passphrase and no LVM).
|
||||
|
||||
If you do not have a wired connection, first set up wifi
|
||||
Set up wifi if no wired connection is available:
|
||||
|
||||
wpa_passphrase "SSID" "PSK" | sudo wpa_supplicant -B -i wlp4s0 -c/dev/stdin
|
||||
wpa_passphrase "SSID" "PSK" | wpa_supplicant -B -i wlp4s0 -c/dev/stdin
|
||||
|
||||
Create the partition table (enter the indented lines in the repl).
|
||||
Create the partition table (enter the indented lines in the repl):
|
||||
|
||||
sudo parted /dev/sdX
|
||||
parted /dev/sdX
|
||||
mktable GPT
|
||||
mkpart primary 1MiB 2MiB
|
||||
mkpart primary 2MiB 500MiB
|
||||
|
@ -20,69 +48,76 @@ Create the partition table (enter the indented lines in the repl).
|
|||
disk_toggle pmbr_boot
|
||||
quit
|
||||
|
||||
Format encrypted partition and open it
|
||||
On UEFI:
|
||||
|
||||
sudo cryptsetup luksFormat /dev/sdX3
|
||||
sudo cryptsetup luksOpen /dev/sdX3 HOSTNAME-pv
|
||||
parted /dev/nvmeXnY
|
||||
mktable GPT
|
||||
mkpart ESP 1MiB 512MiB
|
||||
mkpart root 512MiB 100%
|
||||
set 1 esp on
|
||||
quit
|
||||
|
||||
Create LVM (replace `8G` with desired swap size)
|
||||
Format encrypted partition and open it:
|
||||
|
||||
sudo pvcreate /dev/mapper/HOSTNAME-pv
|
||||
sudo vgcreate HOSTNAME-vg /dev/mapper/HOSTNAME-pv
|
||||
sudo lvcreate -L 8G -n swap HOSTNAME-vg
|
||||
sudo lvcreate -l '100%FREE' -n root HOSTNAME-vg
|
||||
cryptsetup luksFormat --type luks2 /dev/sdX3
|
||||
cryptsetup open --type luks2 /dev/sdX3 HOSTNAME-pv
|
||||
|
||||
Create LVM (replace `8G` with desired swap size):
|
||||
|
||||
pvcreate /dev/mapper/HOSTNAME-pv
|
||||
vgcreate HOSTNAME-vg /dev/mapper/HOSTNAME-pv
|
||||
lvcreate -L 8G -n swap HOSTNAME-vg
|
||||
lvcreate -l '100%FREE' -n root HOSTNAME-vg
|
||||
|
||||
**Hint**: If you have to reboot to the installation system later because
|
||||
something went wrong and you need access to the LVM (but don’t know LVM), do
|
||||
the following after opening the luks partition: `sudo vgchange -ay`
|
||||
the following after opening the luks partition: `vgchange -ay`.
|
||||
|
||||
Create filesystems
|
||||
Create filesystems:
|
||||
|
||||
sudo mkfs.ext2 /dev/sdX2
|
||||
sudo mkfs.ext4 -L root /dev/HOSTNAME-vg/root
|
||||
sudo mkswap -L swap /dev/HOSTNAME-vg/swap
|
||||
mkfs.ext2 /dev/sdX2
|
||||
mkfs.btrfs -L root /dev/HOSTNAME-vg/root
|
||||
mkswap -L swap /dev/HOSTNAME-vg/swap
|
||||
|
||||
Mount the file systems and activate swap
|
||||
On UEFI:
|
||||
|
||||
sudo mount /dev/HOSTNAME-vg/root /mnt
|
||||
sudo mkdir /mnt/boot
|
||||
sudo mount /dev/sdX2 /mnt/boot
|
||||
sudo swapon /dev/HOSTNAME-vg/swap
|
||||
mkfs.fat -F 32 -n boot /dev/nvmeXnYpZ
|
||||
mkfs.btrfs -L root /dev/HOSTNAME-vg/root
|
||||
mkswap -L swap /dev/HOSTNAME-vg/swap
|
||||
|
||||
Create the configuration (see [below](#how-to-add-new-device)) and copy this
|
||||
repository to your new home directory (e.g. `/mnt/home/simon/nixos`).
|
||||
Mount the file systems and activate swap:
|
||||
|
||||
Add a symlink as the global configuration
|
||||
|
||||
sudo mkdir -p /mnt/etc/nixos/
|
||||
sudo ln -s ../../home/simon/nixos/machines/nunotaba/configuration.nix /mnt/etc/nixos/configuration.nix
|
||||
mount /dev/HOSTNAME-vg/root /mnt
|
||||
mkdir /mnt/boot
|
||||
mount /dev/sdX2 /mnt/boot
|
||||
swapon /dev/HOSTNAME-vg/swap
|
||||
|
||||
Generate hardware configuration and copy hardware configuration to machine
|
||||
configuration
|
||||
configuration (skip this step if you already have a hardware-configuration for
|
||||
this machine):
|
||||
|
||||
sudo nixos-generate-config --root /mnt/
|
||||
sudo mv /mnt/etc/nixos/hardware-configuration.nix /mnt/home/simon/nixos/machines/nunotaba/hardware-configuration.nix
|
||||
sudo ln -s ../../home/simon/nixos/machines/nunotaba/hardware-configuration.nix /mnt/etc/nixos/hardware-configuration.nix
|
||||
nixos-generate-config --root /mnt/
|
||||
|
||||
Install NixOS
|
||||
sudo nixos-install --no-root-passwd
|
||||
Modify the hardware configuration as needed and add it to the machine
|
||||
configuration in this repository. If necessary, create the machine
|
||||
configuration first by basing it on an already existing configuration and
|
||||
adding an entry to `machines/default.nix`. Then copy this repository to the
|
||||
target machine and run (`--impure` is needed since `/mnt/nix/store` is not in
|
||||
`/nix/store`):
|
||||
|
||||
Enter the target as a container and set a user password
|
||||
nixos-install --impure --flake /path/to/repository#hostname
|
||||
|
||||
sudo cp /etc/resolv.conf /mnt/etc/ # see https://github.com/NixOS/nixpkgs/issues/39665
|
||||
nixos-enter
|
||||
passwd simon
|
||||
^D # nixos-enter
|
||||
sudo rm /mnt/etc/resolv.conf
|
||||
reboot
|
||||
Add the krops sentinel file:
|
||||
|
||||
## How to add new device
|
||||
mkdir -p /mnt/var/src
|
||||
touch /mnt/var/src/.populate
|
||||
|
||||
* Copy the config from the device that is similar to the new one
|
||||
* Import profiles/modules you want
|
||||
* Change settings in `configuration.nix`
|
||||
* Change secrets
|
||||
Reboot.
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](LICENSE)
|
||||
Unless otherwise noted in the specific files or directories,
|
||||
the files in this repository are licensed under the [MIT License](LICENSE).
|
||||
This only applies to the nix expressions, not the built system or package closures.
|
||||
Patches may also be licensed differently,
|
||||
since they may be derivative works of the packages to which they apply.
|
||||
|
|
60
deploy.nix
60
deploy.nix
|
@ -1,60 +0,0 @@
|
|||
let
|
||||
sources = import ./nix/sources.nix;
|
||||
|
||||
krops = sources.krops;
|
||||
lib = import "${krops}/lib";
|
||||
kropsPkgs = import "${krops}/pkgs" { };
|
||||
|
||||
kropsDeploy =
|
||||
{ hostname
|
||||
, target ? null
|
||||
, secrets ? true
|
||||
, extraSources ? { }
|
||||
}:
|
||||
let
|
||||
source = lib.evalSource [
|
||||
{
|
||||
nixpkgs.git = {
|
||||
ref = sources.nixpkgs.rev;
|
||||
url = https://github.com/NixOS/nixpkgs;
|
||||
shallow = true;
|
||||
};
|
||||
config.file = {
|
||||
path = toString ./.;
|
||||
filters = [
|
||||
{
|
||||
type = "exclude";
|
||||
pattern = ".git";
|
||||
}
|
||||
{
|
||||
type = "exclude";
|
||||
pattern = "*.qcow2";
|
||||
}
|
||||
];
|
||||
};
|
||||
nixos-config.symlink = "config/machines/${hostname}/configuration.nix";
|
||||
}
|
||||
(lib.mkIf secrets {
|
||||
secrets.pass = {
|
||||
dir = toString ~/.password-store;
|
||||
name = "nixos/machines/${hostname}";
|
||||
};
|
||||
})
|
||||
extraSources
|
||||
];
|
||||
in
|
||||
kropsPkgs.krops.writeDeploy "deploy-${hostname}" {
|
||||
source = source;
|
||||
target = lib.mkTarget (if target == null then "root@${hostname}" else target) // {
|
||||
extraOptions = [
|
||||
# force allocation of tty to allow aborting with ^C and to show build progress
|
||||
"-t"
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
builtins.mapAttrs (hostname: configuration: kropsDeploy ({ inherit hostname; } // configuration))
|
||||
{
|
||||
nunotaba = { };
|
||||
sayuri = { };
|
||||
}
|
286
flake.lock
Normal file
286
flake.lock
Normal file
|
@ -0,0 +1,286 @@
|
|||
{
|
||||
"nodes": {
|
||||
"AriaNg": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1641157028,
|
||||
"narHash": "sha256-Da9GR1v2niJCU02NnC3aKLDMkUDEN2GULFgBQAT3tsY=",
|
||||
"ref": "master",
|
||||
"rev": "ea678a781a34613cf67c9c81d4f176d531f40630",
|
||||
"revCount": 604,
|
||||
"type": "git",
|
||||
"url": "https://git.sbruder.de/simon/AriaNg"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://git.sbruder.de/simon/AriaNg"
|
||||
}
|
||||
},
|
||||
"aria2_exporter": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1621073204,
|
||||
"narHash": "sha256-NXjp8rgWsNwX3WR8F11TAGxYoi8QZjrmuc5nsj/IjdQ=",
|
||||
"owner": "sbruder",
|
||||
"repo": "aria2_exporter",
|
||||
"rev": "4b170f34720be5da2d2b8e791ff891624fe40e51",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "sbruder",
|
||||
"repo": "aria2_exporter",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"bang-evaluator": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1627835028,
|
||||
"narHash": "sha256-LHTdNog+0EmRn+4DIz451vvQ2EeC8KwyV3/8JpX9yiw=",
|
||||
"ref": "master",
|
||||
"rev": "7fc3d5019c907566abbad8f84ba9555a5786bd01",
|
||||
"revCount": 52,
|
||||
"type": "git",
|
||||
"url": "https://git.sbruder.de/simon/bangs"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://git.sbruder.de/simon/bangs"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1638122382,
|
||||
"narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "74f7e4319258e287b0f9cb95426c9853b282730b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1639871969,
|
||||
"narHash": "sha256-6feWUnMygRzA9tzkrfAzpA5/NBYg75bkFxnqb1DtD7E=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "697cc8c68ed6a606296efbbe9614c32537078756",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"ref": "release-21.11",
|
||||
"repo": "home-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"infinisilSystem": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1626615686,
|
||||
"narHash": "sha256-eXt4eon7oEg1gBUC8myZNACmDisgsQOAHGlnDhyG6zk=",
|
||||
"owner": "Infinisil",
|
||||
"repo": "system",
|
||||
"rev": "f1fd247eca84abccbad3b57da39454702d7ef2c6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Infinisil",
|
||||
"repo": "system",
|
||||
"rev": "f1fd247eca84abccbad3b57da39454702d7ef2c6",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"krops": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1632420452,
|
||||
"narHash": "sha256-ncK6vABW/Ku9XI0kqj1otarUfblryoQzSaOCnaZ0oSs=",
|
||||
"owner": "Mic92",
|
||||
"repo": "krops",
|
||||
"rev": "0388970c568905fedcbf429e5745aacd4f7a6633",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Mic92",
|
||||
"repo": "krops",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-pre-commit-hooks": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1639823344,
|
||||
"narHash": "sha256-jlsQb2y6A5dB1R0wVPLOfDGM0wLyfYqEJNzMtXuzCXw=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "ff9c0b459ddc4b79c06e19d44251daa8e9cd1746",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"ref": "master",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1641965797,
|
||||
"narHash": "sha256-AfxfIzAZbt9aAzpVBn0Bwhd/M4Wix7G91kEjm9H6FPo=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "87a35a0d58f546dc23f37b4f6af575d0e4be6a7a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "master",
|
||||
"repo": "nixos-hardware",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1641870998,
|
||||
"narHash": "sha256-6HkxR2WZsm37VoQS7jgp6Omd71iw6t1kP8bDbaqCDuI=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "386234e2a61e1e8acf94dfa3a3d3ca19a6776efb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-21.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-overlay": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"flake-utils"
|
||||
],
|
||||
"nix-pre-commit-hooks": [
|
||||
"nix-pre-commit-hooks"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1638388788,
|
||||
"narHash": "sha256-4t+iDoZO9X8fM1cWfbCbsIagRN0PRkpGcJKaMLJE7yc=",
|
||||
"ref": "master",
|
||||
"rev": "72d323ca0410a08abc2d981b812c5cd0fd3338bf",
|
||||
"revCount": 38,
|
||||
"type": "git",
|
||||
"url": "https://git.sbruder.de/simon/nixpkgs-overlay"
|
||||
},
|
||||
"original": {
|
||||
"type": "git",
|
||||
"url": "https://git.sbruder.de/simon/nixpkgs-overlay"
|
||||
}
|
||||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1641887635,
|
||||
"narHash": "sha256-kDGpufwzVaiGe5e1sBUBPo9f1YN+nYHJlYqCaVpZTQQ=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b2737d4980a17cc2b7d600d7d0b32fd7333aca88",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"AriaNg": "AriaNg",
|
||||
"aria2_exporter": "aria2_exporter",
|
||||
"bang-evaluator": "bang-evaluator",
|
||||
"flake-utils": "flake-utils",
|
||||
"home-manager": "home-manager",
|
||||
"infinisilSystem": "infinisilSystem",
|
||||
"krops": "krops",
|
||||
"nix-pre-commit-hooks": "nix-pre-commit-hooks",
|
||||
"nixos-hardware": "nixos-hardware",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-overlay": "nixpkgs-overlay",
|
||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||
"sops-nix": "sops-nix"
|
||||
}
|
||||
},
|
||||
"sops-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1641374494,
|
||||
"narHash": "sha256-a56G6Um43+0+n+yNYhRCh/mSvDdRVzQHSKcFaDEB9/8=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "7edb4b080023ef12f39262a3aa7aab31015a7a0e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
217
flake.nix
Normal file
217
flake.nix
Normal file
|
@ -0,0 +1,217 @@
|
|||
{
|
||||
description = "NixOS system configuration";
|
||||
|
||||
inputs = {
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-21.11";
|
||||
nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
|
||||
home-manager.url = "github:nix-community/home-manager/release-21.11";
|
||||
home-manager.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
krops.url = "github:Mic92/krops";
|
||||
krops.inputs.flake-utils.follows = "flake-utils";
|
||||
krops.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
nixos-hardware.url = "github:nixos/nixos-hardware/master";
|
||||
|
||||
nix-pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix/master";
|
||||
nix-pre-commit-hooks.inputs.flake-utils.follows = "flake-utils";
|
||||
nix-pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
sops-nix.url = "github:Mic92/sops-nix";
|
||||
sops-nix.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
infinisilSystem.url = "github:Infinisil/system/f1fd247eca84abccbad3b57da39454702d7ef2c6";
|
||||
infinisilSystem.flake = false;
|
||||
|
||||
nixpkgs-overlay.url = "git+https://git.sbruder.de/simon/nixpkgs-overlay";
|
||||
nixpkgs-overlay.inputs.flake-utils.follows = "flake-utils";
|
||||
nixpkgs-overlay.inputs.nixpkgs.follows = "nixpkgs";
|
||||
nixpkgs-overlay.inputs.nix-pre-commit-hooks.follows = "nix-pre-commit-hooks";
|
||||
|
||||
bang-evaluator.url = "git+https://git.sbruder.de/simon/bangs";
|
||||
bang-evaluator.inputs.flake-utils.follows = "flake-utils";
|
||||
bang-evaluator.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
aria2_exporter.url = "github:sbruder/aria2_exporter";
|
||||
aria2_exporter.inputs.flake-utils.follows = "flake-utils";
|
||||
aria2_exporter.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
AriaNg.url = "git+https://git.sbruder.de/simon/AriaNg";
|
||||
AriaNg.inputs.flake-utils.follows = "flake-utils";
|
||||
AriaNg.inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
outputs =
|
||||
{ self
|
||||
, flake-utils
|
||||
, krops
|
||||
, nix-pre-commit-hooks
|
||||
, nixpkgs
|
||||
, nixpkgs-overlay
|
||||
, ...
|
||||
}@inputs: flake-utils.lib.eachDefaultSystem
|
||||
(system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
inherit (pkgs) lib;
|
||||
in
|
||||
{
|
||||
checks = {
|
||||
pre-commit-check = nix-pre-commit-hooks.lib.${system}.run {
|
||||
src = self;
|
||||
hooks = {
|
||||
black.enable = true;
|
||||
nixpkgs-fmt.enable = true;
|
||||
shellcheck.enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
apps = lib.mapAttrs
|
||||
(name: program: { type = "app"; program = toString program; })
|
||||
(flake-utils.lib.flattenTree {
|
||||
deploy = lib.recurseIntoAttrs (lib.mapAttrs
|
||||
(hostname: machine:
|
||||
let
|
||||
inherit (krops.packages.${system}) writeCommand;
|
||||
inherit (krops) lib;
|
||||
in
|
||||
writeCommand "deploy-${hostname}" {
|
||||
target = lib.mkTarget "root@${machine.config.deployment.targetHost}" // {
|
||||
extraOptions = [
|
||||
# force allocation of tty to allow aborting with ^C and to show build progress
|
||||
"-t"
|
||||
];
|
||||
};
|
||||
source = lib.evalSource (lib.singleton {
|
||||
config.file = {
|
||||
path = toString self;
|
||||
useChecksum = true;
|
||||
filters = [
|
||||
{
|
||||
type = "include";
|
||||
pattern = "/machines/${hostname}/";
|
||||
}
|
||||
{
|
||||
type = "exclude";
|
||||
pattern = "/machines/*/";
|
||||
}
|
||||
];
|
||||
};
|
||||
});
|
||||
command = targetPath: ''
|
||||
nixos-rebuild switch --flake ${targetPath}/config -L --keep-going
|
||||
'';
|
||||
}
|
||||
)
|
||||
self.nixosConfigurations);
|
||||
|
||||
deploy-local = lib.recurseIntoAttrs (lib.mapAttrs
|
||||
(hostname: machine: pkgs.writeShellScript "deploy-local-${hostname}" ''
|
||||
${pkgs.nixos-rebuild.override { nix = pkgs.nixFlakes; }}/bin/nixos-rebuild \
|
||||
switch \
|
||||
--flake .#${hostname} \
|
||||
-L \
|
||||
--build-host localhost \
|
||||
--target-host root@${machine.config.deployment.targetHost} \
|
||||
--use-substitutes
|
||||
'')
|
||||
self.nixosConfigurations);
|
||||
|
||||
unlock = lib.recurseIntoAttrs (lib.mapAttrs
|
||||
(hostname: machine:
|
||||
let
|
||||
inherit (machine.config.deployment)
|
||||
targetHost
|
||||
unlockOverV4;
|
||||
in
|
||||
pkgs.writeShellScript "unlock-${hostname}" ''
|
||||
set -exo pipefail
|
||||
# opening luks fails if gpg-agent is not unlocked yet
|
||||
pass "devices/${hostname}/luks" >/dev/null
|
||||
ssh \
|
||||
${lib.optionalString unlockOverV4 "-4"} \
|
||||
-p 2222 \
|
||||
"root@$(${pkgs.dnsutils}/bin/dig \
|
||||
+short \
|
||||
@${if unlockOverV4 then "8.8.8.8" else "2001:4860:4860::8888"} \
|
||||
${targetHost} \
|
||||
${if unlockOverV4 then "A" else "AAAA"})" \
|
||||
"cat > /crypt-ramfs/passphrase" < <(pass "devices/${hostname}/luks")
|
||||
'')
|
||||
self.nixosConfigurations);
|
||||
|
||||
showKeyFingerprint = pkgs.writeShellScript "show-key-fingerprint" ''
|
||||
gpg --with-fingerprint --with-colons --show-key "keys/''${1}.asc" | awk -F: '$1 == "fpr" { print $10; exit }'
|
||||
'';
|
||||
|
||||
});
|
||||
|
||||
devShell = pkgs.mkShell {
|
||||
buildInputs = (with pkgs; [
|
||||
black
|
||||
nixpkgs-fmt
|
||||
shellcheck
|
||||
sops
|
||||
ssh-to-pgp
|
||||
]);
|
||||
|
||||
shellHook = ''
|
||||
find ${./keys} -type f -print0 | xargs -0 ${pkgs.gnupg}/bin/gpg --quiet --import
|
||||
'' + self.checks.${system}.pre-commit-check.shellHook;
|
||||
};
|
||||
}) // {
|
||||
overlay = import ./pkgs;
|
||||
|
||||
nixosConfigurations = nixpkgs.lib.mapAttrs
|
||||
(hostname: { system
|
||||
, extraModules ? [ ]
|
||||
, targetHost ? hostname
|
||||
, unlockOverV4 ? true
|
||||
, nixpkgs ? inputs.nixpkgs
|
||||
}: nixpkgs.lib.nixosSystem rec {
|
||||
inherit system;
|
||||
|
||||
modules = [
|
||||
(./machines + "/${hostname}/configuration.nix")
|
||||
|
||||
{
|
||||
_module.args.inputs = inputs;
|
||||
}
|
||||
|
||||
# deployment settings
|
||||
({ lib, ... }: {
|
||||
options.deployment = {
|
||||
targetHost = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
};
|
||||
unlockOverV4 = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
description = "Whether to unlock the host over IPv4 (only)";
|
||||
};
|
||||
};
|
||||
config.deployment = {
|
||||
inherit
|
||||
targetHost
|
||||
unlockOverV4;
|
||||
};
|
||||
})
|
||||
] ++ (with inputs; [
|
||||
home-manager.nixosModules.home-manager
|
||||
sops-nix.nixosModules.sops
|
||||
|
||||
aria2_exporter.nixosModules.aria2_exporter
|
||||
bang-evaluator.nixosModules.bang-evaluator
|
||||
]) ++ (builtins.attrValues nixpkgs-overlay.nixosModules)
|
||||
++ extraModules;
|
||||
})
|
||||
(import ./machines inputs);
|
||||
};
|
||||
}
|
28
keys/machines/fuuko.asc
Normal file
28
keys/machines/fuuko.asc
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
xsFNBAAAAAABEACkl9IfFWt7bGRtnJmDsv3sfotEQZusmFA6d9+Lh3J3Z5Ekx1Yz
|
||||
wIf26Y2MgOtxv8AJJ8QW13wH8/NOrySTPUaaQwjmkiv+7Hp3Ez7uoSg7BRrUXVez
|
||||
oo6dIStda5rNmx1ClYnzBVu0q54/mOayYWxeJOTl1YVKr7cSx2jcV+h5vEMZYeym
|
||||
AkHGNoFz83dguwNWTZvURjp6B65G84w3YuZyG0YHeQ8Lr0gCJDEmrP2NzIuXeGWy
|
||||
VEaE4XAUOF/9T+WVkuQmz6Drnqpw59Wc/J51Z2bz/2KL1oI1vR1HSzJlv7kc3joJ
|
||||
63yYv0TXy4AeptWoY8FX2wtHxfIUK6ClHNfBhjis0cYgvru0KZSMNAGQutlGB0yA
|
||||
2YHOS1vSPXfdyKbODCP08CpA1lufYapJwSNgU0c5d22OCCYvdwdr0HRc/0zmUoVH
|
||||
/ge2SL0dRTm85ny/wEE5TgL9qnh3iWpWM60lCX3MgkHRnfgmSYn/FJHB4+3miQ31
|
||||
hYkw1X1ee5ZFNsptVT5vtz/b1reVA/+v6moReIsFaWKxEgGFHXBYCRt8HnxyYvcv
|
||||
jv9B+qpL12p7gflMr/trA5xTu9yQLpLqxSRpl1vebLo5p6H084pUelwFtBq/hLs6
|
||||
bEPw5R/n/7EyPauDeEPb/xHKACez3hhdS+GqxgcaaLqQZN1w7/cxXBVSFQARAQAB
|
||||
zSlyb290IChJbXBvcnRlZCBmcm9tIFNTSCkgPHJvb3RAbG9jYWxob3N0PsLBYgQT
|
||||
AQgAFgUCAAAAAAkQacgYfJxDdU4CGw8CGQEAALeFEABb6uheTtzwh2pmbEfahsMf
|
||||
3Umb9E1hGVaKz9KUez2gU/C3EbnELm7qPSP8Bj5gp5hF527YpwcPTGMKXD+SyyUE
|
||||
w+1lFun6RNEEeeJoOEtDoQZA6j4bcpZqvR7r7jAhdU1LHuIjD+4AM4jrTF3B2BrN
|
||||
LpuX70MO0zX0b6ryHeH+9y3iCDmxViXmn0EVG/MLAjguWMrimZ66R0raKfs4eRR4
|
||||
WbbFRl+xXPOv5JvPVhl0BQItVXrTTXFnRNF8y0AxmpxGZ8uFr3PwN9xB9I4o25mu
|
||||
5Pj+aEfJkHTiMqzG44+TITu4pN3xvy32yqO9skn99pz16Q1jQy1cYYnl64nfktJ5
|
||||
cH9Unq5CQIzyugrHhFTruN4PZR07mMMoIHRNisKOVifoyEQPqKUEOsYsaEv+zeU3
|
||||
a42acC3AXJJrSgjN5XoA7bV4RRmU3QYQUsO87gJF2I3xnZwKkRL8R+g0cZeBTaG3
|
||||
U1DwKNfb2WhiAtagixVk7bsKknYJDar41LA0FM5i6uRez+Pb1y8yscD9TP3xiR5d
|
||||
m+/mbrz4fF+5ifRqhvfsewcZIwkVVXR0pBK8c/eGL7YrZ1pJwt3JDsWfM50TGvS1
|
||||
O9LCghAw/SZPfyBik0vKc3R01Pfj3yC70gsG6DI9bIG1UavLhbGQCgDPcEpDZiIt
|
||||
N7RsQdc2NwPnMMMH4mTAvg==
|
||||
=9jYa
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
28
keys/machines/mayushii.asc
Normal file
28
keys/machines/mayushii.asc
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
xsFNBAAAAAABEADjzT31zliBOnM3UALM6S3Oa5nEKHhwn6Dmi8uMABiDUJ0tF3Nw
|
||||
cM8X69FI4oCA9YxQFWn/J8o/h5TvDPfiBwnjE/kuNCnRVkrPxRDFZybxgMyHM/dM
|
||||
QjeZBqCexVa5IhugOrjnx/OWKaFhjLp4mTT/g+HhtvD15tandWxRhLBizKAnPQz9
|
||||
da1nj0i6YbyWP/E+3EGHxw3qHkjDbts7c1oB2N7cTNFtTfdI24G/aiuSmrURHECl
|
||||
bD9xokEui6ZYAtg6cXDsBlmZE1/9D/sUIdrYvspj5bW0XLZrPLNud10Nh7kumBPG
|
||||
uy5xqzD7cl6xCcw4phlveHtDnNhNMH7LUplGyMKBc+CEQHC2uiEQ76P6oRTYSHnq
|
||||
d2fRwzaynBKA00Bv7WH2mucA8fERyLxl/CuBvaswCu/XBWgr3Mi8s9E7p/vB7EUX
|
||||
DDhJWYDBfy8ONUyWAUxdOwitoiPuKWO04mORLKYOQXS+Z4dpHJc8QwYeZoPNIh0H
|
||||
yv8mb7U8MNO2DVPDsoDTvC3vtNo8lwEH5BL2zRruc4LMllSPtkLmWRgMz77LL+9W
|
||||
HYFBfl3URR3MxE0RBU3BMrDeMFHjbxB0kQJL7vYahl6wwTlE6F3KF/l5oyCsd3R8
|
||||
5oqh4gjkhwIlopXizO8kTqnPWeR51VgNvB+tj5o08sRanB54XREulhRsSwARAQAB
|
||||
zSlyb290IChJbXBvcnRlZCBmcm9tIFNTSCkgPHJvb3RAbG9jYWxob3N0PsLBYgQT
|
||||
AQgAFgUCAAAAAAkQRKN/qMFQU7MCGw8CGQEAAOAnEABGFmF4VKNUQoZYLbnANtHY
|
||||
r0VGrSiAYQdj+HVP7W3dd04PSbH6YWjpP7yzZLncjd/+zr1azG14D8UjCZdnelGG
|
||||
jlOLFZNMLwVHjz/quLSMKDgERLfxwDCZsjxnA0CvMvZbWo0VoAs/ncPClqYVjMGP
|
||||
Lq8O+JVJYNGj0jra/PvLGweVqupbfAuJ6KBLlna9iYJiv8uCTjoRF90/dCPIEEQY
|
||||
ZUQstHw5zfGs8cycTElfIv2XpPLmARJ+juyLLUvRQQFIif1o9VI4+MC9oFKS/Tku
|
||||
Osa/KF86z1nLRFRyqKZwgOmZUADKqpEdQwHgyqKCE6XCey089hwBrwnwy/opdXUR
|
||||
hnP28tc4MgUAEAJhBH3uHH4TQyUI5gUOST9MkmxqQLTNVV5IuK6KqO5XPxtczdCf
|
||||
LISNRLjzL3H/zCy9BuhnwDZsdAz0ae5NMjjXnVpFcuGW7kP7RsiGL5aZSAYfx08N
|
||||
mdq1EiK3e3EQAgeunLpGqlc0Os/fB937yuQoR3lYAug6bwa7RnElZMID+Xj1GsQb
|
||||
qY1xodRDM6DE2qyYlDV2f0WoFjG2f2VjN0IVI0AxiydlIfrrK7v5TR9/8gVuo2Vl
|
||||
D1/6pVotiCeUapXhf/ezEBRS1DhRXa0v9rpwzV1t91A+M30CGj2Cye0CQc6uDvno
|
||||
lJ/oTo6bAXwmWGmvvyCtTw==
|
||||
=S83g
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
28
keys/machines/sayuri.asc
Normal file
28
keys/machines/sayuri.asc
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
xsFNBAAAAAABEACbZMv7VT/YLGIy1NnPmVO0c7ximkxFAx8N8UiCQB6aLL6WKIYB
|
||||
xuDZAzkRbv7HvzfHbovjWKKrHDihtcup4WA2AF/fBk1grMDq+zIT17EMke2xqp92
|
||||
OY788ijMPm63+sRgQMfyVOoh16VQb27kgCO8ouPCkjbgabiBz0sC2sVztoDK4xh5
|
||||
RTT4mVjODeqX1wxhYO90Nez4yZt1zX9t9oOPawTCwzoLKco/QNflz3wAYx21DJ7B
|
||||
UxfACkHfI3nxjbCbmVDLMzTmcn1UZoxtovJYp9gd//fCaySMxlfk489j/8kPVrxy
|
||||
bCFtFWEqehLvgQZg0Yrpy/Ih4vuzoCRLPj17GC5LevhrS7sIaATd4UeU/ke9+f/U
|
||||
T8Yf2dh3e7g0pmeiXphpyG7mUPhxCz3MN/FQnNQauQAwmB8MmhxQXPtfx2OyXnP4
|
||||
xjLb8sAtrtpaKNQ50k3/1LVcrJozvx6ELkmOE87MIhbi61jeplhUAnqPP7rpUvhn
|
||||
VeNQ5FgIei78oWVDa6/d1R4Z0Bos/kvNWCdG9OWuqgGnMOfvUfi2WojId8ZM2s2Q
|
||||
eHqg/NO36zctyCtoF7NBIBsJVDA406M2H3B0Mkx2yGHBXLlgwCBl5mopgjc5wrn0
|
||||
xMWgUv+H5jcwbzCNcA0dn/I1BlBWPk64T+iCJh4WO+/ZcD4IsXh+fmnB0wARAQAB
|
||||
zSlyb290IChJbXBvcnRlZCBmcm9tIFNTSCkgPHJvb3RAbG9jYWxob3N0PsLBYgQT
|
||||
AQgAFgUCAAAAAAkQZTN48Qym4AoCGw8CGQEAAP1OEAB8vJKvssUiZm72t3EDrc4i
|
||||
KW6M/kCPTlHBPmkFiLIi1c0qjZ9Oziw20WMhwRdYu6Bv66Of6YqNWNHbDQjdDcSE
|
||||
/echXBKwdo/uwGpYsIEB5pQwtxkmT+8MlHmfUD9cfPK0vweGq4OOiWtNwzS7jt6M
|
||||
fvp6Ar2BDXxT7zt6j/2BgioldmlxXVewtEgC+m9jBnCbML4xAyj9AEMrwYVwAvY4
|
||||
QJoUK18lPWX85bSLpTPyfpJl0DkDiFR1EXHgpiZs/cdv3r0lMb9EfpvZbHtqolMy
|
||||
MDIdwUy2cnoQu8WazbMloe9nAx6kZ9ylnvjkxuhgNpYV397kESWXzl74es1KAOgg
|
||||
xURdt/IM2MJoUTs3B5v3d6SkV+UtSzMLSbBPJ5T0ehykgIihHNINcXvQSDAHPBbv
|
||||
+Add/40MSi7NcJVlGwJvYmIRSiH8nvcQy2UcCGJPx6h3CKk7OskROpSNZ4SbPDsQ
|
||||
WJk2OXr3tNxBoUp565DRURvIANQLerYV8ziwHxhbIyEudm+9/g8CbDy+wPGulwMZ
|
||||
ruN6Lu3L6ctYLniXf7mADNVeZWXlrFQB+qNag9TVhj++kv+qsC5VOVI8o/h6N3Ai
|
||||
yo3aFmDEbsA3F5dE5GZ7kE/u0b3b8nvqKCp+5IQuKl9nwyzKqy9Zj55HmewES3mR
|
||||
DUKUW9W7ZnROHuiQxO5jTA==
|
||||
=XySc
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
28
keys/machines/vueko.asc
Normal file
28
keys/machines/vueko.asc
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
xsFNBAAAAAABEADQYi6d6/laFq0OQWLZYL/48/SF1gnej22Ob+Cy0Tm0d2w9lU95
|
||||
hASROWy6ZqUFwVXKp85uh6UJtA6q2XpaodfurGciCW7DYOjPNexJ0o2xmyFqGB/s
|
||||
PuQDB4NxGXhCyNBXa42adfIlDyYHo5zIDuglMbwr7CQ3RZ1ktxudaA6t9Zlw/5pM
|
||||
c1RXuTwvlhLGstnAz/ojNFwEH4lzYIIRpW4GXmWrtnmjXL/z4LLplYrfPGnsPIij
|
||||
Qf31vhIrEp42nzJIY2wjshZaTvj5y0QIBPfgy9Q9I8/YwxFSY2wt3x8ooGLkTw4v
|
||||
bshqUReatSdoIL4snCaA1oFtnKpqv2vJy/Z6LvURA4e/sbD+c5lMBTE/EkVgvCkC
|
||||
6AbvCxwYHxB2G+lizKgRrQ8tVNDEHOFJBKNMaJAXpzz50ItaSpC+8FrYEP+y7iHk
|
||||
0SBzKlJv3F+yuo1WrD4gHyxHAxACa2eDUU+EikO9BrOh78unOmWYEWVCju+ICHHP
|
||||
STpW8jvEkldttv9Zr4YBDe22sjLKGuqngqabfSCokjjtEPgABCuJMLaGMW5nQm1K
|
||||
Qdr0OHjr1apQMG454CMl4SGoXuNv0XIAcDpaR9xUB5cbBmAmwOWtdrqP2z772+9E
|
||||
jw2WwavW6bn/cApa6BHSK+PQhF9wWvASy138i4m7aCLC8cteukOd6jCexwARAQAB
|
||||
zSlyb290IChJbXBvcnRlZCBmcm9tIFNTSCkgPHJvb3RAbG9jYWxob3N0PsLBYgQT
|
||||
AQgAFgUCAAAAAAkQPLm479f+10kCGw8CGQEAABX4EAAT59Yhu+JwOlmSI9UlzM/E
|
||||
FJ+A8AHijh7Fc8+TjqnA7HmUSlhhVzhuSpjsSt8f1wswNXdcM9N7A5p0DCPZ+caG
|
||||
9TyUrQXktiUdOj3O8bAwnsp7c/GYSBpIjhK1ZN8giN/c66l6z5IcolLA/KBPkMOp
|
||||
2ipPBNjD7bk4khAzAqbPxGxGcpHqaNCS/nC/ovRlcQ2O8rgedXhhRZackuy6gw5+
|
||||
fwGyrnAt9oVthBqhYSUNItQwEPWnEj1yZzsQVvpCX61Vkh7qfqiG/ewvWVVTVOL3
|
||||
lEV5EUsFhiNX5ORUm3pk2qqELR8FbcVzTWf8sLgRM3NeqnotPS3rcHFb11Crh5SD
|
||||
kqoAK2U0oYdGj5wlOH/yNtO5Q1auKwQ0Unttj8zmy55tCwqTiSrahmVxksCyINJn
|
||||
B7h4Xct0ENH9gK/03aEGSZCzLxNG3BpOAOjWU+Ir5W2QLVxZDJT1KiaSftf81h9I
|
||||
k57QsrXAoJNfzwONphQGSVKADBa0Y1P/zkm91gOcuIh3WXZ7BRcn5YZ72POqf61o
|
||||
4uvT5xnDH2Y7upsCMTQkOUCenRUspapQZEQP+tZgQIwli86UeXfcPsqXX8j5QiJD
|
||||
5HOl1jSRt5Rh4rqHfWYyobvLaEnWFEc3H/tYWSkk/w1ideiB3jMCdw65clQHGqJy
|
||||
benF3GpcdU5XwmnJZ3XrCA==
|
||||
=4Idg
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
28
keys/machines/yuzuru.asc
Normal file
28
keys/machines/yuzuru.asc
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
xsFNBAAAAAABEADlgmSvdnFWue1i5dS1qA9df+cRQDA1NDBHYm5dGpsTe7xghvde
|
||||
9B1aAzWxbxeppwr2IHvLo1boWyH0ODC5HFxvleaYd6R9oLljQvxZEPq8ANWMyxDx
|
||||
T4MyRlLClegMrUaCoQTFxoO7LFujrhKPC1+r/JVBBehJrpw31WAUQV2SLDTPFRMJ
|
||||
GVAJXR1vplafbftlkI9K3t12T1RrD1D5QxPtFPPEdwdfPQ8CDE7cCado9iv+P3e+
|
||||
9gA3fE0HJzS1ZRySF0sZ5lP3RX3ZBoY7z/8s3ZHGCYfD9ssGwZS5ByjMk2eJiPY2
|
||||
tX0ZwffBdzAwyq64e1/ddubGTIhKNPd5Iy2GCnOEgPMC8TCke5Zz5IeInUE3ANyS
|
||||
zkuwpCbqT8Vu541yqhs8+dOnH3srgks9OH2Ar2ctMWx3gmICDoCLHrWfbvlkqUwB
|
||||
cxnGxAeNzOXiem1Fu5IJwVC5JR1+5b4dqa3k+f/nuWRizvrU26OP/1S+NTz3T7/W
|
||||
TEF6KyE7+dy3K4IO95SDYwVp6mF/0fh4FTahNi6B1BDEAZKZjaVXyd2TOk77Y7si
|
||||
Tc98E4SUTUlRRCLh8SmUmxalI168LLgGMwUWhDvRw6EP7uh9FBEi1kLXnN6am0kP
|
||||
q1jgQL798DzFwcgEYTx7rTDHZLkbwrxWA32Lpu3T6twtaZiQE+o7wuXMTQARAQAB
|
||||
zSlyb290IChJbXBvcnRlZCBmcm9tIFNTSCkgPHJvb3RAbG9jYWxob3N0PsLBYgQT
|
||||
AQgAFgUCAAAAAAkQZ0WmUqMRhtsCGw8CGQEAAIyAEAA89dyQvXx4sS7I1nRlMw9q
|
||||
Agbi4h1lrCifEH6srlInbg3kZNgnlsDY+cVCIiy8m/Oyupn0U4uduMI8P7R5kgWQ
|
||||
g9+FKFXoLK8P1kO5gani+tWNmBW49leSN8un9YAviKele5wDM/Dg+rNbWDaYHKu5
|
||||
SspZV/SiP0JkxXOgxkMgOOl97kNmvv6O3qYHPG5rz5P/YV0pdDSi1cfhdREvTPAl
|
||||
eNqzMrdEuE/GUrYJYeF8kN+TswBubTgy4WBqQdMlS+Go1B/7HQd56pl5BHiHM8HZ
|
||||
l01ljbgqdYdggmXt7CI90Txe3RRduzKS4ncEQ1VVQiXEmOzU7emu+DFwknGnSgTW
|
||||
gW6Nps3u2XhcsJNczf2PdEzDAv0oNAp4So7JdTGetkJ1Yw4quS0l1XWWBm+cf376
|
||||
nanAGkENvuBbS36kgHNjNT1EnUnyJoMDMnc1AmSSlTf/ORc+JrzM4PtMonhWJTAU
|
||||
eM66tozyJ3qYWApiI2doYwMDuh/u3jvqpTddxklaNFUOxIA2VITP0EgCFkVjW2u3
|
||||
0gPY2tV6AtcxcUn1NnhS92xf0//O4fcGOwlTvNaPqDuF0mk9OazAPQ5L37mfNZzb
|
||||
XUc3AyZXRZNhlE+aNfeJSKtzFCpGUJfstPmkdOwPxK29G4GDbjzWevpYF9Rv6Xpq
|
||||
Ky38rXnis6Hpih/z6/7HOg==
|
||||
=5Ki8
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
52
keys/users/simon.asc
Normal file
52
keys/users/simon.asc
Normal file
|
@ -0,0 +1,52 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBF/lCz0BEADKOij3IA1IIiZc9c8rgxTUtrn4W1R8ncgsnFuXIDGD35dBB9e0
|
||||
wd5noQigoqts9N8ULHEV6J8AuBdl1IP2nAKAr6h3F+hrLjL5tZZCPpTN5fhxWguz
|
||||
wt6aFZgcFwFmQfZHSInxO2XpcibyJAs5ZXW3cO+VYQdVxXLT6KOLKkqWCCGMlQSt
|
||||
xNigzNbrjUcjrcGBcjNbFJs0P4BkVvD6+3xBerpT6zwAuFdBiUpZZk+XI1QCAuVF
|
||||
6ld5A+x+pwvKoN/n040UAUAdLTne7oisNonLhSvZVrH2uH4dKkku/yi2glSkUwps
|
||||
n+ffr0jD9VrdbxktcqQBE0WU2q7Eqe6EjSxURHI6uJ/wFh0QeYR8sT5mgPMt5O9T
|
||||
T49Kz2uUdljuHW0eI37DJSUDcXWh0OtuENRFf7m0lvIIaaPpbPM4btS8j9lCFs9h
|
||||
pJsQIQbNjV+UmIBvddDKGwcL+DHJFk0E2sqPYOwsebvbQLhVvPSPWWUVKrqMay9Y
|
||||
Vd9KKy/KddESzM6c3TFmUbkEj1h4qWSZ0XX0vGL8LL68maaDHwO1nKuw/XfSpjAC
|
||||
c+3wuqAgwFB+ihO/qWs8CB0z+wo+7NK9OUUVVucu2duUUjNknf6+v6fPedtziapp
|
||||
SHVQQKWYvozxVa7XU+dnrU3ZUHzIrv6Fr6yTdGy6fw7pE3yPFIwbw9vsowARAQAB
|
||||
tB9TaW1vbiBCcnVkZXIgPHNpbW9uQHNicnVkZXIuZGU+iQJSBBMBCgA8FiEER+dV
|
||||
ngN6NWUtu/iqjTyC+fMJ+OwFAl/lCz0CGwMFCQeEzgAECwkIBwQVCgkIBRYCAwEA
|
||||
Ah4BAheAAAoJEI08gvnzCfjsYFoP+weWMfiJ3mMeBeZBBcgp9NZTjrJoc2tKn/9s
|
||||
RL4PL/3lwLRSEu6JS4LauAD6fW1d5QnNnUe4nIcvTO6RvJ7R/lDWg1KL+pdCfYtk
|
||||
FiIesUkp+eW5Gqw5m6Bt1a9UjXdtHJuVGKQ/XjxC2914Ps6nhp5mY+NUm5zwZCBK
|
||||
qbjiPjD17TeTCThEui3kwl0sgBhNX/eCPpJZtw3u7vzxpN24+sX8Ogo9r4nRtHKv
|
||||
64vVggiT1Iu9JXm9KYlySFDZed9iVbgM2wKpylw1I0+F4VS8Jw/RDiIW61exKxAe
|
||||
VuxPzbIGeJ0R8u0ZcvTiRbXr7op9barUDCQFn2K2oHXd8uCMUULinlO2pPYyshGh
|
||||
znnZcZIvawqtWnImNnyTvKYe5Il9w2fmm6SzwRmcMvHBZ60eJC/PmnhpRcpBxyiG
|
||||
mAWgFmmgMhc81wcPZFD0Mp91twMDHRchgfmBBlNdqMBt9nNJ2Mm7o52mVX/daMG4
|
||||
VCqLdvbW9mWkyQVjfBq30XabanzN8RST63LlZEwArQqFpH8OifNMHI22fW2xGvPq
|
||||
09k6SLA9qbobGFw+OGKIaGHiVbFq5aeTkqHr0sgL8QBHUJWv+SE0q49GfDDvA4JE
|
||||
iDsLW6RJuNFGTaBq/NzN3A7iT8tTcdClYc7MSQxsEyTpuU+BlC9ewNC4cV/PyJ8l
|
||||
13yeMkdZuQINBF/lCz0BEADs+rV9/tDQ6hyJlgMEKA34LjV4OEBdpwnRS51juXYt
|
||||
nJiRC22Ljs6FY3NivOQPUNJR4yLU7/FGCGgyXlsLEyMIqH5Lldq1iaTMY8FHSdc4
|
||||
e+BM4QYCiaYT05Jqeydorq0fZe0nIXobK7RqB4dG543JNzrttotQ94qpx/cFUy6i
|
||||
ADxp216IyDFh0q10TKao/GB2gwkbOlRNuLYXXUMDON9i8VL0Yh7p0KhZuOl2vREm
|
||||
9/IQDJJHFv4CbSTmdQ0de+k8rVgyiW05SdYq3vrqRmNuI9fbGTf3vw8bHljq1SiH
|
||||
VoapbNJ8CnQCRzrsaX+pOlJwFVUUjxco7iyCHKFobfx+3ju5kwc+i/58nDiSkxMV
|
||||
DPqfjFXnN+72EihfHiw56k1zIRhF9D9b8eq6aqGOIgTtjRujQUR9Rn5BJRZ87/pR
|
||||
nlZsS3wE3nQxOo7fXKv9FU7TyEy6gu1LuK53dUk5xLlu4zMoIP8mc/mZchXqsksi
|
||||
JSWPFDeXh9HLFhKyzintRxdXNp5xV5XaXsMlFkNiTBLUHLbU8Ln9tiLcuJZ29y3b
|
||||
ynLtVo+GN4+G5b+koIoZ9065qSJ0coBPMUa6o7go2e1/oil+xKmtM3UHS+mMNa+4
|
||||
elSqSRdpv3Xgo5lLNP+e60FpN155/93Hq33UMvh8rS9KVaQgp0c1unP99ewY84ra
|
||||
9QARAQABiQI8BBgBCgAmFiEER+dVngN6NWUtu/iqjTyC+fMJ+OwFAl/lCz0CGwwF
|
||||
CQeEzgAACgkQjTyC+fMJ+OzfUBAAkVNY0chFGvzWHOxEKNJY9rW5EQrayrKPNhjr
|
||||
3j9xHoD+1AO7Yinqgd8Ribw88l1+2lVQGHIpIQ2ZPDz/XGND5FvP5PrW71FcUJ/z
|
||||
AKaEnYP4iZ1jgnjp280bJ2iHBMmHc5cs/7OwTCs1uos1kWhjLGA9M12OWDWN9iqB
|
||||
+UJo5W8hs9c5LpYp7ByThQp+g0m3E/ZWSbfZqi0BqWX/X6QC1MMXYS1lZcg6qttF
|
||||
rs6d9hquNHZO7PkI73Ph89DWdxMIirmmn4Iwv88w3jW1KJXiGJbp0N2yooZFtsq+
|
||||
Yd5SHexET9rtU49BfeggEcWuDWJCGvPqdqCfAH6lKe9ddXwQx/R4f+Ffib8WYA6k
|
||||
49HA55U6WfPs74yfbR09mh79kDV2uQgtkaHFJyuVuO4e3oyUoqe3hQdqOMR2lCAR
|
||||
NSc7j5JdR9LxkUDqjUT8ipjzsTxwgPHaO0QkUjugs2v1TpivsDSRooI7NzWFTxbk
|
||||
MkUX5BGUnPnEivBiB3n++1o5kZp1jk3OAi8cqVkosOMjduWei8f6yKpQ4ZKg9cH7
|
||||
ovqpDS9R6CDrACDPNJSTBn2VyOdjGVc4FrhGsXp3FAe5prt1b9psvYTTuXrZZJZP
|
||||
dI1cLPI0Knyymf56gVMGCjp+x1+w7ef0ylGLPtFEuy/6iqWR3H5htZDQo3AgOVgd
|
||||
R7VFGCA=
|
||||
=7eg7
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
44
machines/default.nix
Normal file
44
machines/default.nix
Normal file
|
@ -0,0 +1,44 @@
|
|||
{ ... }@inputs:
|
||||
let
|
||||
hardware = inputs.nixos-hardware.nixosModules;
|
||||
in
|
||||
{
|
||||
sayuri = {
|
||||
system = "x86_64-linux";
|
||||
extraModules = [
|
||||
hardware.common-cpu-intel
|
||||
hardware.common-pc-ssd
|
||||
];
|
||||
};
|
||||
vueko = {
|
||||
system = "x86_64-linux";
|
||||
extraModules = [
|
||||
"${inputs.infinisilSystem}/config/new-modules/murmur.nix"
|
||||
];
|
||||
|
||||
targetHost = "vueko.sbruder.de";
|
||||
};
|
||||
fuuko = {
|
||||
system = "x86_64-linux";
|
||||
extraModules = [
|
||||
hardware.common-cpu-intel
|
||||
hardware.common-pc-ssd
|
||||
];
|
||||
|
||||
targetHost = "fuuko.home.sbruder.de";
|
||||
unlockOverV4 = false; # gets slaac ipv6 address from router
|
||||
};
|
||||
mayushii = {
|
||||
system = "x86_64-linux";
|
||||
extraModules = [
|
||||
#hardware.lenovo-thinkpad-p14s-amd-gen2
|
||||
(import "${inputs.nixos-hardware}/lenovo/thinkpad/p14s/amd/gen2")
|
||||
hardware.common-pc-ssd
|
||||
];
|
||||
};
|
||||
yuzuru = {
|
||||
system = "x86_64-linux";
|
||||
|
||||
targetHost = "yuzuru.sbruder.xyz";
|
||||
};
|
||||
}
|
27
machines/fuuko/README.md
Normal file
27
machines/fuuko/README.md
Normal file
|
@ -0,0 +1,27 @@
|
|||
# fuuko
|
||||
|
||||
## Hardware
|
||||
|
||||
HP MicroServer Gen8 with an [Intel Xeon E3-1220L
|
||||
v2](https://ark.intel.com/content/www/us/en/ark/products/65735/intel-xeon-processor-e3-1220l-v2-3m-cache-2-30-ghz.html)
|
||||
and 8 GiB ECC RAM (1600 MHz). It isn’t the best choice, but I already had it
|
||||
lying around and it is acceptable after changing the CPU from the original
|
||||
Celeron. I decided not to use another consumer-grade computer for this, since
|
||||
the server offers ECC memory and therefore should be more reliable.
|
||||
|
||||
The SSD (Intel DC S4500 480GB) is connected to the first drive slot in a 3.5 ″
|
||||
adapter. I originally wanted to connect it to the internal ODD SATA port, but
|
||||
since it only supports SATA2 (3Gbit/s) and does not support booting from it,
|
||||
requiring an additional boot drive, I decided against this.
|
||||
|
||||
For storage it has two Hard drives (Seagate Exos E 7E8 ST8000NM000A and WD
|
||||
Ultrastar DC HC320 0B36404) in BTRFS RAID1. They are connected to the 2rd and
|
||||
3th bay. Bay 3 is only SATA2, but that should not be the bottleneck.
|
||||
|
||||
## Purpose
|
||||
|
||||
It is my main server handling most long-runing tasks and services.
|
||||
|
||||
## Name
|
||||
|
||||
Fuuko Ibuki is a student in *Clannad* who carves starfish out of wood.
|
79
machines/fuuko/configuration.nix
Normal file
79
machines/fuuko/configuration.nix
Normal file
|
@ -0,0 +1,79 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
../../modules
|
||||
../../users/simon
|
||||
|
||||
./services/ankisyncd.nix
|
||||
./services/binary-cache.nix
|
||||
./services/dnsmasq.nix
|
||||
./services/factorio.nix
|
||||
./services/gitea.nix
|
||||
./services/grafana.nix
|
||||
./services/hedgedoc.nix
|
||||
./services/hydra.nix
|
||||
./services/matrix
|
||||
./services/media-backup.nix
|
||||
./services/media.nix
|
||||
./services/prometheus.nix
|
||||
./services/scan.nix
|
||||
./services/torrent.nix
|
||||
./services/wordclock-dimmer.nix
|
||||
];
|
||||
|
||||
sbruder = {
|
||||
wireguard.home.enable = true;
|
||||
nginx.hardening.enable = true;
|
||||
restic.system = {
|
||||
enable = true;
|
||||
extraPaths = [
|
||||
"/data"
|
||||
];
|
||||
extraExcludes = [
|
||||
"/data/media/video"
|
||||
"/data/misc"
|
||||
"/data/torrent"
|
||||
];
|
||||
prune = true;
|
||||
};
|
||||
unfree.allowSoftware = true;
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
|
||||
virtualHosts."fuuko.home.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
|
||||
virtualHosts."sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
root = pkgs.sbruder.contact;
|
||||
};
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
systemd.services.nginx.serviceConfig.SupplementaryGroups = lib.singleton "keys";
|
||||
|
||||
services.postgresqlBackup = {
|
||||
enable = true;
|
||||
startAt = [ ]; # triggered by restic system backup
|
||||
location = "/data/backup/postgresql";
|
||||
};
|
||||
systemd.services.restic-backups-system = {
|
||||
after = [ "postgresqlBackup.service" ];
|
||||
wants = [ "postgresqlBackup.service" ];
|
||||
};
|
||||
|
||||
networking.hostName = "fuuko";
|
||||
|
||||
system.stateVersion = "20.09";
|
||||
}
|
98
machines/fuuko/hardware-configuration.nix
Normal file
98
machines/fuuko/hardware-configuration.nix
Normal file
|
@ -0,0 +1,98 @@
|
|||
{ config, lib, modulesPath, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot = {
|
||||
kernelModules = [ "kvm-intel" ];
|
||||
blacklistedKernelModules = [ "acpi_power_meter" ]; # constantly pollutes kernel log
|
||||
extraModulePackages = [ ];
|
||||
supportedFilesystems = [ "btrfs" ];
|
||||
kernelParams =
|
||||
let
|
||||
mainInterface = config.systemd.network.networks.eno1;
|
||||
first = lib.flip lib.elemAt 0;
|
||||
in
|
||||
[
|
||||
"ip=${first mainInterface.address}::${first mainInterface.gateway}::${config.networking.hostName}:${mainInterface.name}"
|
||||
];
|
||||
initrd = {
|
||||
availableKernelModules = [
|
||||
"aesni_intel" # hardware crypto for luks
|
||||
"ahci"
|
||||
"ehci_pci"
|
||||
"sd_mod"
|
||||
"tg3" # network interface
|
||||
"uhci_hcd"
|
||||
"usb_storage"
|
||||
"usbhid"
|
||||
"xhci_pci"
|
||||
];
|
||||
kernelModules = [ ];
|
||||
network.enable = true; # remote unlocking
|
||||
luks.devices = {
|
||||
root = {
|
||||
name = "root";
|
||||
device = "/dev/disk/by-uuid/c5cf6858-cca0-40dc-a3b5-ab47a3f9d49c";
|
||||
preLVM = true;
|
||||
allowDiscards = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
loader.grub.device = "/dev/disk/by-id/ata-INTEL_SSDSC2KB480G7_PHYS749202D6480BGN";
|
||||
};
|
||||
|
||||
environment.etc.crypttab.text = ''
|
||||
data0 UUID=aa692e73-2b75-4239-8a87-5f5b69ea56c5 /root/luks-data luks
|
||||
data1 UUID=1f4120b6-a3a0-4973-8c4c-a4d6703eea2a /root/luks-data luks
|
||||
'';
|
||||
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "/dev/disk/by-uuid/92a1f733-8a23-42ea-958b-0d01a5de7776";
|
||||
fsType = "btrfs";
|
||||
options = [ "compress=zstd" "discard" "noatime" ];
|
||||
};
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-uuid/0f1822e1-643b-49e0-b279-5e3373c6a26c";
|
||||
fsType = "ext2";
|
||||
};
|
||||
"/data" = {
|
||||
device = "/dev/mapper/data0";
|
||||
fsType = "btrfs";
|
||||
options = [ "compress=zstd" ];
|
||||
};
|
||||
};
|
||||
|
||||
services.btrfs.autoScrub = {
|
||||
enable = true;
|
||||
fileSystems = [ "/data" ];
|
||||
};
|
||||
|
||||
swapDevices = [
|
||||
{
|
||||
device = "/dev/disk/by-partuuid/22978e17-fbbf-4879-9385-5c9473df1706";
|
||||
randomEncryption.enable = true;
|
||||
}
|
||||
];
|
||||
|
||||
powerManagement.cpuFreqGovernor = "performance";
|
||||
|
||||
networking.useDHCP = false;
|
||||
systemd.network = {
|
||||
enable = true;
|
||||
networks = {
|
||||
eno1 = {
|
||||
name = "eno1";
|
||||
dns = [ "192.168.100.1" ];
|
||||
domains = [ "home.sbruder.de" ];
|
||||
address = [ "192.168.100.61/24" ];
|
||||
gateway = [ "192.168.100.1" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
services.resolved.enable = false;
|
||||
}
|
62
machines/fuuko/secrets.yaml
Normal file
62
machines/fuuko/secrets.yaml
Normal file
|
@ -0,0 +1,62 @@
|
|||
gitea-mail: ENC[AES256_GCM,data:ck4S9YJ1BLUb6+mOrRmg22KWI1xQwsdIw1dowNk1OOk=,iv:+aQiTSGzmBOLYbIVgwH/SIhslKgdJKoL1ZaGAXCeqHY=,tag:H3vCEGMktqAV/9BASVR5tg==,type:str]
|
||||
go-neb-overrides: ENC[AES256_GCM,data:Ws/2yCNNLLEpa9MbN7mZk6BBBaJxtHN2X9I41baWJylZeUld6/h4WCxyHw4MWzigK7k26E+7CGVGThF5Ucd6AuvuD9dd21uaoOtwsAKJVsCavk6VPQvfAuSqYJcBYY2pSwDpA6KbXbQqhC9OgcktvYQdnvNPbsSffK4zhrDjcFpDYYyBRQWxqHu/ZGh2088ECbhm2OCWeC9/5u/2id8dHutip6tUXBIalFmWObc6zgx4atCJGdq9/bOPgajQzrpWlauV0h3ioMwp0gsulOJl2LuI7Lvbsvm+UWe8hVd9ZLqR+4ZAwC5oCQht68AxekKrLNl02KQ8rM4fmWJpbK4NsR/m8+ifMZhqIe8tqUUhWGvJqbxEI/Rsbqm92ToIHL5x9hNSZ/crm+hF4c2Uh9jnSA3E/tOxjZaMU5hB+2Y4tF83nz61tzFnwhQ32VxFeq6IHyMOhgQzGZkDPAyFg2e4tbG6zp5oMx2lsUlgbaXrSrzBU73CjWiLDiJFNyGLx7ADeZ4aZVsZnvGL6y7K4p0uVuK7KSNzoW0=,iv:tniWSP8RgSDJ8ap+PK83TcPAvRdaXWC/gchF6+8uffs=,tag:SC6RB8zyVmjjbLA73cFb4A==,type:str]
|
||||
hcloud_exporter-environment: ENC[AES256_GCM,data:TPMeNK7uC716PC8UqDCnUKtriueIkg3l1ql9e3lse46Ko3TVvwW1oAQRSbwK8CG5AjuF2s2Y8GJdYcI8PN6Z5kERYF1RL2GDpN4pLSuw/l0YqsFkt0uK,iv:cmB+hZHvbk1p8uRmLDyYdPr6rTsFxKcoTcQVo729sAQ=,tag:nkiSvy7rsoInDN0l+1FOOQ==,type:str]
|
||||
nix-binary-cache-htpasswd: ENC[AES256_GCM,data:IktPHrrvExeZlCPmP82W9AovC59ILPbMQExVDO7U2S9lJ9cQKP14mQPuYwA+yKTycIdA01MwRDbt/SxhVleZ+aKkyOPwx/iG5B0cQX6cVqQWVTNVmxlW2sjupnnwwibcdikU21CIw6YsDKs7pMqRAfC/U2OJ3POo2qH5GgFY,iv:ofzEQ143HQQGZIEVkdWCrcENz0i6JPljLDGmG0A7aJ8=,tag:a557cdgRD25jWHhZeT+CnQ==,type:str]
|
||||
prometheus-htpasswd: ENC[AES256_GCM,data:eJOWrcTC3YISJJLuQV6sxzD0r8Gr8uoUt48D9sSEHhsbNUUy3pDgIPqJHrkG0ek2sIF6NvpWdDGK1kFcduRAL9h7nLxQLOtf7dxsdObGlPH5nwe6CwdR+1wTE/2WzrsmTGnUrMjMiBgLPV2yRiQg3VJ7W1Me8tHPYHrqYhM=,iv:WvgwIoIfxc3vyjF+znyUzOElv+sd/thoYpxWVaIavx0=,tag:9FnRw7ol++1PCbl1c2IyoA==,type:str]
|
||||
restic-password: ENC[AES256_GCM,data:IVFXmuzzvvqDS0T3P0R5ZMIn2wdkbE1AqwDMkWqMpDdCOVMP4/HhP4jF+tEarq22,iv:Eu6Wspzm0rPl0CuSoYTTLz+MmaEtmwCD57nH2JTBuaA=,tag:tKqt5Z7nF7lLcSsDKS4E3A==,type:str]
|
||||
restic-s3: ENC[AES256_GCM,data:VJ/jgYnUSkbsNMb1ciLiCcRVEpuaznsSFf0QkEnPhTRHpFv4Nt0f8ARnNtG5j3iXSIT4+H2+5HWKXEsjhvL85p0XE3xe4h45xGKnvvVO2obF+b/zsMDdceFJtLbcq+APzPBjchYU,iv:W+80GhAvYD/52dNZsNYiEhiLo4dhO8oxkd+GAbk42NU=,tag:Kj9CaGo/xAmYxdoLE/Lo1Q==,type:str]
|
||||
synapse-registration-shared-secret: ENC[AES256_GCM,data:lNzK/7QAk4Scv+lNM8bTTKvowI139c4R4Y7Qpq60n8R61aahlxrnWc/PUEOv85Pdx+8IdBOLnV0kp7OQF6tStGBBCOkAicYmnsLoR36DmuDCvTSKVArryV7BrxL8pv0=,iv:ZT9IIF7W0NHqvnU3lPQclVS5uXXK5HIQUzXNYwYFMIo=,tag:a/sUixOlHEvn5ZOINPwQlg==,type:str]
|
||||
synapse-turn-shared-secret: ENC[AES256_GCM,data:sAvP4/jVma7Uq9TR4W/zEoJA17Stj75uG+G4niYaQ1tflxRhE+/HfrhMn7whnmpSgXDb/ZPtLfVaW1DCfU2jovz3Y9Ij1kveXar2aAjlPSsSVwTbFmei,iv:S7uVlE2rhK7ta2S/eX+KXBMQyc69onHYjfMNro3OCjM=,tag:rvI299PQ9TVfVzQjgfUKww==,type:str]
|
||||
wg-aria-private-key: ENC[AES256_GCM,data:qbxpfNRocrXDbUJ3MwR5WMXX8LB4Vnv9HMXN403ANaBbCLrRTEL9hy93roY=,iv:l2DYXGY1wN1rP2bG/s9uSwRhbvCUm2T6IJy5LKzguqk=,tag:51S+m1P1EtHk1QWEjdUCUA==,type:str]
|
||||
wg-home-private-key: ENC[AES256_GCM,data:6l3CgB4qCsPuyYOWuwU2vNiEeC0D1wl6yZvXGGYVsZfYvdPjRz8j5yV7ekQ=,iv:slB/qr+cxi8r7cnTuZAd8CuzWVnvp24Li6A/AnZaFzo=,tag:ynh1Z2+IELAJcgBbHwFC0A==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age: []
|
||||
lastmodified: "2022-01-14T16:18:19Z"
|
||||
mac: ENC[AES256_GCM,data:i6TJ+X85H+ptli5GaodNh6KbjqBLuJcs/Cy88JIQdq5az6nVJUtB55SuhkOAu35pPqlGX4tTBRO7OHupkEwS0Gpl2rC+OQB8gvnfuANzK8uFKGs4EK29BJsqNjsRdDmH1NjGjrIjau4spLz0wfELUcKtKofkZeLvzITsgzjRj+4=,iv:ZuFOIeXb+k1PWfWYPyIBKAnBaLZu+E4SeThysXCQ+iI=,tag:BFMwx9Am66pRSmWQWnVpgA==,type:str]
|
||||
pgp:
|
||||
- created_at: "2021-04-06T11:27:21Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMAwDgSONkM+d4AQ/+KSo1N4aEuIAF2JMX+3RborUdEMIJNqIQsBYejPF4o5UD
|
||||
25XVDt+GrC4Lx6OJsWobLOHm+FDLPzm4Zfo+grU+JaEBo0ZSthUul610iqChwEGF
|
||||
zVMkNKARsZE7lDQ3uN54Mq/A7RQaav4mrt1AbHTOwBR9UdG5hrEJ8JZjObS7Gqz2
|
||||
/OFpX4xr214IA9ALx+O2UIkSAJT9u9Ann/xcKL5GpwE9etcGZbYqOhAPaSzbOSDr
|
||||
BtWuM8Z5nKb1O90pXEe16yVUmFXyO7T+lU1gDrDReSXJJFg7zcjMY4s9rro2H7xq
|
||||
u0z/ufl4sf1E5u7fLLpzrVcqKJAOw+fvfoPeqMrNsGy3r3AdATw9jPp6giRoB8qL
|
||||
xm3gGvs/VedBBqbXMDSCTIuhBcTu3/rrTWb0TJeuMz9RM01owkvtTrL3zjwK81BK
|
||||
pNTwz2a49ylCiDS8Vin2u2jwjoRlri4mPTzw5pvcGqNAoNopv6cjawGQ2toCD5qG
|
||||
tqx0hY0uXAE1cnfewFC63VGFbaBwfCYLryjGLefRH7XFOAcqZ3dlZFi5lJTVnnXO
|
||||
44uO7dW8wfJj45USIEoG6D0BiRU7JPUhgPIjMa1cEI4XpoBSj13EACxovE3z5AYa
|
||||
pX72eJHMkKZ5u+eRrXkrFSGFWkYBGKtgIdbgXn1i9Zw/Ewbf7Qz8kC83kxkih7jS
|
||||
XAEbvfL1DTAHDEyAXFoI2ekIoTTGAtCpsadQcTZ3+3DeWU5R8X29vflEG/kSeRO4
|
||||
m2npmJ9OCKyEN+zAd/WRIQ0wChFgadlTugsDcmXazdvzJ1qJiuNGmzpRn3QF
|
||||
=dltN
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 47E7559E037A35652DBBF8AA8D3C82F9F309F8EC
|
||||
- created_at: "2021-04-06T11:27:21Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMA2nIGHycQ3VOAQ//RC1NMySQoeqfTGEKFB7LwC3o0yLTMHAqoi4qm2Q8jKxH
|
||||
6zSjHNoYI9+2VNEWJcSvUwd9ks79jkVOAWO+Lmv2h1QT3RrsSsj16VZwl+ORp50/
|
||||
+PDrZjaimMafAKaqGJ3HaPlzFX7jUjCHS0yCaF6WIU1ztRLVnHAv3p8dsPzQ1w+7
|
||||
p1h0oQ2noWibl2GLGI3+1O3sv1N5tusTGZWFacG6VsTbtbJmbVCO5FQRqX7vcJtM
|
||||
xfClghFPoHCGbN5W1NWpo/a/lOLUucqO7bFB5DIOoXme6SSS7lrYQKtjBQy/4DRe
|
||||
r3VIjvS6ncVUIYPPnEMlxI3MPUB2lwJLG2B89XNNWwfwREUXTG4DEg09Z6jMUqVr
|
||||
yNO67YCF95fNUQFMQ0LWyVsWZW1n1ef7/iKtDHNoFubCVGjWimIa3ZDX/e4WemEN
|
||||
ww7dab2RXEY3oTLJZwAFMN4jeqUfpgH1TOvcs9OHwF0CQjJIDyDj6uyt6wYqITT2
|
||||
dorhmn1FN/tUUNn4hE0iRjFaD1QrN30KZ4pQ1S/G3IkHGzJ4AlelO0j9yE2VMR2q
|
||||
E8wEhVtDlO/VAYZSx7tJ7jd24gFsGlL70OfSXvo7jyNpo+OjaN9yy5Qy8iogwpGC
|
||||
Jua/Y7+XORx3+SVB+1AUNSwCABOhWL2RQGnGxRRQrST4uEv2Gn6IV5sQuPz6my3S
|
||||
TgEtH78YDDWHFdEE4b3lQaPAR8NGNvuE0btjpdeR7QoTOAkmg0SaUNqAoqrz80jj
|
||||
7kdIBtI8XA2CW/oXYcoxHlkqbPNqPAhaRu3YDci8oQ==
|
||||
=ukYv
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 2372651C56E22972C2D9F3F569C8187C9C43754E
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.7.1
|
BIN
machines/fuuko/secrets/aria2-wireguard.nix
Normal file
BIN
machines/fuuko/secrets/aria2-wireguard.nix
Normal file
Binary file not shown.
17
machines/fuuko/services/ankisyncd.nix
Normal file
17
machines/fuuko/services/ankisyncd.nix
Normal file
|
@ -0,0 +1,17 @@
|
|||
{ config, ... }:
|
||||
let
|
||||
cfg = config.services.ankisyncd;
|
||||
in
|
||||
{
|
||||
services.ankisyncd = {
|
||||
enable = true;
|
||||
host = "127.0.0.1";
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."anki.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/".proxyPass = "http://${cfg.host}:${toString cfg.port}";
|
||||
};
|
||||
}
|
76
machines/fuuko/services/binary-cache.nix
Normal file
76
machines/fuuko/services/binary-cache.nix
Normal file
|
@ -0,0 +1,76 @@
|
|||
# This serves a local binary cache. If the request comes from my home network,
|
||||
# it will set its priority higher than cache.nixos.org (which has a priority of
|
||||
# 40), so local devices get a faster binary cache. If the request coes from
|
||||
# outside my home network, it will set its priority lower, only store paths
|
||||
# exclusive to this cache will be substituted.
|
||||
# This only works well when a host does not change its “location”, since nix
|
||||
# caches binary caches locally (per-user, also for root!) in
|
||||
# ${XDG_CACHE_HOME:-$HOME/.cache}/.cache/nix/binary-cache-v6.sqlite and does
|
||||
# not re-check or invalidate them. Devices that often are not at home should
|
||||
# ensure that the cached priority is 50 to avoid slow substitutions.
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
binaryCachePath = "/data/cache/nix-binary-cache";
|
||||
in
|
||||
{
|
||||
sops.secrets.nix-binary-cache-htpasswd = {
|
||||
owner = "nginx";
|
||||
sopsFile = ../secrets.yaml;
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
appendHttpConfig = ''
|
||||
geo $nix_binary_cache_priority {
|
||||
default 50;
|
||||
|
||||
192.168.100.0/24 30;
|
||||
2001:470:1f0b:abc::/64 30;
|
||||
}
|
||||
'';
|
||||
virtualHosts."nix-cache.sbruder.de" = rec {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
root = binaryCachePath;
|
||||
locations = {
|
||||
"/nix-cache-info" = {
|
||||
return = "200 \"StoreDir: /nix/store\\nPriority: $nix_binary_cache_priority\\n\"";
|
||||
};
|
||||
"/".extraConfig = ''
|
||||
log_not_found off;
|
||||
|
||||
client_max_body_size 5G;
|
||||
|
||||
# WebDAV (for uploading)
|
||||
dav_methods PUT DELETE;
|
||||
create_full_put_path on; # nar/ does not exist by default
|
||||
dav_access user:rw group:r all:r;
|
||||
# same filesystem for temporary files
|
||||
client_body_temp_path ${root}/.upload-tmp;
|
||||
|
||||
limit_except GET {
|
||||
auth_basic "restricted upload";
|
||||
auth_basic_user_file ${config.sops.secrets.nix-binary-cache-htpasswd.path};
|
||||
}
|
||||
|
||||
# workaround for nginx dropping parent headers
|
||||
# see https://github.com/yandex/gixy/blob/master/docs/en/plugins/addheaderredefinition.md
|
||||
${lib.concatStringsSep "\n" (lib.filter
|
||||
(lib.hasPrefix "add_header ")
|
||||
(lib.splitString "\n" config.services.nginx.commonHttpConfig))}
|
||||
add_header Access-Control-Allow-Origin https://hydra.sbruder.de;
|
||||
'';
|
||||
"/nix/store/".proxyPass = "http://localhost:${toString config.services.nar-serve.port}";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.nginx.serviceConfig.ReadWritePaths = lib.singleton binaryCachePath;
|
||||
|
||||
services.nar-serve = {
|
||||
enable = true;
|
||||
cacheURL = "file://${binaryCachePath}";
|
||||
};
|
||||
|
||||
# nar-serve logs multiple lines on every request
|
||||
systemd.services.nar-serve.serviceConfig.StandardOutput = "null";
|
||||
}
|
44
machines/fuuko/services/dnsmasq.nix
Normal file
44
machines/fuuko/services/dnsmasq.nix
Normal file
|
@ -0,0 +1,44 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.dnsmasq = {
|
||||
enable = true;
|
||||
|
||||
extraConfig = ''
|
||||
bogus-priv # do not forward revese lookups of internal addresses
|
||||
domain-needed # do not forward names without domain
|
||||
local-service # only respond to queries from local network
|
||||
no-hosts # do not resolve hosts from /etc/hosts
|
||||
no-resolv # only use explicitly configured resolvers
|
||||
|
||||
cache-size=10000
|
||||
|
||||
server=/fritz.box/192.168.100.1
|
||||
|
||||
domain=home.sbruder.de
|
||||
|
||||
dhcp-range=192.168.100.20,192.168.100.150,12h
|
||||
dhcp-option=option:router,192.168.100.1
|
||||
'';
|
||||
servers = [
|
||||
"9.9.9.9" # dns.quad9.net
|
||||
"2620:fe::fe"
|
||||
"194.150.168.168" # dns.as250.net
|
||||
];
|
||||
};
|
||||
|
||||
# Make `local-service` work (requires network interface with all addresses)
|
||||
systemd.services.dnsmasq = {
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
};
|
||||
|
||||
services.prometheus.exporters.dnsmasq = {
|
||||
enable = true;
|
||||
listenAddress = "127.0.0.1";
|
||||
leasesPath = "/var/lib/dnsmasq/dnsmasq.leases";
|
||||
};
|
||||
|
||||
networking.firewall.allowedUDPPorts = [ 53 67 ];
|
||||
networking.firewall.allowedTCPPorts = [ 53 ];
|
||||
}
|
21
machines/fuuko/services/factorio.nix
Normal file
21
machines/fuuko/services/factorio.nix
Normal file
|
@ -0,0 +1,21 @@
|
|||
{ lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.factorio = {
|
||||
enable = true;
|
||||
package = pkgs.factorio-headless.overrideAttrs (o: o // rec {
|
||||
name = "factorio-headless-${version}";
|
||||
version = "1.1.42";
|
||||
|
||||
src = pkgs.fetchurl {
|
||||
name = "factorio_headless_x64-${version}.tar.xz";
|
||||
url = "https://factorio.com/get-download/${version}/headless/linux64";
|
||||
sha256 = "sha256-QpCZBqJY3NU4FIJY3LDungPKBjhR09jKA9FxJpk7QdA=";
|
||||
};
|
||||
});
|
||||
openFirewall = true;
|
||||
admins = [ "sbruder" ];
|
||||
game-name = "factorio.sbruder.de";
|
||||
game-password = "MoinMoin";
|
||||
};
|
||||
}
|
75
machines/fuuko/services/gitea.nix
Normal file
75
machines/fuuko/services/gitea.nix
Normal file
|
@ -0,0 +1,75 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.gitea;
|
||||
in
|
||||
{
|
||||
sops.secrets.gitea-mail = {
|
||||
owner = cfg.user;
|
||||
sopsFile = ../secrets.yaml;
|
||||
};
|
||||
systemd.services.gitea.serviceConfig.SupplementaryGroups = lib.singleton "keys";
|
||||
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
|
||||
rootUrl = "https://git.sbruder.de/";
|
||||
appName = "sbrudergit";
|
||||
cookieSecure = true;
|
||||
log.level = "Warn";
|
||||
lfs = {
|
||||
enable = true;
|
||||
contentDir = "/data/gitea/lfs/";
|
||||
};
|
||||
enableUnixSocket = true;
|
||||
ssh = {
|
||||
clonePort = 2022;
|
||||
};
|
||||
database.type = "postgres";
|
||||
mailerPasswordFile = config.sops.secrets.gitea-mail.path;
|
||||
settings = {
|
||||
mailer = {
|
||||
ENABLED = true;
|
||||
HOST = "vueko.sbruder.de:587";
|
||||
FROM = "gitea@sbruder.de";
|
||||
USER = "gitea@sbruder.de";
|
||||
};
|
||||
avatar = {
|
||||
DISABLE_GRAVATAR = true;
|
||||
};
|
||||
server = {
|
||||
# privacy
|
||||
DISABLE_ROUTER_LOG = true;
|
||||
OFFLINE_MODE = true;
|
||||
|
||||
# internal ssh server
|
||||
BUILTIN_SSH_SERVER_USER = "git";
|
||||
START_SSH_SERVER = true;
|
||||
SSH_SERVER_HOST_KEYS = "ssh/gitea.ed25519,ssh/gitea.rsa";
|
||||
};
|
||||
service = {
|
||||
DEFAULT_KEEP_EMAIL_PRIVATE = true;
|
||||
ENABLE_NOTIFY_MAIL = true;
|
||||
NO_REPLY_ADDRESS = "users.git.sbruder.de";
|
||||
REGISTER_EMAIL_CONFIRM = true;
|
||||
};
|
||||
session = {
|
||||
PROVIDER = "file";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ cfg.ssh.clonePort ];
|
||||
|
||||
services.nginx.virtualHosts."git.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://unix:/run/gitea/gitea.sock";
|
||||
};
|
||||
|
||||
extraConfig = ''
|
||||
client_max_body_size 1G; # Git LFS
|
||||
'';
|
||||
};
|
||||
}
|
52
machines/fuuko/services/grafana.nix
Normal file
52
machines/fuuko/services/grafana.nix
Normal file
|
@ -0,0 +1,52 @@
|
|||
{ config, ... }:
|
||||
let
|
||||
cfg = config.services.grafana;
|
||||
in
|
||||
{
|
||||
services.grafana = {
|
||||
enable = true;
|
||||
# grafana supports sockets, but no permission management (always 660 grafana:grafana)
|
||||
addr = "127.0.0.1";
|
||||
domain = "grafana.sbruder.de";
|
||||
rootUrl = "https://%(domain)s/";
|
||||
database = {
|
||||
type = "postgres";
|
||||
host = "/run/postgresql";
|
||||
user = "grafana";
|
||||
};
|
||||
provision = {
|
||||
enable = true;
|
||||
datasources = [
|
||||
{
|
||||
name = "Prometheus";
|
||||
type = "prometheus";
|
||||
url = "http://${config.services.prometheus.listenAddress}:${toString config.services.prometheus.port}";
|
||||
isDefault = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
analytics.reporting.enable = false;
|
||||
};
|
||||
|
||||
systemd.services.grafana.after = [ "postgresql.service" ];
|
||||
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
ensureDatabases = [ cfg.database.name ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = cfg.database.user;
|
||||
ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; };
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."grafana.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations = {
|
||||
"/".proxyPass = "http://${cfg.addr}:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
}
|
63
machines/fuuko/services/hedgedoc.nix
Normal file
63
machines/fuuko/services/hedgedoc.nix
Normal file
|
@ -0,0 +1,63 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.hedgedoc;
|
||||
in
|
||||
{
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
ensureDatabases = [ "hedgedoc" ];
|
||||
ensureUsers = lib.singleton {
|
||||
name = "codimd";
|
||||
ensurePermissions = {
|
||||
"DATABASE hedgedoc" = "ALL PRIVILEGES";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.hedgedoc = {
|
||||
enable = true;
|
||||
configuration = {
|
||||
host = "127.0.0.1";
|
||||
port = 3001;
|
||||
db = {
|
||||
dialect = "postgres";
|
||||
host = "/run/postgresql";
|
||||
#user = "hedgedoc";
|
||||
database = "hedgedoc";
|
||||
};
|
||||
domain = "pad.sbruder.de";
|
||||
protocolUseSSL = true;
|
||||
csp.enable = true;
|
||||
imageUploadType = "filesystem";
|
||||
uploadsPath = "/data/hedgedoc/uploads";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.hedgedoc = {
|
||||
after = [ "postgresql.service" ];
|
||||
preStart = toString (pkgs.writeShellScript "hedgedoc-generate-session-secret" ''
|
||||
if [ ! -f ${cfg.workDir}/session_secret_env ]; then
|
||||
echo "CMD_SESSION_SECRET=$(${pkgs.pwgen}/bin/pwgen -s 32 1)" > ${cfg.workDir}/session_secret_env
|
||||
fi
|
||||
'');
|
||||
serviceConfig = {
|
||||
Environment = [
|
||||
"CMD_LOGLEVEL=warn"
|
||||
];
|
||||
EnvironmentFile = [
|
||||
"-${cfg.workDir}/session_secret_env" # - ensures that it will not fail on first start
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${cfg.configuration.uploadsPath} 0700 codimd codimd - -"
|
||||
];
|
||||
|
||||
services.nginx.virtualHosts."pad.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/".proxyPass = "http://${cfg.configuration.host}:${toString cfg.configuration.port}";
|
||||
};
|
||||
}
|
54
machines/fuuko/services/hydra.nix
Normal file
54
machines/fuuko/services/hydra.nix
Normal file
|
@ -0,0 +1,54 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.hydra;
|
||||
in
|
||||
{
|
||||
services.hydra = {
|
||||
enable = true;
|
||||
listenHost = "127.0.0.1";
|
||||
port = 3003;
|
||||
hydraURL = "https://hydra.sbruder.de";
|
||||
notificationSender = "hydra@sbruder.de";
|
||||
buildMachinesFiles = [
|
||||
(pkgs.writeText "hydra-build-machines" ''
|
||||
# hostname system sshKey maxJobs speedFactor mandatory+supportedFeatures mandatoryFeatures
|
||||
localhost x86_64-linux - 4 1 kvm,nixos-test
|
||||
'')
|
||||
];
|
||||
useSubstitutes = true;
|
||||
|
||||
minimumDiskFreeEvaluator = 10;
|
||||
minimumDiskFree = 10;
|
||||
|
||||
extraConfig = ''
|
||||
store_uri = file:///data/cache/nix-binary-cache?secret-key=${config.sops.secrets.binary-cache-secret-key.path}
|
||||
server_store_uri = file:///data/cache/nix-binary-cache
|
||||
|
||||
upload_logs_to_binary_cache = true
|
||||
log_prefix = https://nix-cache.sbruder.de/
|
||||
'';
|
||||
};
|
||||
|
||||
sops.secrets.binary-cache-secret-key.owner = "hydra-queue-runner";
|
||||
systemd.services.hydra-queue-runner.serviceConfig = {
|
||||
SupplementaryGroups = lib.singleton "keys";
|
||||
|
||||
Nice = 10;
|
||||
IOSchedulingPriority = 5;
|
||||
};
|
||||
|
||||
# Hydra uses restricted eval, which by default does not work with flakes that
|
||||
# use git+https inputs
|
||||
nix.extraOptions = ''
|
||||
allowed-uris = https://git.sbruder.de/
|
||||
'';
|
||||
|
||||
services.nginx.virtualHosts."hydra.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/" = {
|
||||
proxyPass = "http://${cfg.listenHost}:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
}
|
7
machines/fuuko/services/matrix/default.nix
Normal file
7
machines/fuuko/services/matrix/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
imports = [
|
||||
./synapse.nix
|
||||
./mautrix-whatsapp.nix
|
||||
./go-neb.nix
|
||||
];
|
||||
}
|
93
machines/fuuko/services/matrix/go-neb.nix
Normal file
93
machines/fuuko/services/matrix/go-neb.nix
Normal file
|
@ -0,0 +1,93 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
synapseCfg = config.services.matrix-synapse;
|
||||
in
|
||||
{
|
||||
sops.secrets = {
|
||||
go-neb-overrides.sopsFile = ../../secrets.yaml;
|
||||
};
|
||||
|
||||
users.users.go-neb = {
|
||||
isSystemUser = true;
|
||||
group = "go-neb";
|
||||
};
|
||||
users.groups.go-neb = { };
|
||||
|
||||
services.go-neb = rec {
|
||||
enable = true;
|
||||
bindAddress = "127.0.0.1:8010";
|
||||
baseUrl = "http://${bindAddress}";
|
||||
config = {
|
||||
clients = [
|
||||
{
|
||||
UserID = "@alertmanager:${synapseCfg.server_name}";
|
||||
HomeserverURL = synapseCfg.public_baseurl;
|
||||
Sync = false;
|
||||
AutoJoinRooms = false;
|
||||
DisplayName = "Prometheus Alertmanager";
|
||||
}
|
||||
];
|
||||
services = [
|
||||
{
|
||||
ID = "alertmanager_service";
|
||||
Type = "alertmanager";
|
||||
UserID = "@alertmanager:${synapseCfg.server_name}";
|
||||
Config = {
|
||||
webhook_url = "${baseUrl}/services/hooks/YWxlcnRtYW5hZ2VyX3NlcnZpY2U";
|
||||
rooms = {
|
||||
"!ceigaGYfREXXSeLFiH:sbruder.de" = {
|
||||
text_template = "{{ range .Alerts }}{{ if eq .Status \"firing\" }}@room {{ end }}[{{ .Status }}] {{ index .Labels \"alertname\" }}: {{ index .Annotations \"description\" }}\n{{ end }}";
|
||||
html_template = ''
|
||||
{{ range .Alerts }}
|
||||
{{- if eq .Status "firing" }}@room {{ end -}}
|
||||
{{ $severity := index .Labels "severity" }}
|
||||
<font{{ if eq .Status "firing" -}}
|
||||
{{- if eq $severity "critical" }} color="red"
|
||||
{{- else if eq $severity "warning" }} color="orange"
|
||||
{{- end -}}
|
||||
{{- else }} color="green"
|
||||
{{- end }}>
|
||||
<strong>{{ if eq .Status "firing" -}}
|
||||
[firing{{ if ne $severity "" }} - {{ $severity }}{{ end }}]
|
||||
{{- else -}}
|
||||
[resolved]
|
||||
{{- end }}</strong>
|
||||
</font>
|
||||
{{ index .Labels "alertname" }}: {{ index .Annotations "description" }} <a href="{{ .GeneratorURL }}">source</a><br/>
|
||||
{{ end }}
|
||||
'';
|
||||
msg_type = "m.text";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# Load AccessToken and DeviceID from secret
|
||||
systemd.services.go-neb = {
|
||||
serviceConfig = {
|
||||
RuntimeDirectory = "go-neb";
|
||||
RuntimeDirectoryMode = "0750";
|
||||
DynamicUser = lib.mkForce false;
|
||||
ExecStartPre =
|
||||
let
|
||||
baseConfig = pkgs.writeText "config-base.json" (builtins.toJSON config.services.go-neb.config);
|
||||
in
|
||||
[
|
||||
"!${pkgs.coreutils}/bin/install -g go-neb ${config.sops.secrets.go-neb-overrides.path} /run/go-neb/config-overrides.json"
|
||||
# needs to be run in a shell script for redirection to work
|
||||
(pkgs.writeShellScript "merge-go-neb-config" ''
|
||||
${pkgs.jq}/bin/jq \
|
||||
--slurp \
|
||||
'. | map(map_values(. | with_entries(.key = (.value.ID // .value.SessionID // .value.UserID)))) | .[0] * .[1] | with_entries(.value = [.value[]])' \
|
||||
${baseConfig} \
|
||||
/run/go-neb/config-overrides.json \
|
||||
> /run/go-neb/config.json
|
||||
'')
|
||||
];
|
||||
};
|
||||
environment.CONFIG_FILE = lib.mkForce "/run/go-neb/config.json";
|
||||
};
|
||||
}
|
78
machines/fuuko/services/matrix/mautrix-whatsapp.nix
Normal file
78
machines/fuuko/services/matrix/mautrix-whatsapp.nix
Normal file
|
@ -0,0 +1,78 @@
|
|||
# somewhat adapted from https://github.com/NixOS/nixpkgs/pull/59211
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
synapseCfg = config.services.matrix-synapse;
|
||||
in
|
||||
let
|
||||
config = rec {
|
||||
homeserver = {
|
||||
address = synapseCfg.public_baseurl;
|
||||
domain = synapseCfg.server_name;
|
||||
};
|
||||
appservice = rec {
|
||||
hostname = "127.0.0.1";
|
||||
port = 29318;
|
||||
address = "http://${hostname}:${toString port}";
|
||||
provisioning.shared_secret = "disable";
|
||||
database = {
|
||||
type = "sqlite3";
|
||||
uri = "/var/lib/mautrix-whatsapp/mautrix-whatsapp.db";
|
||||
};
|
||||
id = "whatsapp";
|
||||
bot = {
|
||||
username = "whatsappbot";
|
||||
displayname = "WhatsApp bridge bot";
|
||||
avatar = "mxc://maunium.net/NeXNQarUbrlYBiPCpprYsRqr";
|
||||
};
|
||||
};
|
||||
whatsapp = {
|
||||
browser_name = "mx-wa";
|
||||
os_name = "Mautrix-WhatsApp bridge";
|
||||
};
|
||||
bridge = {
|
||||
command_prefix = "!wa";
|
||||
delivery_receipts = true;
|
||||
displayname_template = "{{if .FullName}}{{.FullName}}{{else if .Notify}}{{.Notify}}{{else}}{{.Jid}}{{end}} (WA)";
|
||||
history_sync = {
|
||||
backfill = true;
|
||||
};
|
||||
identity_change_notices = true;
|
||||
permissions = {
|
||||
# Only one user since using the name from the address book does not
|
||||
# work with multiple users
|
||||
"@simon:${homeserver.domain}" = 100;
|
||||
};
|
||||
private_chat_portal_meta = true;
|
||||
reaction_notices = true;
|
||||
relay.enable = false;
|
||||
};
|
||||
logging.print_level = "info";
|
||||
};
|
||||
|
||||
generatedConfig = pkgs.runCommandNoCC "mautrix-whatsapp-config"
|
||||
{
|
||||
buildInputs = with pkgs; [ mautrix-whatsapp ];
|
||||
}
|
||||
''
|
||||
mkdir $out
|
||||
cat ${pkgs.writeText "mautrix-whatsapp.yaml" (lib.generators.toYAML { } config)} > $out/config.yaml
|
||||
mautrix-whatsapp -c $out/config.yaml -g -r $out/registration.yaml
|
||||
'';
|
||||
in
|
||||
{
|
||||
systemd.services.mautrix-whatsapp = {
|
||||
description = "Mautrix-WhatsApp Service - A WhatsApp bridge for Matrix";
|
||||
after = [ "network.target" "matrix-synapse.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
StateDirectory = "mautrix-whatsapp";
|
||||
WorkingDirectory = "/var/lib/mautrix-whatsapp";
|
||||
ExecStart = "${pkgs.mautrix-whatsapp}/bin/mautrix-whatsapp -c ${generatedConfig}/config.yaml";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
|
||||
services.matrix-synapse.app_service_config_files = lib.singleton "${generatedConfig}/registration.yaml";
|
||||
}
|
153
machines/fuuko/services/matrix/synapse.nix
Normal file
153
machines/fuuko/services/matrix/synapse.nix
Normal file
|
@ -0,0 +1,153 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.matrix-synapse;
|
||||
|
||||
fqdn = "matrix.sbruder.de";
|
||||
domain = "sbruder.de";
|
||||
in
|
||||
{
|
||||
sops.secrets = {
|
||||
synapse-registration-shared-secret = {
|
||||
owner = "matrix-synapse";
|
||||
sopsFile = ../../secrets.yaml;
|
||||
};
|
||||
synapse-turn-shared-secret = {
|
||||
owner = "matrix-synapse";
|
||||
sopsFile = ../../secrets.yaml;
|
||||
};
|
||||
};
|
||||
systemd.services.matrix-synapse.serviceConfig.SupplementaryGroups = lib.singleton "keys";
|
||||
|
||||
services.matrix-synapse = {
|
||||
enable = true;
|
||||
server_name = domain;
|
||||
public_baseurl = "https://${fqdn}";
|
||||
|
||||
listeners = lib.singleton {
|
||||
port = 8008;
|
||||
bind_address = "127.0.0.1";
|
||||
type = "http";
|
||||
tls = false;
|
||||
x_forwarded = true;
|
||||
resources = lib.singleton {
|
||||
names = [ "client" "federation" "metrics" ];
|
||||
compress = false;
|
||||
};
|
||||
};
|
||||
|
||||
dataDir = "/data/matrix/synapse";
|
||||
|
||||
turn_uris = [
|
||||
"turns:turn.sbruder.de:5349?transport=udp"
|
||||
"turns:turn.sbruder.de:5349?transport=tcp"
|
||||
"turn:turn.sbruder.de:3478?transport=udp"
|
||||
"turn:turn.sbruder.de:3478?transport=tcp"
|
||||
];
|
||||
turn_user_lifetime = "3600000"; # 1h
|
||||
|
||||
enable_metrics = true;
|
||||
|
||||
# adapted from https://github.com/NixOS/nixpkgs/blob/7e10bf4327491a6ebccbe1aaa8e6c6c0aca4663a/nixos/modules/services/misc/matrix-synapse-log_config.yaml
|
||||
# - set root.level to WARNING instead of INFO
|
||||
logConfig = builtins.toJSON {
|
||||
version = 1;
|
||||
|
||||
formatters.journal_fmt.format = "%(name)s: [%(request)s] %(message)s";
|
||||
|
||||
filters.context = {
|
||||
"()" = "synapse.util.logcontext.LoggingContextFilter";
|
||||
request = "";
|
||||
};
|
||||
|
||||
handlers.journal = {
|
||||
class = "systemd.journal.JournalHandler";
|
||||
formatter = "journal_fmt";
|
||||
filters = [ "context" ];
|
||||
SYSLOG_IDENTIFIER = "synapse";
|
||||
};
|
||||
|
||||
root = {
|
||||
level = "WARNING";
|
||||
handlers = [ "journal" ];
|
||||
};
|
||||
|
||||
disable_existing_loggers = false;
|
||||
};
|
||||
|
||||
max_upload_size = "50M";
|
||||
|
||||
extraConfig = ''
|
||||
# I’m okay with using matrix.org as trusted key server
|
||||
suppress_key_server_warning: true
|
||||
'';
|
||||
|
||||
extraConfigFiles = with config.sops.secrets; [
|
||||
synapse-registration-shared-secret.path
|
||||
synapse-turn-shared-secret.path
|
||||
];
|
||||
};
|
||||
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
# synapse requires custom databse configuration:
|
||||
# CREATE DATABASE "matrix-synapse" TEMPLATE template0 LC_COLLATE "C" LC_CTYPE "C";
|
||||
ensureUsers = lib.singleton {
|
||||
name = "matrix-synapse";
|
||||
ensurePermissions = {
|
||||
"DATABASE \"matrix-synapse\"" = "ALL PRIVILEGES";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts = {
|
||||
"${fqdn}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/".return = "301 https://chat.sbruder.de";
|
||||
|
||||
locations."/_matrix" =
|
||||
let
|
||||
listenerCfg = (lib.elemAt cfg.listeners 0);
|
||||
in
|
||||
{
|
||||
proxyPass = "http://${listenerCfg.bind_address}:${toString listenerCfg.port}";
|
||||
|
||||
extraConfig = ''
|
||||
client_max_body_size ${cfg.max_upload_size};
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
"${domain}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations =
|
||||
let
|
||||
# workaround for nginx dropping parent headers
|
||||
# see https://github.com/yandex/gixy/blob/master/docs/en/plugins/addheaderredefinition.md
|
||||
parentHeaders = lib.concatStringsSep "\n" (lib.filter
|
||||
(lib.hasPrefix "add_header ")
|
||||
(lib.splitString "\n" config.services.nginx.commonHttpConfig));
|
||||
in
|
||||
{
|
||||
"=/.well-known/matrix/server".extraConfig = ''
|
||||
${parentHeaders}
|
||||
add_header Content-Type application/json;
|
||||
return 200 '${builtins.toJSON {
|
||||
"m.server" = "${fqdn}:443";
|
||||
}}';
|
||||
'';
|
||||
"=/.well-known/matrix/client".extraConfig = ''
|
||||
${parentHeaders}
|
||||
add_header Content-Type application/json;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
return 200 '${builtins.toJSON {
|
||||
"m.homeserver"."base_url" = "https://${fqdn}";
|
||||
}}';
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
62
machines/fuuko/services/media-backup.nix
Normal file
62
machines/fuuko/services/media-backup.nix
Normal file
|
@ -0,0 +1,62 @@
|
|||
# This creates a backup of my media files when a specific hard drive is
|
||||
# hotplugged. The hard drive has a btrfs filesystem inside of a luks container.
|
||||
# The filesystem can be created with commands similar to this:
|
||||
# cryptsetup luksFormat --label="fuuko-media-backup-luks" --key-file=/path/to/key /dev/sdb
|
||||
# mkfs.btrfs -L "fuuko-media-backup" /dev/mapper/media-backup
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
baseDir = "/data/media";
|
||||
mountPoint = "/mnt/media-backup";
|
||||
in
|
||||
{
|
||||
# Systemd mount units do not support cryptsetup
|
||||
systemd.services.media-backup-luks = {
|
||||
after = [ ''dev-disk-by\x2dlabel-fuuko\x2dmedia\x2dbackup\x2dluks.device'' ];
|
||||
bindsTo = [ ''dev-disk-by\x2dlabel-fuuko\x2dmedia\x2dbackup\x2dluks.device'' ];
|
||||
unitConfig = {
|
||||
StopWhenUnneeded = true;
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = "yes";
|
||||
ExecStart = "${pkgs.cryptsetup}/bin/cryptsetup open --type luks2 --key-file=${baseDir}/.backup-key /dev/disk/by-label/fuuko-media-backup-luks media-backup";
|
||||
ExecStop = "${pkgs.cryptsetup}/bin/cryptsetup close media-backup";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.mounts = lib.singleton {
|
||||
after = [ "media-backup-luks.service" ];
|
||||
bindsTo = [ "media-backup-luks.service" ];
|
||||
unitConfig = {
|
||||
StopWhenUnneeded = true;
|
||||
};
|
||||
|
||||
what = "/dev/mapper/media-backup";
|
||||
where = mountPoint;
|
||||
};
|
||||
|
||||
systemd.services.media-backup = {
|
||||
wantedBy = [ ''dev-disk-by\x2dlabel-fuuko\x2dmedia\x2dbackup\x2dluks.device'' ];
|
||||
unitConfig = {
|
||||
RequiresMountsFor = "/mnt/media-backup";
|
||||
};
|
||||
|
||||
script = ''
|
||||
${pkgs.rsync}/bin/rsync \
|
||||
--archive \
|
||||
--delete \
|
||||
--links \
|
||||
--partial \
|
||||
--recursive\
|
||||
--verbose \
|
||||
${lib.escapeShellArg baseDir} \
|
||||
${lib.escapeShellArg mountPoint}
|
||||
'';
|
||||
serviceConfig = {
|
||||
IOSchedulingClass = "best-effort";
|
||||
IOSchedulingPriority = 7;
|
||||
Nice = 10;
|
||||
};
|
||||
};
|
||||
}
|
14
machines/fuuko/services/media.nix
Normal file
14
machines/fuuko/services/media.nix
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
services.nginx.virtualHosts."media.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
basicAuthFile = "/data/media/.htpasswd";
|
||||
|
||||
root = "/data/media/";
|
||||
|
||||
locations."=/.htpasswd".return = "403";
|
||||
};
|
||||
|
||||
services.nginx-interactive-index.virtualHosts."media.sbruder.de".locations."/".enable = true;
|
||||
}
|
193
machines/fuuko/services/prometheus.nix
Normal file
193
machines/fuuko/services/prometheus.nix
Normal file
|
@ -0,0 +1,193 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.prometheus;
|
||||
|
||||
mkStaticTargets = targets: lib.singleton { inherit targets; };
|
||||
mkStaticTarget = target: mkStaticTargets (lib.singleton target);
|
||||
in
|
||||
{
|
||||
services.prometheus = {
|
||||
enable = true;
|
||||
listenAddress = "127.0.0.1";
|
||||
webExternalUrl = "https://prometheus.sbruder.de";
|
||||
globalConfig = {
|
||||
scrape_interval = "15s";
|
||||
evaluation_interval = "15s";
|
||||
};
|
||||
extraFlags = [
|
||||
"--storage.tsdb.retention.time=90d"
|
||||
"--web.enable-admin-api"
|
||||
];
|
||||
|
||||
alertmanagers = [
|
||||
{
|
||||
static_configs = mkStaticTarget "${cfg.alertmanager.listenAddress}:${toString cfg.alertmanager.port}";
|
||||
path_prefix = "/alertmanager/";
|
||||
}
|
||||
];
|
||||
alertmanager = {
|
||||
enable = true;
|
||||
listenAddress = "127.0.0.1";
|
||||
webExternalUrl = "https://prometheus.sbruder.de/alertmanager";
|
||||
configuration = {
|
||||
global.resolve_timeout = "2m";
|
||||
|
||||
route = {
|
||||
receiver = "matrix";
|
||||
group_by = [ "alertname" ];
|
||||
group_wait = "3m";
|
||||
};
|
||||
|
||||
receivers = [
|
||||
{
|
||||
name = "matrix";
|
||||
webhook_configs = lib.singleton {
|
||||
url = (lib.elemAt
|
||||
(lib.filter
|
||||
({ ID, ... }: ID == "alertmanager_service")
|
||||
config.services.go-neb.config.services)
|
||||
0).Config.webhook_url;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
scrapeConfigs = [
|
||||
{
|
||||
job_name = "prometheus";
|
||||
static_configs = mkStaticTarget "localhost:${toString cfg.port}";
|
||||
}
|
||||
{
|
||||
job_name = "node";
|
||||
static_configs = mkStaticTargets [
|
||||
"fuuko.vpn.sbruder.de:9100"
|
||||
"mayushii.vpn.sbruder.de:9100"
|
||||
"sayuri.vpn.sbruder.de:9100"
|
||||
"vueko.vpn.sbruder.de:9100"
|
||||
"yuzuru.vpn.sbruder.de:9100"
|
||||
];
|
||||
}
|
||||
{
|
||||
job_name = "aria2";
|
||||
static_configs = mkStaticTarget "127.0.0.1:9578";
|
||||
relabel_configs = lib.singleton {
|
||||
target_label = "instance";
|
||||
replacement = "torrent.sbruder.de";
|
||||
};
|
||||
}
|
||||
{
|
||||
job_name = "fritzbox";
|
||||
static_configs = mkStaticTarget "127.0.0.1:9133";
|
||||
}
|
||||
(
|
||||
let
|
||||
listenerCfg = (lib.elemAt config.services.matrix-synapse.listeners 0);
|
||||
in
|
||||
{
|
||||
job_name = "synapse";
|
||||
static_configs = mkStaticTarget "${listenerCfg.bind_address}:${toString listenerCfg.port}";
|
||||
metrics_path = "/_synapse/metrics";
|
||||
relabel_configs = lib.singleton {
|
||||
target_label = "instance";
|
||||
replacement = "matrix.sbruder.de";
|
||||
};
|
||||
}
|
||||
)
|
||||
{
|
||||
job_name = "dnsmasq";
|
||||
static_configs = mkStaticTarget (with config.services.prometheus.exporters.dnsmasq; "${listenAddress}:${toString port}");
|
||||
relabel_configs = lib.singleton {
|
||||
target_label = "instance";
|
||||
replacement = "fuuko.home.sbruder.de";
|
||||
};
|
||||
}
|
||||
{
|
||||
job_name = "hcloud";
|
||||
static_configs = mkStaticTarget config.services.hcloud_exporter.listenAddress;
|
||||
}
|
||||
];
|
||||
|
||||
rules =
|
||||
let
|
||||
mkAlert = { name, expr, for ? "1m", description ? null }: {
|
||||
alert = name;
|
||||
inherit expr for;
|
||||
annotations = lib.optionalAttrs (description != null) { inherit description; };
|
||||
};
|
||||
in
|
||||
[
|
||||
(lib.generators.toYAML { } {
|
||||
groups = lib.singleton {
|
||||
name = "alert.rules";
|
||||
rules = map mkAlert [
|
||||
{
|
||||
name = "InstanceDown";
|
||||
expr = ''up{instance!~"(sayuri|mayushii).vpn.sbruder.de:.*"} == 0'';
|
||||
description = "Instance {{ $labels.instance }} of job {{ $labels.job }} has been down for more than 1 minutes.";
|
||||
}
|
||||
{
|
||||
name = "SystemdUnitFailed";
|
||||
expr = ''node_systemd_unit_state{state="failed"} == 1'';
|
||||
description = "Systemd unit {{ $labels.name }} on {{ $labels.instance }} has state failed.";
|
||||
}
|
||||
{
|
||||
name = "NodeHighLoad";
|
||||
expr = ''sum by (instance) (node_load15) / count by (instance) (node_cpu_seconds_total{mode="system"}) > 2'';
|
||||
for = "15m";
|
||||
description = "Node {{ $labels.instance }} is having a per-core load ≥ 2 for the last 15 minutes.";
|
||||
}
|
||||
{
|
||||
name = "NodeHighMemory";
|
||||
expr = ''(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes > 0.9'';
|
||||
for = "2m";
|
||||
description = "Node {{ $labels.instance }} is using more than 90 % of available RAM.";
|
||||
}
|
||||
{
|
||||
name = "TorrentNoPeers";
|
||||
expr = "sum by (instance) (aria2_torrent_peers) == 0";
|
||||
description = "Aria2 instance {{ $labels.instance }} has no peers. There might be a network connectivity problem";
|
||||
}
|
||||
];
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
exporters = {
|
||||
fritzbox = {
|
||||
enable = true;
|
||||
gatewayAddress = "192.168.100.1";
|
||||
listenAddress = "127.0.0.1";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# get rid of “could not call action: authorization required” every scrape
|
||||
systemd.services.prometheus-fritzbox-exporter.serviceConfig.StandardOutput = "null";
|
||||
|
||||
# exporters that are not part of nixpkgs’ prometheus infrastructure
|
||||
services.hcloud_exporter = {
|
||||
enable = true;
|
||||
listenAddress = "127.0.0.1:9501";
|
||||
environmentFile = config.sops.secrets.hcloud_exporter-environment.path;
|
||||
};
|
||||
sops.secrets.hcloud_exporter-environment.sopsFile = ../secrets.yaml;
|
||||
|
||||
sops.secrets.prometheus-htpasswd = {
|
||||
owner = "nginx";
|
||||
sopsFile = ../secrets.yaml;
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."prometheus.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
basicAuthFile = config.sops.secrets.prometheus-htpasswd.path;
|
||||
|
||||
locations = {
|
||||
"/".proxyPass = "http://${cfg.listenAddress}:${toString cfg.port}";
|
||||
|
||||
"/alertmanager/".proxyPass = "http://${cfg.alertmanager.listenAddress}:${toString cfg.alertmanager.port}";
|
||||
};
|
||||
};
|
||||
}
|
89
machines/fuuko/services/scan.nix
Normal file
89
machines/fuuko/services/scan.nix
Normal file
|
@ -0,0 +1,89 @@
|
|||
{ lib, pkgs, ... }:
|
||||
{
|
||||
users.users.scan = {
|
||||
home = "/var/lib/scans";
|
||||
isSystemUser = true;
|
||||
group = "scan";
|
||||
# this is a low-risk account and since the only thing the account can do is
|
||||
# login to the ftp server from my home network, you can also sniff the
|
||||
# password since the connection is unencrypted
|
||||
password = "meeB3laodoo8na3z";
|
||||
};
|
||||
users.groups.scan = { };
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/scans 0755 scan root 7d"
|
||||
];
|
||||
|
||||
sbruder.restic.system.extraExcludes = [ "/var/lib/scans" ];
|
||||
|
||||
services.vsftpd = {
|
||||
enable = true;
|
||||
writeEnable = true;
|
||||
localUsers = true;
|
||||
userlist = [ "scan" ];
|
||||
extraConfig = ''
|
||||
# I only want this to be reachable from within my home network. Since
|
||||
# IPv6 has all ports forwarded, it is disabled here.
|
||||
listen=YES
|
||||
listen_ipv6=NO
|
||||
|
||||
# user’s shell is nologin
|
||||
check_shell=NO
|
||||
|
||||
# scans should be readable
|
||||
local_umask=022
|
||||
|
||||
pasv_min_port=30000
|
||||
pasv_max_port=30009
|
||||
'';
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."scan.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/" = {
|
||||
root = "/var/lib/scans";
|
||||
|
||||
extraConfig = ''
|
||||
autoindex on;
|
||||
|
||||
allow 192.168.100.0/24;
|
||||
allow 2001:470:1f0b:abc::/64;
|
||||
deny all;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = [ 21 ];
|
||||
allowedTCPPortRanges = [{ from = 30000; to = 30009; }];
|
||||
};
|
||||
|
||||
systemd.services.scan-converter = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
script = ''
|
||||
set -euo pipefail
|
||||
${pkgs.inotify-tools}/bin/inotifywait -m --include "\.tif$" -e close_write /var/lib/scans | while read path action file; do
|
||||
echo "Converting ''${file}…"
|
||||
${pkgs.imagemagick}/bin/convert -strip "/var/lib/scans/$file" "/var/lib/scans/''${file%.*}.png"
|
||||
rm "/var/lib/scans/$file"
|
||||
done
|
||||
'';
|
||||
serviceConfig = {
|
||||
User = "scan";
|
||||
Restart = "always";
|
||||
|
||||
# systemd-analyze --no-pager security scan-converter.service
|
||||
CapabilityBoundingSet = null;
|
||||
PrivateDevices = true;
|
||||
PrivateNetwork = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
ProtectHome = true;
|
||||
RestrictNamespaces = true;
|
||||
SystemCallFilter = "@system-service";
|
||||
};
|
||||
};
|
||||
}
|
199
machines/fuuko/services/torrent.nix
Normal file
199
machines/fuuko/services/torrent.nix
Normal file
|
@ -0,0 +1,199 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
homeDir = "/var/lib/aria2";
|
||||
downloadDir = "/data/torrent";
|
||||
sessionFile = "${homeDir}/session";
|
||||
|
||||
settings = {
|
||||
# locations
|
||||
dir = downloadDir;
|
||||
|
||||
# logging
|
||||
show-console-readout = false;
|
||||
summary-interval = 0;
|
||||
|
||||
# rpc
|
||||
enable-rpc = true;
|
||||
|
||||
# permanent queue
|
||||
bt-load-saved-metadata = true;
|
||||
bt-save-metadata = true;
|
||||
force-save = true;
|
||||
input-file = sessionFile;
|
||||
save-session = sessionFile;
|
||||
save-session-interval = 900; # automatic saving
|
||||
|
||||
# network
|
||||
async-dns-server = "193.138.218.74"; # aria2 does not respect netns resolv.conf
|
||||
dht-listen-port = 56595;
|
||||
listen-port = 56718;
|
||||
interface = "wg-aria";
|
||||
|
||||
# limits
|
||||
max-concurrent-downloads = 65536;
|
||||
max-overall-download-limit = "6M";
|
||||
max-overall-upload-limit = "4M";
|
||||
seed-ratio = 0; # do not stop seeding after reaching ratio
|
||||
};
|
||||
|
||||
toString' = value:
|
||||
if lib.isBool value
|
||||
then (if value then "true" else "false")
|
||||
else (toString value);
|
||||
|
||||
configFile = pkgs.writeText "aria2.conf" (lib.concatStringsSep
|
||||
"\n"
|
||||
(lib.mapAttrsToList
|
||||
(k: v: "${k}=${toString' v}")
|
||||
settings));
|
||||
|
||||
mkProxyService = socket: port: {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "wireguard-wg-aria.service" ];
|
||||
partOf = [ "wireguard-wg-aria.service" ];
|
||||
|
||||
serviceConfig = {
|
||||
PrivateNetwork = true;
|
||||
NetworkNamespacePath = "/run/netns/aria2";
|
||||
|
||||
Restart = "always";
|
||||
ExecStart = "${pkgs.socat}/bin/socat UNIX-LISTEN:${socket},fork,reuseaddr,mode=660,unlink-early TCP:127.0.0.1:${toString port}";
|
||||
User = "aria2";
|
||||
Group = "nginx";
|
||||
|
||||
# systemd-analyze --no-pager security aria2-rpc-proxy.service
|
||||
CapabilityBoundingSet = null;
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
ProtectHome = true;
|
||||
RestrictNamespaces = true;
|
||||
SystemCallFilter = "@system-service";
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
users.users.aria2 = {
|
||||
group = "aria2";
|
||||
uid = config.ids.uids.aria2;
|
||||
home = homeDir;
|
||||
};
|
||||
|
||||
users.groups.aria2.gid = config.ids.gids.aria2;
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d '${downloadDir}' 0775 aria2 users - -"
|
||||
"d '${homeDir}' 0771 aria2 aria2 - -"
|
||||
];
|
||||
|
||||
sops.secrets.wg-aria-private-key.sopsFile = ../secrets.yaml;
|
||||
|
||||
networking.wireguard.interfaces.wg-aria = {
|
||||
interfaceNamespace = "aria2";
|
||||
preSetup = "ip netns add aria2 && ip -n aria2 link set lo up";
|
||||
postShutdown = "ip netns del aria2";
|
||||
|
||||
privateKeyFile = config.sops.secrets.wg-aria-private-key.path;
|
||||
} // (import ../secrets/aria2-wireguard.nix); # potentially sensitive data
|
||||
|
||||
environment.etc."netns/aria2/resolv.conf".text = ''
|
||||
nameserver 193.138.218.74
|
||||
'';
|
||||
|
||||
systemd.services.aria2 = {
|
||||
description = "aria2 Service";
|
||||
after = [ "wireguard-wg-aria.service" ];
|
||||
requires = [ "wireguard-wg-aria.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
preStart = ''
|
||||
if [[ ! -e "${sessionFile}" ]]; then
|
||||
touch "${sessionFile}"
|
||||
fi
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
PrivateNetwork = true;
|
||||
NetworkNamespacePath = "/run/netns/aria2";
|
||||
|
||||
Restart = "always";
|
||||
ExecStart = "${pkgs.aria2}/bin/aria2c --conf-path=${configFile}";
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
User = "aria2";
|
||||
Group = "aria2";
|
||||
|
||||
# Increase number of open file descriptors (default: 1024)
|
||||
LimitNOFILE = 65536;
|
||||
|
||||
# systemd-analyze --no-pager security aria2.service
|
||||
CapabilityBoundingSet = null;
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
ProtectHome = true;
|
||||
RestrictNamespaces = true;
|
||||
SystemCallFilter = "@system-service";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.aria2-rpc-proxy = mkProxyService "${homeDir}/rpc.sock" 6800;
|
||||
|
||||
services.aria2_exporter = {
|
||||
enable = true;
|
||||
listenAddress = "localhost:9578";
|
||||
};
|
||||
|
||||
systemd.services.aria2_exporter = {
|
||||
after = [ "wireguard-wg-aria.service" ];
|
||||
partOf = [ "wireguard-wg-aria.service" ];
|
||||
|
||||
serviceConfig = {
|
||||
PrivateNetwork = true;
|
||||
NetworkNamespacePath = "/run/netns/aria2";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.aria2_exporter-proxy = mkProxyService "${homeDir}/metrics.sock" 9578;
|
||||
|
||||
services.nginx.virtualHosts."torrent.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
# treated as state
|
||||
basicAuthFile = "${homeDir}/htpasswd";
|
||||
|
||||
locations = {
|
||||
"/" = {
|
||||
root = pkgs.AriaNg;
|
||||
};
|
||||
"/jsonrpc" = {
|
||||
proxyPass = "http://unix:${homeDir}/rpc.sock";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
"/download/" = {
|
||||
alias = "${downloadDir}/";
|
||||
extraConfig = ''
|
||||
autoindex on;
|
||||
'';
|
||||
};
|
||||
"=/metrics" = {
|
||||
proxyPass = "http://unix:${homeDir}/metrics.sock";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."aria2-metrics" = {
|
||||
listen = lib.singleton {
|
||||
addr = "127.0.0.1";
|
||||
port = 9578;
|
||||
};
|
||||
|
||||
locations."=/metrics" = {
|
||||
proxyPass = "http://unix:${homeDir}/metrics.sock";
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
aria2
|
||||
mktorrent
|
||||
];
|
||||
}
|
35
machines/fuuko/services/wordclock-dimmer.nix
Normal file
35
machines/fuuko/services/wordclock-dimmer.nix
Normal file
|
@ -0,0 +1,35 @@
|
|||
{ config, ... }:
|
||||
let
|
||||
password = "ymfQkXcEqGuk62S";
|
||||
in
|
||||
{
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [
|
||||
{
|
||||
users = {
|
||||
wordclock = {
|
||||
acl = [
|
||||
"readwrite wordclock/color/+"
|
||||
];
|
||||
inherit password;
|
||||
};
|
||||
};
|
||||
settings = {
|
||||
allow_anonymous = false;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 1883 ];
|
||||
|
||||
services.wordclock-dimmer = {
|
||||
enable = true;
|
||||
mqtt = {
|
||||
user = "wordclock";
|
||||
inherit password;
|
||||
host = "localhost";
|
||||
};
|
||||
};
|
||||
}
|
22
machines/mayushii/README.md
Normal file
22
machines/mayushii/README.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# mayushii
|
||||
|
||||
## Hardware
|
||||
|
||||
ThinkPad P14s AMD Gen2 (≈ T14 AMD Gen2).
|
||||
|
||||
* [AMD Ryzen 7 PRO 5850U](https://www.amd.com/en/products/apu/amd-ryzen-7-pro-5850u) (= Ryzen 7 5800U + “PRO Management”)
|
||||
* 32 GiB DDR4 3200 MHz non-ECC memory
|
||||
* 1TB Samsung PM981a NVMe SSD
|
||||
* 1920×1080 IPS 400nits screen
|
||||
* Realtek RTL8852AE Wireless
|
||||
|
||||
Often used docked to a ThinkPad USB-C Dock Gen2 (40AS),
|
||||
because paying 300€ for a mechanical dock is ridiculous.
|
||||
|
||||
## Purpose
|
||||
|
||||
It is my daily driver so it does everything (except server stuff obviously).
|
||||
|
||||
## Name
|
||||
|
||||
Mayuri Shiina is a student from *Steins;Gate*
|
65
machines/mayushii/configuration.nix
Normal file
65
machines/mayushii/configuration.nix
Normal file
|
@ -0,0 +1,65 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
../../modules
|
||||
../../users/simon
|
||||
];
|
||||
|
||||
sbruder = {
|
||||
games = {
|
||||
enable = true;
|
||||
performanceIndex = 8;
|
||||
};
|
||||
gui.enable = true;
|
||||
media-proxy.enable = true;
|
||||
mullvad.enable = true;
|
||||
restic.system.enable = true;
|
||||
unfree.allowSoftware = true;
|
||||
wireguard.home.enable = true;
|
||||
};
|
||||
|
||||
virtualisation.libvirtd = {
|
||||
enable = true;
|
||||
qemu.package = pkgs.qemu_kvm;
|
||||
};
|
||||
|
||||
services.samba = {
|
||||
enable = true;
|
||||
securityType = "user";
|
||||
extraConfig = ''
|
||||
interfaces = 192.168.122.1
|
||||
bind interfaces only = yes
|
||||
map to guest = bad user
|
||||
load printers = no
|
||||
printing = bsd
|
||||
disable spoolss = yes
|
||||
usershare max shares = 0
|
||||
acl allow execute always = True
|
||||
'';
|
||||
shares = {
|
||||
qemu = {
|
||||
path = "/home/simon/.cache/vm-share";
|
||||
browseable = "yes";
|
||||
"read only" = "no";
|
||||
"guest ok" = "yes";
|
||||
"force user" = "simon";
|
||||
};
|
||||
};
|
||||
};
|
||||
networking.firewall.trustedInterfaces = [ "virbr0" ];
|
||||
|
||||
services.tor = {
|
||||
enable = true;
|
||||
client.enable = true;
|
||||
};
|
||||
services.privoxy = {
|
||||
enable = true;
|
||||
enableTor = true;
|
||||
};
|
||||
|
||||
networking.hostName = "mayushii";
|
||||
|
||||
system.stateVersion = "21.05";
|
||||
}
|
64
machines/mayushii/hardware-configuration.nix
Normal file
64
machines/mayushii/hardware-configuration.nix
Normal file
|
@ -0,0 +1,64 @@
|
|||
{ config, lib, modulesPath, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot = {
|
||||
kernelModules = [ "kvm-amd" ];
|
||||
loader = {
|
||||
grub.enable = false;
|
||||
systemd-boot.enable = true;
|
||||
efi.canTouchEfiVariables = true;
|
||||
};
|
||||
initrd = {
|
||||
availableKernelModules = [ "aesni_intel" "cryptd" "nvme" "sd_mod" "sdhci_pci" "usb_storage" "xhci_pci" ];
|
||||
luks.devices = {
|
||||
root = {
|
||||
name = "root";
|
||||
device = "/dev/disk/by-uuid/16d97095-34d2-4422-819c-d1ddc9c3ce1e";
|
||||
preLVM = true;
|
||||
allowDiscards = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
extraModprobeConfig = ''
|
||||
options thinkpad_acpi fan_control=1
|
||||
'';
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "/dev/disk/by-uuid/cd7ed921-4b59-4de4-b39e-9679571ce034";
|
||||
fsType = "btrfs";
|
||||
options = [ "discard=async" "noatime" "compress=zstd" ];
|
||||
};
|
||||
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-uuid/861A-D1A2";
|
||||
fsType = "vfat";
|
||||
};
|
||||
};
|
||||
|
||||
powerManagement = {
|
||||
cpuFreqGovernor = "schedutil";
|
||||
};
|
||||
services.tlp = {
|
||||
enable = true;
|
||||
settings = {
|
||||
START_CHARGE_THRESH_BAT0 = 75;
|
||||
STOP_CHARGE_THRESH_BAT0 = 92;
|
||||
USB_DENYLIST = lib.concatStringsSep " " [
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# logind fails to detect that the system is still docked when the external
|
||||
# monitor is switched off via dpms
|
||||
services.logind.lidSwitchExternalPower = "ignore";
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
radeontop
|
||||
];
|
||||
}
|
52
machines/mayushii/secrets.yaml
Normal file
52
machines/mayushii/secrets.yaml
Normal file
|
@ -0,0 +1,52 @@
|
|||
wg-home-private-key: ENC[AES256_GCM,data:ZPPEuIOKCAEv6uN3ZmQpf1SfaQdzUORYBv6u91/rm9g/nxHww6b3umL8eDc=,iv:wtIEEbs6RbINbouW/qc/T1lm4s+5+n27co2AKu2IfTs=,tag:QOpNmYWGYD10DQJtKqIAzw==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age: []
|
||||
lastmodified: "2021-10-05T18:14:40Z"
|
||||
mac: ENC[AES256_GCM,data:Uck/kX7BE3gqpMD8wgsksEX3DKzNSUinSRAPqpafH5UbVfQLYVOD637j7wltrtcHSOLjqGSrSbf6jhql/Ve3yTthYB72cHKcJ1UOk5cTD9xCpUJCx56Eid0yj9UZpifIM3PLRjnqqZFF2TYa/s8HcmsY4uvcN+U5dyXYpS6XYMU=,iv:2mhjUTxjU9xH0wFS0ZbgQ3GYRL+8BQboeQuVBpAQvsI=,tag:ZhAKuPo6iPE8890tkxHdaw==,type:str]
|
||||
pgp:
|
||||
- created_at: "2021-10-05T18:14:16Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMAwDgSONkM+d4ARAAvcpLQ4pl2zWfpNnyoi5Vu7Ok6kiQF2UveJQkxkvgQom0
|
||||
TtvlazVEy7kBebM9sgYz9NtcWlTFTMCXC04gpJz9fGYAyssnZ9+D7J/yekK6vyEY
|
||||
5vY9Dd6FX9HGOQuG3wAwBr98AgNHB76Rt31LBSUjIzNZj6RdsbakM2GRIRocFB9V
|
||||
mykpRozkE1ju9l+E3NqnBm65AhjEX9q8W48oyrZLd0lFlfo3Lseda3AlGIMz+PV+
|
||||
MNZ9jTERJZQStpeenE2u2+cS+tMJZbXGk0QBY3+Clz7fTOBlA30ePiWefy1ix3XG
|
||||
mIm5WM12GP5cCpLc1mwAJvyNi/kTw4Myfy0+xth9j65nZCOl2xLIAGqgfikcmQoc
|
||||
/NKs/ijpTwSaqbh3o2vmlmYoif7UkVDxoz/cQKoh9Boa0br7eEI6beKwL2bvDcn9
|
||||
KBNYBeHftt08+sPrg8hSLGjVSpcES9IH6u1WHUWnQYH9ykN9b2VcFeMVUjjYsyWd
|
||||
AwO+quTMF0dfo6es6t21/whzE5TrYZQGSAZzaGASPbzk9MKWQ92hJxICPyyFuZFq
|
||||
NOdWZWRQfYS2Ia9HXqdzcEIiLtLBm4gZ6sZQ/vkv3bBKFcq1rZ2UqfJhsaL9eOsw
|
||||
QiSOoiVpjOAq6SXLF6yQnTmPZczQV02XSvwtNjBSD3yXAIMsXt5JyIW4bCcEIJvS
|
||||
XgESvf5cIkUUA/zmoSmiKFNhHDO7X7b9xMPAE4BqnJqFRL5iBkY9Wkwlv+DFOCDw
|
||||
0W6U4V5dFtnGYMudnjQMp0qtsHeDkfhj/IQGAY7RuBaag7HnmBPAzWnYmgE7DW0=
|
||||
=Fru9
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 47E7559E037A35652DBBF8AA8D3C82F9F309F8EC
|
||||
- created_at: "2021-10-05T18:14:16Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMA0Sjf6jBUFOzAQ/5AbFqOiaNS2Wy5al/H0AVNbpPNPHYYYUaAiDYitdwNgur
|
||||
oChxTYVP+h1UVwNhy+5e1XnLpEwJNcLrzfeQgxr21CqBcaSbOzEE7G9/COX0TD7z
|
||||
pyEP5aup2TmCx8Gzc7Ugjbfiksg1m6EhoZV1k1bsuh5mrFMQqhnhI/xQr0Kehl9E
|
||||
dggOw6IGfu7rZ77U++AHF4b22ZqR2LuRdhpHAvC4H7qlCXIiRlV2qQBT7ArnaOG5
|
||||
7b9WxPI+PjJUNdm/O3rv/ooAtdYz+mvsoZJIMuS0ruxKNGGO0SInxY16QFECKixY
|
||||
n7/q5OmlNTVr4i9++JPSAu0enQsqOscSZm7TctiGF0ekHEn+axRsrMBi8pqEzu08
|
||||
nHb4HXmf/jkdlYjg/K34I4mec9jy1L7a11y6lfsAab1FnabbKJjgm3jrBMMoM/Fj
|
||||
hEH7CWpAAvG0+rwJ9EmuVjq1gGbi6Q8mBpmX0g6/hfSao/YWOhXMi8tDmRNeVWpa
|
||||
eBYhRto2SRB0MhLbOeZyC3UkDASDBIsNgmFz9JTbwLh/opv6anqE7O2sLmKIuXDA
|
||||
IfLJk+ahm05Fdv3AfbPsWGevo1OzxSOxRYn5cDEuF22rcZNDOuRylLJIkkxF9OzN
|
||||
XpsgV7aoSYFgG84u1qa59dE+rvKlhSi8xLQm2mZTRB6L6sDZw/gQ0H4AeXCZC1XS
|
||||
UAF7lyInB6tXrEoNCCIdON9JSrBmSyARMGLoPOX6YqvPV2MQ4OEWf7BZ+SPRgbuI
|
||||
ZFQLv6hk0fYb0fb8xHarmI8krq7k9dsqYxBZI5DjVaPz
|
||||
=7LEL
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 23EEDF49AAF1B41DCD1CD10F44A37FA8C15053B3
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.7.1
|
|
@ -1,21 +0,0 @@
|
|||
# nunotaba
|
||||
|
||||
## Hardware
|
||||
|
||||
ThinkPad T440 with mods to make it acceptable:
|
||||
|
||||
* Touchpad is changed for the T450’s, which has physical mouse buttons (I
|
||||
fucked up during the installation and the touchpad part does not work, so it
|
||||
does not need to be disabled in software).
|
||||
* Screen has a resolution of 1920×1080 and has an IPS panel
|
||||
|
||||
It is used standalone or in on a docking station that connects it to an
|
||||
external mouse, keyboard and monitor (Dell U2410).
|
||||
|
||||
## Purpose
|
||||
|
||||
It is my daily driver so it does everything (except server stuff obviously).
|
||||
|
||||
## Name
|
||||
|
||||
Shinobu Nunotaba is a student/scientist from *A Certain Scientific Railgun*
|
|
@ -1,33 +0,0 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
../../modules
|
||||
../../users/simon
|
||||
];
|
||||
|
||||
sbruder = {
|
||||
cpu.intel.enable = true;
|
||||
docker.enable = true;
|
||||
games.enable = true;
|
||||
gpu.intel.enable = true;
|
||||
gui.enable = true;
|
||||
libvirt.enable = true;
|
||||
media-proxy.enable = true;
|
||||
restic.enable = true;
|
||||
ssd.enable = true;
|
||||
unfree.allowSoftware = true;
|
||||
wireguard.home = {
|
||||
enable = true;
|
||||
address = "10.80.0.4";
|
||||
};
|
||||
};
|
||||
|
||||
services.tor = {
|
||||
enable = true;
|
||||
client.enable = true;
|
||||
};
|
||||
|
||||
networking.hostName = "nunotaba";
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
{ config, lib, modulesPath, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot = {
|
||||
kernelModules = [ "kvm-intel" ];
|
||||
extraModulePackages = [ ];
|
||||
loader.grub.device = "/dev/disk/by-id/ata-INTEL_SSDSC2KB480G7_PHYS749202D6480BGN";
|
||||
initrd = {
|
||||
availableKernelModules = [ "ahci" "ehci_pci" "rtsx_pci_sdmmc" "sd_mod" "usb_storage" "usbhid" "xhci_pci" ];
|
||||
kernelModules = [ "dm-snapshot" ];
|
||||
luks.devices = {
|
||||
root = {
|
||||
name = "root";
|
||||
device = "/dev/disk/by-uuid/f3a2fa57-581b-4e95-9a45-d61cda9edc54";
|
||||
preLVM = true;
|
||||
allowDiscards = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "/dev/disk/by-uuid/8937d1ac-23cb-456f-9c16-e348acc66bb7";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-uuid/da2e90cc-1e0c-4691-8807-5d2f4858df6e";
|
||||
fsType = "ext2";
|
||||
};
|
||||
};
|
||||
|
||||
swapDevices = [
|
||||
{ device = "/dev/disk/by-uuid/b9ad2d56-fee0-49df-98c1-00d93d991b9f"; }
|
||||
];
|
||||
|
||||
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
|
||||
}
|
|
@ -5,13 +5,16 @@
|
|||
HP Z440 workstation.
|
||||
|
||||
* [Intel Xeon E5-1620 v4](https://ark.intel.com/content/www/us/en/ark/products/92991/intel-xeon-processor-e5-1620-v4-10m-cache-3-50-ghz.html)
|
||||
* 16 GiB DDR4 ECC memory
|
||||
* 16 GiB DDR4 2400 MHz ECC memory
|
||||
* 250GB Samsung 970 Evo Pro NVMe SSD
|
||||
* 256GB micron SSD
|
||||
* 2TB Toshiba HDWA120 HDD
|
||||
* Sapphire Nitro+ Radeon RX 480
|
||||
|
||||
## Purpose
|
||||
|
||||
FIMXE
|
||||
Tasks that benefit from parallel computing, require a decent amount of GPU
|
||||
power or possibly even both.
|
||||
|
||||
## Name
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, pkgs, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
|
@ -8,31 +8,90 @@
|
|||
];
|
||||
|
||||
sbruder = {
|
||||
cpu.intel.enable = true;
|
||||
docker.enable = true;
|
||||
games.enable = true;
|
||||
gpu.amd.enable = true;
|
||||
games = {
|
||||
enable = true;
|
||||
performanceIndex = 8;
|
||||
};
|
||||
gui.enable = true;
|
||||
libvirt.enable = true;
|
||||
media-proxy.enable = true;
|
||||
restic = {
|
||||
mullvad.enable = true;
|
||||
restic.system = {
|
||||
enable = true;
|
||||
extraPaths = [
|
||||
"/data"
|
||||
];
|
||||
};
|
||||
ssd.enable = true;
|
||||
unfree.allowSoftware = true;
|
||||
wireguard.home = {
|
||||
enable = true;
|
||||
address = "10.80.0.5";
|
||||
wireguard.home.enable = true;
|
||||
};
|
||||
|
||||
virtualisation.libvirtd = {
|
||||
enable = true;
|
||||
qemu.package = pkgs.qemu_kvm;
|
||||
};
|
||||
|
||||
services.tor = {
|
||||
enable = true;
|
||||
client.enable = true;
|
||||
};
|
||||
services.privoxy = {
|
||||
enable = true;
|
||||
enableTor = true;
|
||||
};
|
||||
|
||||
services.samba = {
|
||||
enable = true;
|
||||
securityType = "user";
|
||||
extraConfig = ''
|
||||
interfaces = 192.168.122.1
|
||||
bind interfaces only = yes
|
||||
map to guest = bad user
|
||||
load printers = no
|
||||
printing = bsd
|
||||
disable spoolss = yes
|
||||
usershare max shares = 0
|
||||
acl allow execute always = True
|
||||
'';
|
||||
shares = {
|
||||
qemu = {
|
||||
path = "/data/cache/win10/shared";
|
||||
browseable = "yes";
|
||||
"read only" = "no";
|
||||
"guest ok" = "yes";
|
||||
"force user" = "simon";
|
||||
};
|
||||
};
|
||||
};
|
||||
networking.firewall.trustedInterfaces = [ "virbr0" ];
|
||||
|
||||
networking.hostName = "sayuri";
|
||||
|
||||
system.stateVersion = "20.03";
|
||||
|
||||
specialisation = {
|
||||
foldingathome.configuration = {
|
||||
services.foldingathome = {
|
||||
enable = true;
|
||||
user = "sbruder";
|
||||
};
|
||||
};
|
||||
intel-sucks.configuration = {
|
||||
# https://make-linux-fast-again.com/
|
||||
boot.kernelParams = [
|
||||
"l1tf=off"
|
||||
"mds=off"
|
||||
"mitigations=off"
|
||||
"no_stf_barrier"
|
||||
"noibpb"
|
||||
"noibrs"
|
||||
"nopti"
|
||||
"nospec_store_bypass_disable"
|
||||
"nospectre_v1"
|
||||
"nospectre_v2"
|
||||
"tsx=on"
|
||||
"tsx_async_abort=off"
|
||||
];
|
||||
sbruder.gui.enable = lib.mkForce false;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
boot = {
|
||||
kernelModules = [ "kvm-intel" ];
|
||||
extraModulePackages = [ ];
|
||||
loader.grub.device = "/dev/disk/by-id/ata-MTFDDAK256TBN-1AR15ABHA_UFZMQ01ZR50NMM";
|
||||
loader.grub.device = "/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_250GB_S4EUNJ0N412342P";
|
||||
initrd = {
|
||||
availableKernelModules = [ "ahci" "ehci_pci" "sd_mod" "usb_storage" "usbhid" "xhci_pci" ];
|
||||
availableKernelModules = [ "aesni_intel" "ahci" "ehci_pci" "nvme" "sd_mod" "sr_mod" "usb_storage" "usbhid" "xhci_pci" ];
|
||||
kernelModules = [ "dm-snapshot" ];
|
||||
luks.devices = {
|
||||
root = {
|
||||
name = "root";
|
||||
device = "/dev/disk/by-uuid/d7e4d213-8a13-4059-a011-0f68081e86d8";
|
||||
device = "/dev/disk/by-uuid/1607bb2a-329b-4252-b11a-b43eb6b7bf0c";
|
||||
preLVM = true;
|
||||
allowDiscards = true;
|
||||
};
|
||||
|
@ -25,29 +25,56 @@
|
|||
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "/dev/disk/by-uuid/024e31ab-aa98-4070-95be-7980043541ac";
|
||||
fsType = "ext4";
|
||||
device = "/dev/disk/by-uuid/9e6b279e-6995-44da-b673-21b9e23a5278";
|
||||
fsType = "btrfs";
|
||||
options = [ "discard=async" "noatime" "compress=zstd" ];
|
||||
};
|
||||
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-uuid/c5bde64b-c629-438d-a78b-c4341796dae9";
|
||||
device = "/dev/disk/by-uuid/7b8b75d2-f779-4a49-b09d-b2a1bbd801bb";
|
||||
fsType = "ext2";
|
||||
};
|
||||
|
||||
"/data" = {
|
||||
device = "/dev/mapper/data";
|
||||
fsType = "btrfs";
|
||||
options = [ "compress=zstd" ];
|
||||
encrypted = {
|
||||
label = "data";
|
||||
enable = true;
|
||||
blkDev = "/dev/disk/by-uuid/576088d4-9aae-4159-a028-feadb2621a1a";
|
||||
keyFile = "/mnt-root" + toString <secrets/luks-data>;
|
||||
blkDev = "/dev/disk/by-uuid/7f4ba71e-3aca-4294-b37f-49f37b584dbd";
|
||||
keyFile = "/mnt-root/root/luks-data";
|
||||
};
|
||||
};
|
||||
|
||||
"/data/ssd" = {
|
||||
device = "/dev/mapper/data-ssd";
|
||||
fsType = "btrfs";
|
||||
options = [ "discard=async" "noatime" "compress=zstd" ];
|
||||
encrypted = {
|
||||
# !!! HACK
|
||||
label = "data-ssd --allow-discards";
|
||||
enable = true;
|
||||
blkDev = "/dev/disk/by-uuid/41baa168-7fa0-4eb3-b314-50766ddf126d";
|
||||
keyFile = "/mnt-root/root/luks-data";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
swapDevices = [
|
||||
{ device = "/dev/disk/by-uuid/78f5277f-a6e5-4297-99cd-d3ea5de5317e"; }
|
||||
{ device = "/dev/disk/by-uuid/2774d182-ddc9-4d79-886e-995fcd60a88a"; }
|
||||
];
|
||||
|
||||
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
|
||||
powerManagement.cpuFreqGovernor = lib.mkDefault "performance";
|
||||
|
||||
# GPU
|
||||
hardware.opengl.extraPackages = with pkgs; [
|
||||
rocm-opencl-icd
|
||||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
clinfo
|
||||
radeontop
|
||||
rocm-smi
|
||||
];
|
||||
}
|
||||
|
|
51
machines/sayuri/secrets.yaml
Normal file
51
machines/sayuri/secrets.yaml
Normal file
|
@ -0,0 +1,51 @@
|
|||
wg-home-private-key: ENC[AES256_GCM,data:0KVRmI3QrtLF5rPwL1XjVcI1q3UT8iJojXrzXhnvdyDiDAh6zk1ppPwZ/tM=,iv:CWkCy9EBT7zubB9BsnIp95fdc1/aSzBzBcgjWaiROzE=,tag:beDPXpB/L2c3+jwoJvKJwg==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
lastmodified: '2021-04-10T09:42:48Z'
|
||||
mac: ENC[AES256_GCM,data:kKi9fAbikpohqIUEBR8c5ge0/fStxkrnWXfVhPvQMMeMO+rN/UPHpHJJMCC/v6TjFMC5ckTKTBflpGWL7xYiREoKONLIx9tMtaH02NrTs/MxVJZ4Ji+GKG0TY8mKGfidoJ4tM6a+8Yk1kgugeePmRXwCJDQKxQyEFyZ3BNKMxcA=,iv:l0OmGCg+DTs9KuFj2ZdW5DDH/0kKxjjX3ej43+X9x5c=,tag:/x8CigyZZJQIV3ZvqqVeXg==,type:str]
|
||||
pgp:
|
||||
- created_at: '2021-04-10T09:42:21Z'
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMAwDgSONkM+d4ARAA491uKx1mGdZ4QpjGkVeS5O8UowNdiLAvSnBZ31BGbzQc
|
||||
MrGffPpaDJgjxRfZ4yaGVra8OKOsGg5gAinTc+SCNaHjhIqKFpyQbKjFUDGlu4RW
|
||||
9flBowWQzz0VP475zxTALQ2i9ZrDdAIBMtycA3XdcZx241h4Ty5gvnB8WIqNp0+n
|
||||
9RpOtK4jEZ+SSJXSGlI2RR+3cEI863N0PidepFf4wsqKhWvv34p9kQ3rVCt8VTMG
|
||||
pPelbcxLdx6JfVXFKHSKjJApW+cOUcaVwOU27GefWHclanZWMOYsl16+eGKnmSqB
|
||||
sTiH7z9o0khVxU5vVq6+q63Xu9reaBoAHIq/tTwpTswxGhAoY4CXbPqK1pVFcnKV
|
||||
RfIxkjYffYR9x5W1zWuLoVwC3ueknGWj6g79aMVtcC8lJoRWT/w+GOdwW7lJGex1
|
||||
W56n2+jcnnWtL2ljvUz3AuoJlx3dluquX1Q7H/76U8Gy0FN2TzgBoQw0jo6kvnX9
|
||||
BDLzN/mtA7ph0oWDMCdDSKMW3OBWg3C9Ak+nmV67mIDnysNRfT93fi2OJ7Y5Tb1p
|
||||
KuoodOOo7BqS8hbiS9G4ZUImGECb+GlivwuuoJ7LPrEPdvn87cWzsjDimTyQLgPi
|
||||
RlFPVpw5nsVy8UihVvs/tj7LX99O4B1NNxXlW0Yj1qgcOhPBpvDcNms3o9GK+cDS
|
||||
XgGalgUfb4BNzDclTwNYVILdNYM9AG9Ic5iJCZDNVtUXN65ptHHlCtiut08hqbFV
|
||||
2+mMRJvH5gRTI1l+ZDAoHRV2LgWcn5s7xjENksx28xes9qH94GhWFK+b0yeoMKw=
|
||||
=XxbY
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 47E7559E037A35652DBBF8AA8D3C82F9F309F8EC
|
||||
- created_at: '2021-04-10T09:42:21Z'
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMA2UzePEMpuAKAQ/8DzlMIWH7nDMIeM8HlDckfzeGgYhzr6lJ40vjtYtNqt3j
|
||||
OF3i+6eaBX/SMsqStk7zLj53sNp++pCGev+TZV+1c+yJd4t8fllLTuRh2rfPXONT
|
||||
Pehu3VhsudOjXKxBJcWmyfnPhtLjtIxdKEQpVgLFiEbbDW+OCSn1RveSiQ63/pyd
|
||||
Su0BNYGmpF89/jEA1ttfknhxd69wsuBKGrxQc9P4ZPQvZajnbhQ2TbLeuLnub6yb
|
||||
QTUNbJkAofw19AgBXY77AX+qreYq4esrAMDsz8ICnisPSO6g4FJ2feMc0Tvf5fwA
|
||||
B0janl3G6D1znUG88tjsjUwv8/x/MHsGFJQvBLm4vqLOFoPDaJ9cO0n1Pv5uFtQB
|
||||
XEwFFgkw9TY1gwsR2eJE/4qSiFaW1JYBHx70/Wyn1ZlJMmdUVh00RhY7Xjn3LMkj
|
||||
JiA+LxvzbTglsMSvkswPbIfUUmB4Ws42P3fF55hCXkxd8jj0NjxByrfFy0VXNgJQ
|
||||
KVYtcQS4ZWXyko+yllEV2TbxmTQilaBEUUdty4hYaoLtSX0jh3s8ZVN9jTv7SPcs
|
||||
VhURedXKmtzogujft1wN8lcqzVGQhWHws2qjOMEiMmeyslooUptg7FkBt/Qw6z5j
|
||||
rlJvWeudR20LCHjjCJnPl/eoNEkQkpOeb5kz4NV7n1okA0jEcOMBbG3+rWiX+JXS
|
||||
UAEGnN0ClALycCU8Fj9lnswEd5LP20ohZUbzk30K2K0bqRregxoY+UMWAQ1asSdK
|
||||
Xd4DYz27BFFPHmrpM1F5Gbxhvy+NiFYNu7+2DCkuLGNj
|
||||
=w8xW
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 17FEEBB45E4245330507C960653378F10CA6E00A
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.6.0
|
15
machines/vueko/README.md
Normal file
15
machines/vueko/README.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
# vueko
|
||||
|
||||
## Hardware
|
||||
|
||||
[Hetzner Cloud](https://hetzner.com/cloud) CX11 (1 vCPU, 2 GB RAM, 20 GB SSD).
|
||||
It has no swap, since the disk is already small enough.
|
||||
|
||||
## Purpose
|
||||
|
||||
It provides services that should not be down that often and don’t require much
|
||||
disk space.
|
||||
|
||||
## Name
|
||||
|
||||
Vueko is a character from *Made in Abyss*
|
119
machines/vueko/configuration.nix
Normal file
119
machines/vueko/configuration.nix
Normal file
|
@ -0,0 +1,119 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
../../modules
|
||||
|
||||
./services/coturn.nix
|
||||
./services/element-web.nix
|
||||
];
|
||||
|
||||
sbruder = {
|
||||
nginx.hardening.enable = true;
|
||||
restic.system.enable = true;
|
||||
wireguard.home.enable = true;
|
||||
full = false;
|
||||
|
||||
mailserver = {
|
||||
enable = true;
|
||||
fqdn = "vueko.sbruder.de";
|
||||
domains = [
|
||||
"kegelschiene.net"
|
||||
"sbruder.de"
|
||||
];
|
||||
users = import ./secrets/mail-users.nix;
|
||||
rejectSenders = import ./secrets/mail-reject-senders.nix;
|
||||
};
|
||||
};
|
||||
|
||||
networking.hostName = "vueko";
|
||||
|
||||
system.stateVersion = "20.09";
|
||||
|
||||
# sadly, too many (legitimate) mail servers have broken dnssec on reverse
|
||||
# lookups
|
||||
services.resolved.dnssec = "false";
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
|
||||
virtualHosts = {
|
||||
"vueko.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
default = true;
|
||||
|
||||
root = pkgs.sbruder.imprint;
|
||||
};
|
||||
"dav.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
locations."/".proxyPass = "http://localhost:5232";
|
||||
};
|
||||
"mumble.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
"bangs.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/".proxyPass = "http://localhost:8000";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
80 # HTTP
|
||||
443 # HTTPS
|
||||
];
|
||||
|
||||
services.radicale = {
|
||||
enable = true;
|
||||
settings = {
|
||||
auth = {
|
||||
type = "htpasswd";
|
||||
htpasswd_encryption = "bcrypt";
|
||||
htpasswd_filename = toString (pkgs.writeText
|
||||
"radicale-htpasswd"
|
||||
(lib.concatMapStringsSep
|
||||
"\n"
|
||||
({ address, passwordHash, ... }: "${address}:${passwordHash}")
|
||||
config.sbruder.mailserver.users));
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sops.secrets.murmur-superuser = {
|
||||
owner = config.users.users.murmur.name;
|
||||
sopsFile = ./secrets.yaml;
|
||||
};
|
||||
|
||||
users.users.murmur.isSystemUser = true; # Infinisil’s module does not set that
|
||||
services.murmur = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
superuserPasswordFile = config.sops.secrets.murmur-superuser.path;
|
||||
acmeDomain = "mumble.sbruder.de";
|
||||
config = {
|
||||
bandwidth = "128000";
|
||||
obfuscate = true;
|
||||
logfile = ""; # log to stdout
|
||||
|
||||
channelname = ''[ \\-=\\w\\#\\[\\]\\{\\}\\(\\)\\@\\|]+'';
|
||||
username = "[-_a-zäöüß]+|SuperUser";
|
||||
};
|
||||
};
|
||||
|
||||
services.bang-evaluator = {
|
||||
enable = true;
|
||||
listenAddress = ":8000";
|
||||
};
|
||||
}
|
49
machines/vueko/hardware-configuration.nix
Normal file
49
machines/vueko/hardware-configuration.nix
Normal file
|
@ -0,0 +1,49 @@
|
|||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
boot = {
|
||||
kernelModules = [ ];
|
||||
extraModulePackages = [ ];
|
||||
kernelParams = [ "ip=dhcp" ];
|
||||
initrd = {
|
||||
availableKernelModules = [ "aesni_intel" "ata_piix" "virtio_pci" "xhci_pci" "sd_mod" "sr_mod" ];
|
||||
kernelModules = [ ];
|
||||
network.enable = true; # remote unlocking
|
||||
luks.devices."root".device = "/dev/disk/by-uuid/9d3f544f-d502-4788-8187-1378a9ee0103";
|
||||
};
|
||||
loader.grub.device = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi0-0-0-0";
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "/dev/disk/by-uuid/cad3325d-775d-4771-bb2d-7beaff9dbaf1";
|
||||
fsType = "ext4";
|
||||
};
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-uuid/52c65d2f-2208-48aa-9d0a-592bca2ecfe3";
|
||||
fsType = "ext2";
|
||||
};
|
||||
};
|
||||
|
||||
networking.useDHCP = false;
|
||||
networking.usePredictableInterfaceNames = false;
|
||||
systemd.network = {
|
||||
enable = true;
|
||||
networks = {
|
||||
eth0 = {
|
||||
name = "eth0";
|
||||
DHCP = "yes";
|
||||
domains = [ "sbruder.de" ];
|
||||
address = [ "2a01:4f8:1c1c:4397::/64" ];
|
||||
gateway = [ "fe80::1" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# no smart on qemu disk
|
||||
services.smartd.enable = false;
|
||||
}
|
54
machines/vueko/secrets.yaml
Normal file
54
machines/vueko/secrets.yaml
Normal file
|
@ -0,0 +1,54 @@
|
|||
murmur-superuser: ENC[AES256_GCM,data:jTVEa1KmbGAIxxFS2/uIlDCnnJTtGmKFZQ==,iv:YJIfcXlgKEwIRzFEY94dgReNjWZqLAqL0Rb6TG4IHIE=,tag:MVzaRkb24QyyNyFCEMwmzQ==,type:str]
|
||||
wg-home-private-key: ENC[AES256_GCM,data:/RHNF6Zw6CTWa9ahUhGWRfkR8KIj+HdqUIojA1w6HQBFbZ/+Vo+CcYTYO5I=,iv:2sDH1P3VRjmLw6Ilkq0rw/hossHrNWP5uRvX9yr5fLE=,tag:KIT5GCfXuhg6RjA8+Nmtnw==,type:str]
|
||||
turn-static-auth-secret: ENC[AES256_GCM,data:Nz94xw5sBuAgEqVpwiV44Rd3km16H46X6jVf2gzE+mbbVt2TXExv/7yegQtXI++eBo6q4wbpOfxwl0b1Pvsa/A==,iv:HSdqj43Vmq5McWAbMoxeNUa38UD75Xe4PJEwY5mKjOQ=,tag:cFpFsVwhisWt7JMMzJemCA==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age: []
|
||||
lastmodified: "2021-12-01T16:49:21Z"
|
||||
mac: ENC[AES256_GCM,data:wLy9If4/YdAVILwz1vSzCQsjG0U8Z2GvpME/+xW9pS/xmKoXTwaxP2QQpy8ReTmtikpbKS327j5pz2dSMiweqaUFSVb1nIEvUFxV4PKnxf5ubJalPZAGa82Cw0aassMKz0IAd8rDF/xK9RoB3ayRluYKAP/qnbEcFrys0BokGE0=,iv:Yw3tG1J135QImJqXEGrpSq3k8Lo++uUXfEKmCCNCpDg=,tag:FChnsJ1qIzalpVypMIilrg==,type:str]
|
||||
pgp:
|
||||
- created_at: "2021-04-06T11:13:54Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMAwDgSONkM+d4ARAAxn8UVtRKn0s+wpuUBpk3cCwSSa3te4BjHshyNrI3TyZ9
|
||||
A2jEVz7xfZXItD5VMs9cZmwhm5kD5qC+2qFauwAnQA8JVn5pCKL1gVxGZURZHgPe
|
||||
eLON75sxWCt6+A+HCXvl8x8ay2ZMSgQ3N+SSuqrihMKe0UcsngzAJQS4qIUPIrQd
|
||||
YQYkm2Nf6n1Ya+t05W0CRqyHLLkwObOF0OWN/t8wvBOh4HY2UCRqvXqSEz6nCb06
|
||||
8jDfy6GLhJBjSMV5000/GTvnbVNH11vYjqq0U/2k33HYD/ddX2TPRarWKQsWi8Fe
|
||||
QYYMjU/zIubNQ1y2Iv89zzpd7DBVFlnCkjnSIjxop+eR4Kk8EUkJnGFHlRek67lc
|
||||
k9le8sdlBTYBahT48igpKWfxrZ3bky27O39TLY7luLAXxpjWTGZ//8WD3eJyiY9d
|
||||
k/TmI7ZLLtR42NKeD/anVmHpSf/rHtgHWwYm1m0Qz0/mvKWhZbdkFTPGWMPVAPNu
|
||||
hBiBjuXd1Gt8ekKr3jZxLR4uRCzzeCA/zXib4x7HvYs/9cLib2UblHsB2hLYwZQ8
|
||||
ah59+O51SrcJWcq56kRhwKbrqh6Oui/KCXUSTdbO2auwtzBxUMmcbJAZV5cxRdtA
|
||||
eD9RXW8WfXVtcmvJ+B9Ab52+RfdYmd/bVpljLPY1kmUEKZG08jDfH08kAtcScyLS
|
||||
XgG0mxcyhD+ZiGIeLgIPUwFC0UT8FT2V0+VAAso1CVH+iIzdF+9BiGPpc2usoOiY
|
||||
XDcaU74seCR/EeiuMWfEeNasu6EULEG+AKOnG9s8zoPp5730EG9v8r4q7ma89jc=
|
||||
=JlIF
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 47E7559E037A35652DBBF8AA8D3C82F9F309F8EC
|
||||
- created_at: "2021-04-06T11:13:54Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMAzy5uO/X/tdJAQ/9Hx6h7IIjr4vwFPC3UCx07rt/lljWHwqA8d8bN3VIcVWJ
|
||||
39doJ3DigerCeZWZo/5Wvdm1TBLnbvnQndl+7EcP5mbAuGUmNo2VajTBOkFoySLa
|
||||
A6g0HwkztuftjtxQV2ICunw1NEsqBCWlNKziGKBjEzsDgOuXLzIaN5ArJAkiUFel
|
||||
kH8jGyHCP6W+nplHE1zOD20SA/oIyRfLW1m+G7d8KU6EuluaPSgASocS6t4oGtsG
|
||||
gnApj6WwWOdM3tDefxtYxa/PlPDXo4gj+Dhak6mOMK88UW/wrDC/f4fYL9JrILmT
|
||||
ImjtA+BIWCI9nLkeo3FTTFhtfr+evOhCsLc8qGL/NMCVZOXB0gK7rpCsReBRQS09
|
||||
4t2KGI1Jti01rNFYvdTN16o59+oF0DoFYnE2dXHAnBA4jmWt+9eDqd5TPmlsuIyr
|
||||
XBiqBcKK+1z0/3ad7nv7vb8jOYkUjKasJl+qhLUaUD5ehojfaCawDMUVia7Y2k72
|
||||
yS77m3m/hCEq0vVvUvMev7hvSTKbfQy3gQkjcnWGavbFfdz64pVBI/KgSJPBM5YE
|
||||
1VFRFZIf30wOF9Xlt++9Cc6xFMQH9JVLG/WouK5On4mfdWwcfnMLgpu83qmYtS6b
|
||||
30hYAuuqKUwWDMbZtXsYOrfb6HXGqs0mtBfpJzgFaiZyHyIVVhb/blXF4ML4dfnS
|
||||
UAGUryszfSsH+ag2oerNKEaDFmgdktmL0FdpP3ycf2qVkMmBNbTpTf2BZaVPcrzF
|
||||
mSfsOU6k+KcWtXYpurZr31zUVK626Re0fsr5XbPSj+9G
|
||||
=Grqu
|
||||
-----END PGP MESSAGE-----
|
||||
fp: BB046D773F54739757553A053CB9B8EFD7FED749
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.7.1
|
BIN
machines/vueko/secrets/mail-reject-senders.nix
Normal file
BIN
machines/vueko/secrets/mail-reject-senders.nix
Normal file
Binary file not shown.
BIN
machines/vueko/secrets/mail-users.nix
Normal file
BIN
machines/vueko/secrets/mail-users.nix
Normal file
Binary file not shown.
78
machines/vueko/services/coturn.nix
Normal file
78
machines/vueko/services/coturn.nix
Normal file
|
@ -0,0 +1,78 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.coturn;
|
||||
|
||||
fqdn = "turn.sbruder.de";
|
||||
|
||||
ipAddresses = [ "195.201.139.15" "2a01:4f8:1c1c:4397::" ];
|
||||
in
|
||||
{
|
||||
sops.secrets.turn-static-auth-secret = {
|
||||
owner = "turnserver";
|
||||
sopsFile = ../secrets.yaml;
|
||||
};
|
||||
|
||||
services.coturn = {
|
||||
enable = true;
|
||||
|
||||
# config adapted from synapse’s turn howto:
|
||||
# https://github.com/matrix-org/synapse/blob/develop/docs/turn-howto.md
|
||||
use-auth-secret = true;
|
||||
realm = fqdn;
|
||||
# the NixOS module does not support loading the secret from a dedicated file
|
||||
static-auth-secret-file = config.sops.secrets.turn-static-auth-secret.path;
|
||||
|
||||
no-tcp-relay = true;
|
||||
|
||||
cert = "/run/turnserver/fullchain.pem";
|
||||
pkey = "/run/turnserver/key.pem";
|
||||
|
||||
min-port = 49160;
|
||||
max-port = 49200;
|
||||
|
||||
listening-ips = ipAddresses;
|
||||
relay-ips = ipAddresses;
|
||||
|
||||
no-cli = true;
|
||||
|
||||
extraConfig = ''
|
||||
denied-peer-ip=10.0.0.0-10.255.255.255
|
||||
denied-peer-ip=192.168.0.0-192.168.255.255
|
||||
denied-peer-ip=172.16.0.0-172.31.255.255
|
||||
|
||||
user-quota=12
|
||||
total-quota=1200
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.coturn = {
|
||||
after = [ "acme-finished-${fqdn}.target" ];
|
||||
serviceConfig = {
|
||||
ExecStartPre = lib.singleton "!${pkgs.writeShellScript "coturn-setup-tls" ''
|
||||
cp ${config.security.acme.certs."${fqdn}".directory}/{fullchain,key}.pem /run/turnserver/
|
||||
chgrp turnserver /run/turnserver/{fullchain,key}.pem
|
||||
''}";
|
||||
};
|
||||
};
|
||||
|
||||
security.acme.certs."${fqdn}".postRun = ''
|
||||
if systemctl is-active coturn; then
|
||||
systemctl --no-block restart coturn
|
||||
fi
|
||||
'';
|
||||
|
||||
services.nginx.virtualHosts."${fqdn}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = with cfg; [ listening-port alt-listening-port tls-listening-port ];
|
||||
allowedUDPPorts = with cfg; [ listening-port alt-listening-port tls-listening-port ];
|
||||
|
||||
allowedUDPPortRanges = lib.singleton {
|
||||
from = cfg.min-port;
|
||||
to = cfg.min-port;
|
||||
};
|
||||
};
|
||||
}
|
53
machines/vueko/services/element-web.nix
Normal file
53
machines/vueko/services/element-web.nix
Normal file
|
@ -0,0 +1,53 @@
|
|||
{ lib, pkgs, ... }:
|
||||
let
|
||||
# This uses
|
||||
# https://github.com/vector-im/element-web#configuration-best-practices
|
||||
# but allows to disable the frame-ancestors rule for /usercontent/.
|
||||
mkSecurityHeaders = withFrameOptions: ''
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
'' + lib.optionalString withFrameOptions ''
|
||||
add_header Content-Security-Policy "frame-ancestors 'none'";
|
||||
'' + lib.optionalString (!withFrameOptions) ''
|
||||
add_header Content-Security-Policy "frame-ancestors 'self'";
|
||||
'';
|
||||
in
|
||||
{
|
||||
services.nginx.virtualHosts."chat.sbruder.de" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
|
||||
root = pkgs.element-web;
|
||||
|
||||
extraConfig = mkSecurityHeaders true;
|
||||
locations."/usercontent/".extraConfig = mkSecurityHeaders false;
|
||||
|
||||
# nixpkgs’s override mechanism doesn’t allow overriding of all options
|
||||
locations."=/config.chat.sbruder.de.json".alias = pkgs.writeText "config.chat.sbruder.de.json" (lib.generators.toJSON { } {
|
||||
default_server_config = {
|
||||
"m.homeserver" = {
|
||||
base_url = "https://matrix.sbruder.de";
|
||||
server_name = "matrix.sbruder.de";
|
||||
};
|
||||
};
|
||||
showLabsSettings = true;
|
||||
branding = {
|
||||
authFooterLinks = [ ];
|
||||
};
|
||||
piwik = false;
|
||||
defaultCountryCode = "DE";
|
||||
settingDefaults = {
|
||||
"UIFeature.feedback" = false;
|
||||
"UIFeature.shareSocial" = false;
|
||||
"UIFeature.identityServer" = false;
|
||||
"UIFeature.thirdPartyId" = false;
|
||||
};
|
||||
disable_custom_urls = true;
|
||||
jitsi.preferredDomain = "meet.jalr.de";
|
||||
disable_guests = true;
|
||||
disable_3pid_login = true;
|
||||
desktopBuilds.available = false;
|
||||
});
|
||||
};
|
||||
}
|
18
machines/yuzuru/README.md
Normal file
18
machines/yuzuru/README.md
Normal file
|
@ -0,0 +1,18 @@
|
|||
# yuzuru
|
||||
|
||||
## Hardware
|
||||
|
||||
[Hetzner Cloud](https://hetzner.com/cloud) CX11 (1 vCPU, 2 GB RAM, 20 GB SSD).
|
||||
It has no swap, since the disk is already small enough.
|
||||
|
||||
## Purpose
|
||||
|
||||
It provides privacy-friendly proxies/alternatives to popular web services:
|
||||
|
||||
* Invidious
|
||||
* Libreddit
|
||||
* Nitter
|
||||
|
||||
## Name
|
||||
|
||||
Yuzuru Nishimiya is a character from *A Silent Voice*
|
40
machines/yuzuru/configuration.nix
Normal file
40
machines/yuzuru/configuration.nix
Normal file
|
@ -0,0 +1,40 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
../../modules
|
||||
|
||||
./services/invidious
|
||||
./services/libreddit.nix
|
||||
./services/nitter.nix
|
||||
./services/sbruder.xyz
|
||||
./services/schabernack.nix
|
||||
];
|
||||
|
||||
sbruder = {
|
||||
nginx.hardening.enable = true;
|
||||
wireguard.home.enable = true;
|
||||
full = false;
|
||||
trusted = false;
|
||||
};
|
||||
|
||||
networking.hostName = "yuzuru";
|
||||
|
||||
system.stateVersion = "21.05";
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
};
|
||||
|
||||
services.journald.extraConfig = ''
|
||||
MaxRetentionSec=1week
|
||||
'';
|
||||
}
|
39
machines/yuzuru/hardware-configuration.nix
Normal file
39
machines/yuzuru/hardware-configuration.nix
Normal file
|
@ -0,0 +1,39 @@
|
|||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
boot = {
|
||||
initrd.kernelModules = [ "nvme" ];
|
||||
loader.grub.device = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi0-0-0-0";
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "/dev/disk/by-uuid/b8ceb0bf-1a67-484b-bf57-c16653c23716";
|
||||
fsType = "btrfs";
|
||||
options = [ "discard=async" "noatime" "compress=zstd" ];
|
||||
};
|
||||
};
|
||||
|
||||
networking = {
|
||||
useDHCP = false;
|
||||
usePredictableInterfaceNames = false;
|
||||
interfaces.eth0 = {
|
||||
useDHCP = true;
|
||||
ipv6.addresses = lib.singleton {
|
||||
address = "2a01:4f9:c010:e4a7::";
|
||||
prefixLength = 64;
|
||||
};
|
||||
};
|
||||
defaultGateway6 = {
|
||||
address = "fe80::1";
|
||||
interface = "eth0";
|
||||
};
|
||||
};
|
||||
|
||||
# no smart on qemu disk
|
||||
services.smartd.enable = false;
|
||||
}
|
53
machines/yuzuru/secrets.yaml
Normal file
53
machines/yuzuru/secrets.yaml
Normal file
|
@ -0,0 +1,53 @@
|
|||
invidious-extra-settings: ENC[AES256_GCM,data:sWvf8ASNUTmdRj9HTsXCkPDg0yQ+Hc+ddnHst72pGBKq0403o5erMzudPm5TVvTEzHeeNDB5d+lTt760s6S2diUMc8l/k3G8Z9loYf0Dpx7o,iv:vqyzZ2B4WQB7AmGDp64nu+Xi+6Jxm6m7D3SUfYq0DZs=,tag:aeQQLerfBEjkpi1NW1x2jw==,type:str]
|
||||
wg-home-private-key: ENC[AES256_GCM,data:KIUvsIhz2Rc4uHRQla714xfOxL9ke1WzRAbXVTDd6UyNkYQkuYIxIpmXQw4=,iv:usnONR35DtIVH2CV4tGSBz5FsZyMlEDzSQiYLDQLRnw=,tag:M1V4HhtByXogMacjajl1iw==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age: []
|
||||
lastmodified: "2021-09-08T16:21:04Z"
|
||||
mac: ENC[AES256_GCM,data:8Q52a8+6mO/LCjNR7yo4olqz8fJIqus7XUZ6FtRzzlEGeYvkBD6zFuz0QJBUl8gRtmj04tQWUn4fEKz8LApSluHXHoBv4/WVBNm/vL9T2k7SiAJmxhbU5wZmNt+Hg++Kvn8yZ6KXgpG6KVl5qu+/CHuJu2m39AvpTj9NJ+ThCUc=,iv:r037pF9rVUqe87+D7pVjxqgFM/hFALSWHFx8kB/fXFk=,tag:GsA95+KyajrKb5XMpVOB2g==,type:str]
|
||||
pgp:
|
||||
- created_at: "2021-09-08T16:11:14Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMAwDgSONkM+d4ARAAhB2PfDQ+KeTI22tc2i4Bc5mVUMDHVpUFn81GzEubwrL0
|
||||
xKqhDgCYfOogahJ7nvor/kLo0YSQuNs8mSJEgnBVnC4GnzeTQucJ5y8Ke/erBV0P
|
||||
xscrZSINv4XtUllGFKc6LcKC+J9sbEcjDUMLwTiMBMcnhjm6mjOkT46ldIwXfnVq
|
||||
vbKaVvUj0U/6awt0f/mqmce8PNfHzJ6rubcEEplBTLG/Qu+tmYFNVcWtsmP21SCt
|
||||
u3Va9JeKmkIa83MY1khtnpSA2rnUa/acZL7vTRTcpCh8qvShtfoMrn9BKTjFhV6i
|
||||
ggrkZKf4StJ+A1wgqw2IbwTH+M+5FM5loI4/9xQnkPkyiJIQByZXwQP2/EmuFpPE
|
||||
sF5UByFTrpC/d7kN7R/xXFcGDIf384RM7Ia4W4XleyKUJ4XHWDkecFU1oT1kLcsA
|
||||
kIYNgjEq4TSAVJMCKa4q3fQilaJ0K27Bvs3p90brzVEnM128k6eavpkrcjojs0JU
|
||||
mV3ixEcS9OBwFfmQolekEt9TJebGNVmzg89TAQ3xn3DAJJPtBsmgM1LliJ39/ev3
|
||||
SeO1rQPBWaxurKksWsDoqcqUtB0r+yR/flfh+Lr+iAgi+fS4W67WwcPm/9SENlUV
|
||||
8OJ/YEkFxhBGiwJEudIGXQ965Z7+wSbpn1ILUaEvGvWvuOg1L6KjCUVbIbH92fjS
|
||||
XAETVqe2zqU2IENVIY/HiMfUQG58M+CVytaWr4zyQ9X4Fc9BmvmjUgSn/4d/LdU3
|
||||
kDT/tDL1fvdX1prXIGUseScSQGPxOamWFB3TPqzWdjhvbkEtT8wp8FqKP/Es
|
||||
=rPPP
|
||||
-----END PGP MESSAGE-----
|
||||
fp: 47E7559E037A35652DBBF8AA8D3C82F9F309F8EC
|
||||
- created_at: "2021-09-08T16:11:14Z"
|
||||
enc: |
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
hQIMA2dFplKjEYbbARAAyvcLSp8ktZ/dqVROfa+xeeIFt9J5EGREnAgES2h9wy8m
|
||||
21tsQWPajIwD3H52XW6Z1s0nxG8qUe1bz9RWvd51sonmZZobezagr9YfDMTMji8Z
|
||||
Hmj+fQ0OdhQdJgaUc8JObvmTNeJyjodKS4TbOZqT/SCheS7DhnzcucqlN0uiVuHT
|
||||
DIUzhM1uzHKcU8IOSclz4LPWLrKvn1yuRGKOplBuvwvd5g2I4QA5obq9Je4WYKEv
|
||||
XL9quQfWW2OBV5XMK132Ttv6aXSJcrxDiI5CsvKivOcB+Rw9wjEesMJ9wBe8Od0L
|
||||
jP/ehkGBsxq107M9srbn2WKjkvXFwpdDzpaQG2w1ZSIwHnsNunlDiU95oIDUcW3Y
|
||||
p0JeL9Nn7uBvsnOKkBMCgXNH1VOBSLxRUDHlDVJIHWNl7TCqPfzKCc8ttq+lbmOf
|
||||
dbATPhXh9wXQ1GgduexFGK4DSKteqSC8bgKC5JnmLx2ijOSgLGxaL4snAs3oqD2Q
|
||||
gQptmLgiuFlof98l3TVJDN1yc6ononyIA72gvQ7e+zme6Q7UkkXU7gJHnd9k9YAL
|
||||
7GQcxn9kTCz/iXxC3+ac/IMZae9b5bz8UGZdsI47RoovZ3dJlGj8jkjPJ7QTfZml
|
||||
9EVuGkO0qWyPDzy14VTaCtKjtTOGm5iZwd8G63BPbaAlfyd6412QbisyC5ClICLS
|
||||
TgF/ABxdrd/GbBzs3w7/8bAjR13EAVJWzqUQgKxluP0UxIthZn5od2f3pPaEyvfd
|
||||
30eBLqpclcaQNIbGtv0qr5Ehjs26uKbAOXmNX+GbdA==
|
||||
=h33S
|
||||
-----END PGP MESSAGE-----
|
||||
fp: F4B5F6971A1FAEA1216FCE1C6745A652A31186DB
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.7.1
|
|
@ -0,0 +1,33 @@
|
|||
From 3c692fc4fd5ea7faefc6b6ef63c9b6b20205a1cb Mon Sep 17 00:00:00 2001
|
||||
From: Simon Bruder <simon@sbruder.de>
|
||||
Date: Thu, 9 Sep 2021 16:56:57 +0200
|
||||
Subject: [PATCH] Prefer opus audio streams in listen mode
|
||||
|
||||
---
|
||||
src/invidious/views/components/player.ecr | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr
|
||||
index 6418f66b..73524cfd 100644
|
||||
--- a/src/invidious/views/components/player.ecr
|
||||
+++ b/src/invidious/views/components/player.ecr
|
||||
@@ -7,6 +7,16 @@
|
||||
<source src="<%= URI.parse(hlsvp).request_target %><% if params.local %>?local=true<% end %>" type="application/x-mpegURL" label="livestream">
|
||||
<% else %>
|
||||
<% if params.listen %>
|
||||
+ <%
|
||||
+ opus_streams = audio_streams.select { |fmt|
|
||||
+ metadata = itag_to_metadata?(fmt["itag"])
|
||||
+ metadata ? metadata["acodec"] == "opus" : false
|
||||
+ }.reverse!
|
||||
+ if opus_streams.size > 0
|
||||
+ audio_streams = opus_streams
|
||||
+ end
|
||||
+ audio_streams.sort_by! { |fmt| fmt["bitrate"].as_i }.reverse!
|
||||
+ %>
|
||||
<% audio_streams.each_with_index do |fmt, i| %>
|
||||
<source src="/latest_version?id=<%= video.id %>&itag=<%= fmt["itag"] %><% if params.local %>&local=true<% end %>" type='<%= fmt["mimeType"] %>' label="<%= fmt["bitrate"] %>k" selected="<%= i == 0 ? true : false %>">
|
||||
<% end %>
|
||||
--
|
||||
2.31.1
|
||||
|
53
machines/yuzuru/services/invidious/default.nix
Normal file
53
machines/yuzuru/services/invidious/default.nix
Normal file
|
@ -0,0 +1,53 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
sops.secrets.invidious-extra-settings = {
|
||||
sopsFile = ../../secrets.yaml;
|
||||
group = "keys"; # not ideal, but required since the invidious user is dynamic
|
||||
mode = "440";
|
||||
};
|
||||
systemd.services.invidious.serviceConfig.SupplementaryGroups = [ "keys" ];
|
||||
|
||||
services.invidious = {
|
||||
enable = true;
|
||||
package = pkgs.invidious.overrideAttrs (o: o // {
|
||||
patches = (o.patches or [ ]) ++ [
|
||||
./0001-Prefer-opus-audio-streams-in-listen-mode.patch
|
||||
];
|
||||
});
|
||||
nginx.enable = true;
|
||||
domain = "iv.sbruder.xyz";
|
||||
settings = {
|
||||
host_binding = "127.0.0.1";
|
||||
log_level = "Warn";
|
||||
default_user_preferences = {
|
||||
# allow higher qualities
|
||||
quality = "dash";
|
||||
quality_dash = "auto";
|
||||
|
||||
# humane volume
|
||||
volume = 50;
|
||||
|
||||
# no “popular” content
|
||||
feed_menu = [ "Subscriptions" "Playlists" ];
|
||||
default_home = ""; # search on /
|
||||
};
|
||||
disable_proxy = [ "downloads" ]; # legal precaution
|
||||
local = true; # no external requests
|
||||
use_pubsub_feeds = true;
|
||||
modified_source_code_url = "https://github.com/sbruder/invidious/tree/patches";
|
||||
};
|
||||
extraSettingsFile = config.sops.secrets.invidious-extra-settings.path;
|
||||
};
|
||||
|
||||
systemd.services.invidious.serviceConfig = {
|
||||
Restart = "on-failure";
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."iv.sbruder.xyz" = {
|
||||
locations = {
|
||||
"/robots.txt".return = "200 'User-agent: *\\nDisallow: /'";
|
||||
"/privacy".return = "301 'https://sbruder.xyz/#privacy'";
|
||||
};
|
||||
};
|
||||
}
|
19
machines/yuzuru/services/libreddit.nix
Normal file
19
machines/yuzuru/services/libreddit.nix
Normal file
|
@ -0,0 +1,19 @@
|
|||
{ config, ... }:
|
||||
let
|
||||
cfg = config.services.libreddit;
|
||||
in
|
||||
{
|
||||
services.libreddit = {
|
||||
enable = true;
|
||||
address = "127.0.0.1";
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."libreddit.sbruder.xyz" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations = {
|
||||
"/robots.txt".return = "200 'User-agent: *\\nDisallow: /'";
|
||||
"/".proxyPass = "http://${cfg.address}:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
}
|
44
machines/yuzuru/services/nitter.nix
Normal file
44
machines/yuzuru/services/nitter.nix
Normal file
|
@ -0,0 +1,44 @@
|
|||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.services.nitter;
|
||||
in
|
||||
{
|
||||
services.nitter = {
|
||||
enable = true;
|
||||
server = {
|
||||
port = 8081;
|
||||
hostname = "nitter.sbruder.xyz";
|
||||
address = "127.0.0.1";
|
||||
};
|
||||
preferences = {
|
||||
theme = "Auto";
|
||||
replaceTwitter = "${cfg.server.hostname}";
|
||||
muteVideos = true;
|
||||
hlsPlayback = true;
|
||||
replaceYouTube = "${config.services.invidious.domain}";
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${cfg.server.hostname} = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations = {
|
||||
"/robots.txt".return = "200 'User-agent: *\\nDisallow: /'";
|
||||
"/" = {
|
||||
proxyPass = "http://${cfg.server.address}:${toString cfg.server.port}";
|
||||
extraConfig =
|
||||
let
|
||||
# workaround for nginx dropping parent headers
|
||||
# see https://github.com/yandex/gixy/blob/master/docs/en/plugins/addheaderredefinition.md
|
||||
parentHeaders = lib.concatStringsSep "\n" (lib.filter
|
||||
(lib.hasPrefix "add_header ")
|
||||
(lib.splitString "\n" config.services.nginx.commonHttpConfig));
|
||||
in
|
||||
''
|
||||
${parentHeaders}
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' blob:; style-src 'self' 'unsafe-inline'; media-src 'self' blob:";
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
1
machines/yuzuru/services/sbruder.xyz/.gitignore
vendored
Normal file
1
machines/yuzuru/services/sbruder.xyz/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
index.html
|
40
machines/yuzuru/services/sbruder.xyz/default.nix
Normal file
40
machines/yuzuru/services/sbruder.xyz/default.nix
Normal file
|
@ -0,0 +1,40 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
services.nginx.virtualHosts."sbruder.xyz" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
|
||||
root = pkgs.stdenvNoCC.mkDerivation {
|
||||
name = "sbruder.xyz";
|
||||
|
||||
src = ./.;
|
||||
|
||||
nativeBuildInputs = with pkgs; [ pandoc ];
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
pandoc \
|
||||
-s \
|
||||
--metadata-file metadata.yaml \
|
||||
-f commonmark_x \
|
||||
-t html5 \
|
||||
-o index.html \
|
||||
index.md
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
install -D index.html $out/index.html
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
|
||||
locations = {
|
||||
"/imprint/".alias = "${pkgs.sbruder.imprint}/";
|
||||
};
|
||||
};
|
||||
}
|
64
machines/yuzuru/services/sbruder.xyz/index.md
Normal file
64
machines/yuzuru/services/sbruder.xyz/index.md
Normal file
|
@ -0,0 +1,64 @@
|
|||
On this domain, the following services are currently available:
|
||||
|
||||
* [Invidious](https://iv.sbruder.xyz)
|
||||
* [Libreddit](https://libreddit.sbruder.xyz)
|
||||
* [Nitter](https://nitter.sbruder.xyz)
|
||||
|
||||
They are all semi-public instances.
|
||||
That means, they are not included in lists of public instances,
|
||||
but feel free to use them for personal purposes.
|
||||
|
||||
You can do so by using a browser plugin like [Privacy Redirect](https://github.com/SimonBrazell/privacy-redirect)
|
||||
and configuring the addresses to point to this server.
|
||||
|
||||
However, please note the following if you want to use them:
|
||||
|
||||
* These services are provided as-is without any guarantees.
|
||||
* You must not use these services for any activities illegal under Finnish or German law.
|
||||
* You must not use these services to interfere with the operation of the services
|
||||
or the sites that originally provide the data.
|
||||
* Please don’t over/abuse these services.
|
||||
They run on a tiny VPS and won’t be able to handle high workloads.
|
||||
|
||||
Also note the following service-specific things:
|
||||
|
||||
* **Invidious**: There are no backups, so you are responsible for using the data export feature to back up important data.
|
||||
|
||||
The VPS providing the services is running NixOS.
|
||||
The configuration is available [here](https://git.sbruder.de/simon/nixos-config/src/branch/master/machines/yuzuru).
|
||||
|
||||
If you have any questions, please [contact me](https://sbruder.de).
|
||||
|
||||
## A Note to Copyright Holders
|
||||
|
||||
The services are only relaying content that is otherwise already available on the Internet.
|
||||
If your rights are infringed by content available from this site,
|
||||
please report this to the site originally making it available.
|
||||
Otherwise the content will still be available on the Internet.
|
||||
|
||||
If you still want to report illegal content to me instead of the original site,
|
||||
send me an Email to the address stated in the imprint.
|
||||
This is the fastest way to resolve the issue,
|
||||
so please use that if you care about it.
|
||||
|
||||
## Imprint
|
||||
|
||||
See [Imprint](/imprint/).
|
||||
|
||||
## Privacy
|
||||
|
||||
The Libreddit and Nitter services do not store your personally identifiable information.
|
||||
If you log in to an Invidious account,
|
||||
the data you provide to the service will be stored.
|
||||
You can export or delete that data by using its built-in data control feature.
|
||||
|
||||
In the case of an error, details of the problematic request might be stored on the server
|
||||
and used strictly for debugging and fixing the error.
|
||||
Those logs will be deleted after one week.
|
||||
|
||||
#### Fine Print
|
||||
|
||||
<small>
|
||||
This site and the services provided by it are not associated with YouTube, Reddit and/or Twitter.
|
||||
Trademarks are property of their respective owners.
|
||||
</small>
|
3
machines/yuzuru/services/sbruder.xyz/metadata.yaml
Normal file
3
machines/yuzuru/services/sbruder.xyz/metadata.yaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
title: sbruder.xyz
|
||||
|
||||
mainfont: Roboto, Helvetica, Arial, sans-serif
|
72
machines/yuzuru/services/schabernack.nix
Normal file
72
machines/yuzuru/services/schabernack.nix
Normal file
|
@ -0,0 +1,72 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
domain = "schulischer-schabernack.de";
|
||||
in
|
||||
{
|
||||
services.nginx = {
|
||||
commonHttpConfig = ''
|
||||
# privacy-aware log format
|
||||
log_format schabernack '$remote_addr_schabernack - - [$time_local] "$request" $status $body_bytes_sent "-" "$http_user_agent"';
|
||||
|
||||
# anonymise ip address
|
||||
map $remote_addr $remote_addr_schabernack {
|
||||
~(?P<ip>\d+\.\d+)\. $ip.0.0;
|
||||
~(?P<ip>[^:]+:[^:]+): $ip::;
|
||||
default 0.0.0.0;
|
||||
}
|
||||
'';
|
||||
|
||||
virtualHosts = {
|
||||
${domain} = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
|
||||
root = "/var/www/schabernack/production";
|
||||
|
||||
# only log page views, rss feed access, media file download and embed views
|
||||
extraConfig = ''
|
||||
location ~ index\.html|rss\.xml|\.(opus|m4a|ogg|mp3|\.podlove.json)$ {
|
||||
access_log /var/log/nginx/schabernack.log schabernack;
|
||||
}
|
||||
'';
|
||||
};
|
||||
"www.${domain}" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
globalRedirect = domain;
|
||||
|
||||
extraConfig = ''
|
||||
access_log off;
|
||||
'';
|
||||
};
|
||||
"staging.${domain}" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
|
||||
root = "/var/www/schabernack/staging";
|
||||
|
||||
extraConfig = ''
|
||||
access_log off;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/www/schabernack/production 0755 schabernack root -"
|
||||
"d /var/www/schabernack/staging 0755 schabernack root -"
|
||||
];
|
||||
|
||||
users = {
|
||||
users.schabernack = {
|
||||
isSystemUser = true;
|
||||
group = "schabernack";
|
||||
shell = "/bin/sh";
|
||||
|
||||
openssh.authorizedKeys.keys = map
|
||||
(key: "command=\"${pkgs.rrsync}/bin/rrsync -wo /var/www/schabernack/\",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ${key}")
|
||||
config.sbruder.pubkeys.trustedKeys;
|
||||
};
|
||||
groups.schabernack = { };
|
||||
};
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.sbruder.cpu.intel;
|
||||
in
|
||||
{
|
||||
options.sbruder.cpu.intel.enable = lib.mkEnableOption "intel cpu configuration";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
hardware.cpu.intel.updateMicrocode = true;
|
||||
};
|
||||
}
|
|
@ -8,33 +8,25 @@ lib.mkIf config.sbruder.gui.enable {
|
|||
enable = true;
|
||||
drivers = with pkgs; [
|
||||
gutenprint
|
||||
];
|
||||
] ++ lib.optional config.sbruder.unfree.allowSoftware (cups-kyocera-ecosys-m552x-p502x.override {
|
||||
# in Kyocera terms, EU means duplex enabled by default
|
||||
region = "EU";
|
||||
});
|
||||
};
|
||||
avahi.enable = true;
|
||||
};
|
||||
|
||||
hardware.printers.ensurePrinters = [
|
||||
{
|
||||
name = "kanna";
|
||||
deviceUri = "socket://kanna.home.sbruder.de";
|
||||
model = "${gutenprintWithVersion}://kyocera-fs-c5200dn/expert";
|
||||
ppdOptions = {
|
||||
PageSize = "A4";
|
||||
};
|
||||
}
|
||||
# printer is broken and makes systemd unit fail
|
||||
#{
|
||||
# name = "tintenpisser";
|
||||
# deviceUri = "ipp://tintenpisser.home.sbruder.de:631/ipp/print";
|
||||
# model = "everywhere";
|
||||
# ppdOptions = {
|
||||
# PageSize = "A4";
|
||||
# };
|
||||
#}
|
||||
{
|
||||
name = "ich_drucke_nicht";
|
||||
deviceUri = "socket://192.168.178.26";
|
||||
model = "${gutenprintWithVersion}://bjc-TS3100-series/expert";
|
||||
}
|
||||
] ++ lib.optionals config.sbruder.unfree.allowSoftware [
|
||||
{
|
||||
name = "elma";
|
||||
deviceUri = "socket://elma.home.sbruder.de";
|
||||
model = "Kyocera/Kyocera ECOSYS P5021cdn.PPD";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
|
|
@ -1,50 +1,45 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
# Taken from https://nixos.wiki/wiki/Overlays
|
||||
overlaysCompat = pkgs.writeTextFile {
|
||||
name = "overlays-compat";
|
||||
destination = "/overlays.nix";
|
||||
text = ''
|
||||
self: super:
|
||||
with super.lib;
|
||||
let
|
||||
# Load the system config and get the `nixpkgs.overlays` option
|
||||
overlays = (import <nixpkgs/nixos> { }).config.nixpkgs.overlays;
|
||||
in
|
||||
# Apply all overlays to the input of the current "main" overlay
|
||||
foldl' (flip extends) (_: super) overlays self
|
||||
'';
|
||||
};
|
||||
in
|
||||
|
||||
{
|
||||
# Options that affect multiple modules
|
||||
options.sbruder = {
|
||||
full = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Whether to build the full system. If disabled, the system closure will
|
||||
be smaller, but some features will not be available.
|
||||
'';
|
||||
default = true;
|
||||
};
|
||||
trusted = (lib.mkEnableOption "the trusted status of this machine (i.e. encrypted root)") // { default = true; };
|
||||
gui.enable = lib.mkEnableOption "gui";
|
||||
games.enable = lib.mkEnableOption "games";
|
||||
};
|
||||
|
||||
# All modules are imported but non-essential modules are activated by
|
||||
# configuration options
|
||||
imports = [
|
||||
./cpu
|
||||
../pkgs/modules.nix
|
||||
./cups.nix
|
||||
./docker.nix
|
||||
./fonts.nix
|
||||
./gpu
|
||||
./games.nix
|
||||
./grub.nix
|
||||
./gui.nix
|
||||
./initrd-ssh.nix
|
||||
./libvirt.nix
|
||||
./locales.nix
|
||||
./mailserver.nix
|
||||
./media-proxy.nix
|
||||
./mullvad
|
||||
./network-manager.nix
|
||||
./nginx-interactive-index
|
||||
./nginx.nix
|
||||
./nix.nix
|
||||
./office.nix
|
||||
./prometheus/node_exporter.nix
|
||||
./pubkeys.nix
|
||||
./pulseaudio.nix
|
||||
./restic.nix
|
||||
./pipewire.nix
|
||||
./restic
|
||||
./secrets.nix
|
||||
./ssd.nix
|
||||
./ssh.nix
|
||||
./tools.nix
|
||||
./udev.nix
|
||||
|
@ -52,7 +47,8 @@ in
|
|||
./wireguard
|
||||
];
|
||||
|
||||
config = {
|
||||
config = lib.mkMerge [
|
||||
{
|
||||
# Essential system tools
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
|
@ -69,62 +65,57 @@ in
|
|||
# Set zsh as default shell
|
||||
programs.zsh.enable = true;
|
||||
users.defaultUserShell = pkgs.zsh;
|
||||
environment.etc."zshrc.local".source = "${pkgs.grml-zsh-config}/etc/zsh/zshrc";
|
||||
|
||||
# command-not-found does not work without channels
|
||||
programs.command-not-found.enable = false;
|
||||
|
||||
# Sane swapping
|
||||
boot.kernel.sysctl."vm.swapiness" = 10;
|
||||
|
||||
# Store logs persistently
|
||||
services.journald.extraConfig = "Storage = persistent";
|
||||
|
||||
# Hard drive monitoring
|
||||
services.smartd.enable = true;
|
||||
services.smartd.enable = lib.mkDefault true;
|
||||
# Network monitoring
|
||||
services.vnstat.enable = true;
|
||||
|
||||
# Support for exotic file systems
|
||||
boot.supportedFilesystems = lib.optional config.sbruder.full "ntfs";
|
||||
|
||||
# Authentication/Encryption agents
|
||||
programs.gnupg.agent.enable = true;
|
||||
programs.ssh.startAgent = true;
|
||||
|
||||
# NixOS state version (see https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion)
|
||||
system.stateVersion = "20.03";
|
||||
# When this is set to true (default), routing everything through a
|
||||
# wireguard tunnel does not work.
|
||||
networking.firewall.checkReversePath = false;
|
||||
|
||||
nix = {
|
||||
nixPath = [
|
||||
"/var/src" # pinned nixpkgs and configuration
|
||||
"nixpkgs=/var/src/nixpkgs" # for nix run
|
||||
"nixpkgs-overlays=${overlaysCompat}"
|
||||
];
|
||||
# Make sudoers trusted nix users
|
||||
trustedUsers = [ "@wheel" ];
|
||||
# Open ports for quick tests
|
||||
networking.firewall = {
|
||||
allowedTCPPortRanges = lib.singleton { from = 9990; to = 9999; };
|
||||
allowedUDPPortRanges = lib.singleton { from = 9990; to = 9999; };
|
||||
};
|
||||
|
||||
# On-the-fly optimisation of nix store
|
||||
autoOptimiseStore = true;
|
||||
# Keep output of derivations with gc root
|
||||
extraOptions = ''
|
||||
keep-outputs = true
|
||||
keep-derivations = true
|
||||
# Globally set Let’s Encrypt requirements
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
email = "security@sbruder.de";
|
||||
};
|
||||
|
||||
system.activationScripts.diff = ''
|
||||
[ -L /run/current-system ] && ${pkgs.nixFlakes}/bin/nix \
|
||||
--experimental-features 'nix-command' \
|
||||
store \
|
||||
diff-closures /run/current-system "$systemConfig"
|
||||
'';
|
||||
|
||||
# Make nix build in background less noticeable
|
||||
daemonIONiceLevel = 5; # 0-7
|
||||
};
|
||||
systemd.services.nix-daemon.serviceConfig.CPUSchedulingPolicy = "batch";
|
||||
|
||||
nixpkgs.config = {
|
||||
# Add unstable channel
|
||||
packageOverrides = pkgs: {
|
||||
unstable = import (import ../nix/sources.nix).nixpkgs-unstable {
|
||||
config = config.nixpkgs.config;
|
||||
overlays = config.nixpkgs.overlays;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nixpkgs.overlays = [
|
||||
(import ../pkgs)
|
||||
];
|
||||
};
|
||||
}
|
||||
(lib.mkIf config.sbruder.full {
|
||||
services.fwupd.enable = true;
|
||||
})
|
||||
(lib.mkIf (!config.sbruder.full) {
|
||||
# Adapted from nixpkgs/nixos/modules/profiles/minimal.nix
|
||||
i18n.supportedLocales = map
|
||||
(locale: locale + "/UTF-8")
|
||||
((lib.singleton config.i18n.defaultLocale)
|
||||
++ (lib.attrValues config.i18n.extraLocaleSettings));
|
||||
|
||||
documentation.enable = lib.mkDefault false;
|
||||
})
|
||||
];
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
docker = {
|
||||
enable = true;
|
||||
logDriver = "journald";
|
||||
extraOptions = builtins.concatStringsSep " " [
|
||||
extraOptions = lib.concatStringsSep " " [
|
||||
"--ipv6"
|
||||
"--fixed-cidr-v6=fd00:d0ce:d0ce:d0ce::/64"
|
||||
];
|
||||
|
|
|
@ -3,19 +3,20 @@
|
|||
lib.mkIf config.sbruder.gui.enable {
|
||||
fonts = {
|
||||
fonts = with pkgs; [
|
||||
(nerdfonts.override { fonts = [ "Iosevka" ]; }) # default monospace font
|
||||
] ++ lib.optionals config.sbruder.full [
|
||||
google-fonts # google font collection (free)
|
||||
lmodern # Latin Modern for non-latex applications
|
||||
(nerdfonts.override { fonts = [ "Iosevka" ]; })
|
||||
#roboto # standalone roboto has awful kerning
|
||||
source-han-sans
|
||||
source-han-serif # CJK fonts
|
||||
] ++ lib.optionals (!config.sbruder.full) [
|
||||
roboto # default sans-serif font (normally included in google-fonts)
|
||||
] ++ lib.optionals config.sbruder.unfree.allowAssets [
|
||||
corefonts # good ol’ microsoft fonts
|
||||
vistafonts # newer microsoft fonts
|
||||
];
|
||||
|
||||
enableDefaultFonts = true;
|
||||
enableFontDir = true;
|
||||
|
||||
fontconfig = {
|
||||
defaultFonts = {
|
||||
|
@ -23,7 +24,7 @@ lib.mkIf config.sbruder.gui.enable {
|
|||
sansSerif = [ "Roboto" "Source Han Sans" ];
|
||||
serif = [ "Georgia" "Source Han Serif" ];
|
||||
};
|
||||
localConf = ''
|
||||
localConf = /* xml */ ''
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
|
||||
<fontconfig>
|
||||
|
|
23
modules/games.nix
Normal file
23
modules/games.nix
Normal file
|
@ -0,0 +1,23 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.sbruder.games;
|
||||
in
|
||||
{
|
||||
options.sbruder.games = {
|
||||
enable = lib.mkEnableOption "games";
|
||||
performanceIndex = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
Arbitrary number specifying how powerful the machine is. To be
|
||||
replaced by taking into account single- and multi-core CPU and GPU
|
||||
metrics separately should this system not map to my machines in
|
||||
practice.
|
||||
|
||||
* 2: ~ 2014 ultrabook
|
||||
* 8: ~ 2016 quad-core workstation with mid-range GPU
|
||||
'';
|
||||
default = 1;
|
||||
};
|
||||
};
|
||||
config = lib.mkIf cfg.enable { };
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.sbruder.gpu.amd;
|
||||
in
|
||||
{
|
||||
options.sbruder.gpu.amd.enable = lib.mkEnableOption "amd gpu configuration";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
hardware.opengl.extraPackages = with pkgs; [
|
||||
amdvlk
|
||||
rocm-opencl-icd
|
||||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
clinfo
|
||||
radeontop
|
||||
rocm-smi
|
||||
];
|
||||
|
||||
# force RGB otput for HDMI (otherwise the default is YCbCr)
|
||||
# see https://gitlab.freedesktop.org/drm/amd/-/issues/476
|
||||
#boot.kernelPatches = [
|
||||
# {
|
||||
# name = "force-rgb";
|
||||
# patch = pkgs.fetchpatch {
|
||||
# url = "https://gitlab.freedesktop.org/drm/amd/uploads/99b3664a49ec759075bde5c454e1d7c2/0001-force-rgb.patch";
|
||||
# sha256 = "03dhnlxx9vlj1x8izh3c3j4r9s75q47nx8kf6mbdxqfy3cj96mjm";
|
||||
# };
|
||||
# }
|
||||
#];
|
||||
};
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{ lib, ... }:
|
||||
{
|
||||
imports = [
|
||||
./amd.nix
|
||||
./intel.nix
|
||||
];
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.sbruder.gpu.intel;
|
||||
in
|
||||
{
|
||||
options.sbruder.gpu.intel.enable = lib.mkEnableOption "intel gpu configuration";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
hardware.opengl.extraPackages = with pkgs; [
|
||||
beignet
|
||||
vaapiIntel
|
||||
];
|
||||
};
|
||||
}
|
|
@ -8,8 +8,23 @@ lib.mkIf config.sbruder.gui.enable {
|
|||
extraPackages = [ ];
|
||||
};
|
||||
|
||||
# steam (and other high quality software) still ships 32 bit binaries
|
||||
hardware.opengl.driSupport32Bit = lib.mkIf pkgs.stdenv.isx86_64 true;
|
||||
xdg = {
|
||||
portal = {
|
||||
enable = true;
|
||||
extraPortals = with pkgs; [
|
||||
xdg-desktop-portal-wlr
|
||||
xdg-desktop-portal-gtk
|
||||
];
|
||||
gtkUsePortal = true;
|
||||
};
|
||||
};
|
||||
|
||||
services.logind.lidSwitchDocked = config.services.logind.lidSwitch;
|
||||
services.upower.enable = true;
|
||||
|
||||
# steam (and other high quality software) still ships 32 bit binaries
|
||||
hardware.opengl.driSupport32Bit = lib.mkDefault pkgs.stdenv.isx86_64;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
pkgs.gnome3.adwaita-icon-theme # lutris requires system-wide installation
|
||||
];
|
||||
}
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
ssh = {
|
||||
enable = lib.mkDefault config.boot.initrd.network.enable;
|
||||
port = 2222;
|
||||
# ssh-keygen -t ed25519 -N "" -f initrd-ssh-host-key -C HOSTNAME
|
||||
# pass insert -m nixos/machines/HOSTNAME/initrd-ssh-host-key < initrd-ssh-host-key
|
||||
# ssh-keygen -t ed25519 -N "" -f ssh_host_ed25519_key_initrd -C HOSTNAME
|
||||
# scp ssh_host_ed25519_key_initrd root@machine:/etc/ssh/
|
||||
hostKeys = [
|
||||
(toString <secrets/initrd-ssh-host-key>)
|
||||
"/etc/ssh/ssh_host_ed25519_key_initrd"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
options.sbruder.libvirt.enable = lib.mkEnableOption "libvirt";
|
||||
|
||||
config = {
|
||||
virtualisation.libvirtd.enable = config.sbruder.libvirt.enable;
|
||||
|
||||
environment.systemPackages = lib.mkIf config.sbruder.gui.enable [ pkgs.virt-manager ];
|
||||
};
|
||||
}
|
|
@ -10,4 +10,9 @@
|
|||
console.keyMap = "de";
|
||||
|
||||
time.timeZone = "Europe/Berlin";
|
||||
|
||||
location = {
|
||||
latitude = 49.52;
|
||||
longitude = 10.17;
|
||||
};
|
||||
}
|
||||
|
|
346
modules/mailserver.nix
Normal file
346
modules/mailserver.nix
Normal file
|
@ -0,0 +1,346 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.sbruder.mailserver;
|
||||
|
||||
certDir = config.security.acme.certs."${cfg.fqdn}".directory;
|
||||
in
|
||||
{
|
||||
options.sbruder.mailserver = with lib; with lib.types; {
|
||||
enable = mkEnableOption "simple mail server";
|
||||
fqdn = mkOption {
|
||||
type = str;
|
||||
description = ''
|
||||
FQDN of the mail server
|
||||
|
||||
It needs to have a matching reverse DNS record. Also, an acme
|
||||
certificate with this name has to be present.
|
||||
'';
|
||||
example = "mail.example.com";
|
||||
};
|
||||
storage = mkOption {
|
||||
type = path;
|
||||
description = "Location of the storage for mails";
|
||||
default = "/var/vmail";
|
||||
};
|
||||
domains = mkOption {
|
||||
type = listOf str;
|
||||
description = "Domains to serve";
|
||||
example = [ "example.com" "example.org" ];
|
||||
};
|
||||
users = mkOption {
|
||||
type = listOf (submodule {
|
||||
options = {
|
||||
address = mkOption {
|
||||
type = str;
|
||||
description = "Primary e-mail address of the user";
|
||||
example = "jdoe@example.com";
|
||||
};
|
||||
passwordHash = mkOption {
|
||||
type = str;
|
||||
description = ''
|
||||
Bcrypt hash of the user’s password. Please note that it will be
|
||||
world-readable in the nix store.
|
||||
|
||||
You can generate a password with `nix run nixpkgs.apacheHttpd -c
|
||||
htpasswd -nBC 12 "" | cut -d: -f2`
|
||||
'';
|
||||
example = "$2y$05$SHxhwVGx.XCd19HAcb1NKuidUxW1BwU7GeO0ZIcMTc5t2uZoYLVRK";
|
||||
};
|
||||
aliases = mkOption {
|
||||
type = listOf str;
|
||||
description = ''
|
||||
A list of aliases for the user.
|
||||
|
||||
If multiple users have the same alias defined, mail will be
|
||||
delivered to both of them.
|
||||
'';
|
||||
default = [ ];
|
||||
example = [
|
||||
"j.doe@example.com"
|
||||
"jane.doe@example.com"
|
||||
"postmaster@example.com"
|
||||
];
|
||||
};
|
||||
};
|
||||
});
|
||||
description = "Users of the mail server";
|
||||
};
|
||||
cleanHeaders = mkOption {
|
||||
type = listOf str;
|
||||
description = "A list of regular expressions that define what headers are filtered";
|
||||
default = [
|
||||
"/^\\s*Received:/"
|
||||
"/^\\s*User-Agent:/"
|
||||
"/^\\s*X-Mailer:/"
|
||||
"/^\\s*X-Originating-IP:/"
|
||||
];
|
||||
};
|
||||
rejectSenders = mkOption {
|
||||
type = listOf str;
|
||||
description = "A list of senders to reject mails from";
|
||||
default = [ ];
|
||||
example = [
|
||||
"newsletter@example.com"
|
||||
"spammer@example.com"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# Users and groups
|
||||
users.users.vmail = {
|
||||
uid = 10000;
|
||||
group = "vmail";
|
||||
home = cfg.storage;
|
||||
createHome = true;
|
||||
};
|
||||
|
||||
users.groups.vmail.gid = 10000;
|
||||
|
||||
# Firewall
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
143 # IMAP
|
||||
25 # SMTP
|
||||
587 # SMTP submission
|
||||
];
|
||||
|
||||
# Service dependencies
|
||||
systemd.services.dovecot2 = {
|
||||
wants = [ "acme-finished-${cfg.fqdn}.target" ];
|
||||
after = [ "acme-finished-${cfg.fqdn}.target" ];
|
||||
};
|
||||
systemd.services.postfix = {
|
||||
wants = [ "acme-finished-${cfg.fqdn}.target" ];
|
||||
requires = [ "dovecot2.service" ];
|
||||
after = [ "acme-finished-${cfg.fqdn}.target" "dovecot2.service" ];
|
||||
};
|
||||
|
||||
# Reload on certificate renewal
|
||||
security.acme.certs."${cfg.fqdn}".postRun = ''
|
||||
if systemctl is-active dovecot2; then
|
||||
systemctl --no-block reload dovecot2
|
||||
fi
|
||||
if systemctl is-active postfix; then
|
||||
systemctl --no-block reload postfix
|
||||
fi
|
||||
'';
|
||||
|
||||
# Postfix
|
||||
security.dhparams.params.postfix = { };
|
||||
services.postfix =
|
||||
let
|
||||
listToString = lib.concatStringsSep ",";
|
||||
|
||||
valiases =
|
||||
let
|
||||
# List of attribute sets with single key-value pair
|
||||
plainAliases = (lib.flatten
|
||||
(map
|
||||
({ address, aliases, ... }:
|
||||
map
|
||||
(alias: { "${alias}" = address; })
|
||||
(aliases ++ lib.singleton address))
|
||||
cfg.users));
|
||||
|
||||
# Attribute set with every alias mapped to a list of receivers
|
||||
mergedAliases = (lib.attrsets.foldAttrs
|
||||
(val: col: lib.singleton val ++ col)
|
||||
[ ]
|
||||
plainAliases);
|
||||
|
||||
# Contents of the aliases file
|
||||
aliasesString = (lib.concatStringsSep
|
||||
"\n"
|
||||
(lib.mapAttrsToList
|
||||
(alias: addresses: "${alias} ${listToString addresses}")
|
||||
mergedAliases));
|
||||
in
|
||||
pkgs.writeText
|
||||
"valiases"
|
||||
aliasesString;
|
||||
|
||||
access_sender = pkgs.writeText
|
||||
"access_sender"
|
||||
(lib.concatMapStringsSep
|
||||
"\n"
|
||||
(sender: "${sender} REJECT")
|
||||
cfg.rejectSenders);
|
||||
|
||||
submissionHeaderCleanupRules = pkgs.writeText "submission_header_cleanup_rules"
|
||||
(lib.concatMapStringsSep
|
||||
"\n"
|
||||
(regex: "${regex} IGNORE")
|
||||
cfg.cleanHeaders);
|
||||
in
|
||||
{
|
||||
enable = true;
|
||||
|
||||
enableSubmission = true;
|
||||
|
||||
hostname = cfg.fqdn;
|
||||
networksStyle = "host";
|
||||
sslCert = "${certDir}/fullchain.pem";
|
||||
sslKey = "${certDir}/key.pem";
|
||||
|
||||
recipientDelimiter = "+";
|
||||
|
||||
mapFiles = {
|
||||
inherit access_sender valiases;
|
||||
};
|
||||
|
||||
config = {
|
||||
# General
|
||||
smtpd_banner = "${cfg.fqdn} ESMTP NO UCE";
|
||||
disable_vrfy_command = true; # disable check if mailbox exists
|
||||
enable_long_queue_ids = true; # better for debugging
|
||||
strict_rfc821_envelopes = true; # only accept properly formatted envelope
|
||||
message_size_limit = "50331648"; # 48 MiB
|
||||
|
||||
virtual_mailbox_domains = listToString cfg.domains;
|
||||
virtual_mailbox_maps = "hash:/var/lib/postfix/conf/valiases";
|
||||
virtual_alias_maps = "hash:/var/lib/postfix/conf/valiases";
|
||||
virtual_transport = "lmtp:unix:/run/dovecot2/dovecot-lmtp";
|
||||
|
||||
smtpd_recipient_restrictions = listToString [
|
||||
"reject_non_fqdn_recipient"
|
||||
"reject_rbl_client ix.dnsbl.manitu.net"
|
||||
"reject_unknown_recipient_domain"
|
||||
"reject_unverified_recipient"
|
||||
];
|
||||
|
||||
smtpd_client_restrictions = listToString [
|
||||
"reject_rbl_client ix.dnsbl.manitu.net"
|
||||
"reject_unknown_client_hostname"
|
||||
];
|
||||
|
||||
smtpd_sender_restrictions = listToString [
|
||||
"check_sender_access hash:/var/lib/postfix/conf/access_sender"
|
||||
"reject_non_fqdn_sender"
|
||||
"reject_unknown_sender_domain"
|
||||
];
|
||||
|
||||
# generated 2021-02-04, Mozilla Guideline v5.6, Postfix 3.5.6, OpenSSL 1.1.1i, intermediate configuration
|
||||
# https://ssl-config.mozilla.org/#server=postfix&version=3.5.6&config=intermediate&openssl=1.1.1i&guideline=5.6
|
||||
smtpd_tls_security_level = "may";
|
||||
smtpd_tls_auth_only = "yes";
|
||||
smtpd_tls_mandatory_protocols = "!SSLv2, !SSLv3, !TLSv1, !TLSv1.1";
|
||||
smtpd_tls_protocols = "!SSLv2, !SSLv3, !TLSv1, !TLSv1.1";
|
||||
smtpd_tls_mandatory_ciphers = "medium";
|
||||
smtpd_tls_loglevel = "1";
|
||||
|
||||
tls_medium_cipherlist = listToString [
|
||||
"ECDHE-ECDSA-AES128-GCM-SHA256"
|
||||
"ECDHE-RSA-AES128-GCM-SHA256"
|
||||
"ECDHE-ECDSA-AES256-GCM-SHA384"
|
||||
"ECDHE-RSA-AES256-GCM-SHA384"
|
||||
"ECDHE-ECDSA-CHACHA20-POLY1305"
|
||||
"ECDHE-RSA-CHACHA20-POLY1305"
|
||||
"DHE-RSA-AES128-GCM-SHA256"
|
||||
"DHE-RSA-AES256-GCM-SHA384"
|
||||
];
|
||||
tls_preempt_cipherlist = "no";
|
||||
|
||||
smtpd_tls_dh1024_param_file = config.security.dhparams.params.postfix.path;
|
||||
};
|
||||
|
||||
submissionOptions = {
|
||||
smtpd_tls_security_level = "encrypt";
|
||||
smtpd_sasl_auth_enable = "yes";
|
||||
smtpd_sasl_type = "dovecot";
|
||||
smtpd_sasl_path = "/run/dovecot2/auth";
|
||||
|
||||
smtpd_sender_login_maps = "hash:/etc/postfix/valiases";
|
||||
|
||||
smtpd_recipient_restrictions = listToString [ ];
|
||||
|
||||
smtpd_client_restrictions = listToString [
|
||||
"permit_sasl_authenticated"
|
||||
"reject"
|
||||
];
|
||||
|
||||
smtpd_sender_restrictions = listToString [
|
||||
"reject_sender_login_mismatch"
|
||||
];
|
||||
|
||||
cleanup_service_name = "submission-header-cleanup";
|
||||
};
|
||||
|
||||
masterConfig = {
|
||||
submission-header-cleanup = {
|
||||
private = false;
|
||||
maxproc = 0;
|
||||
command = "cleanup";
|
||||
args = [ "-o" "header_checks=pcre:${submissionHeaderCleanupRules}" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Dovecot
|
||||
services.dovecot2 =
|
||||
let
|
||||
postfixCfg = config.services.postfix;
|
||||
|
||||
passdb = pkgs.writeText "dovecot-users"
|
||||
(lib.concatMapStringsSep
|
||||
"\n"
|
||||
({ address, passwordHash, ... }: "${address}:{BLF-CRYPT}${passwordHash}")
|
||||
cfg.users);
|
||||
in
|
||||
{
|
||||
enable = true;
|
||||
|
||||
enableLmtp = true;
|
||||
enablePAM = false;
|
||||
|
||||
mailUser = "vmail";
|
||||
mailGroup = "vmail";
|
||||
mailLocation = "maildir:${cfg.storage}/%d/%n";
|
||||
|
||||
sslServerCert = "${certDir}/fullchain.pem";
|
||||
sslServerKey = "${certDir}/key.pem";
|
||||
|
||||
extraConfig = ''
|
||||
# generated 2021-02-04, Mozilla Guideline v5.6, Dovecot 2.3.13, OpenSSL 1.1.1i, intermediate configuration
|
||||
# https://ssl-config.mozilla.org/#server=dovecot&version=2.3.13&config=intermediate&openssl=1.1.1i&guideline=5.6
|
||||
ssl = required
|
||||
ssl_min_protocol = TLSv1.2
|
||||
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
||||
ssl_prefer_server_ciphers = no
|
||||
|
||||
service imap-login {
|
||||
inet_listener imap {
|
||||
}
|
||||
}
|
||||
|
||||
service lmtp {
|
||||
unix_listener dovecot-lmtp {
|
||||
mode = 0600
|
||||
user = ${postfixCfg.user}
|
||||
group = ${postfixCfg.group}
|
||||
}
|
||||
}
|
||||
|
||||
passdb {
|
||||
driver = passwd-file
|
||||
args = username_format=%u ${passdb}
|
||||
}
|
||||
|
||||
userdb {
|
||||
driver = static
|
||||
args = uid=vmail gid=vmail home=${cfg.storage}/%d/%n
|
||||
}
|
||||
|
||||
service auth {
|
||||
unix_listener auth {
|
||||
mode = 0660
|
||||
user = ${postfixCfg.user}
|
||||
group = ${postfixCfg.group}
|
||||
}
|
||||
}
|
||||
|
||||
lda_mailbox_autosubscribe = yes
|
||||
lda_mailbox_autocreate = yes
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -2,21 +2,22 @@
|
|||
let
|
||||
port = 8888;
|
||||
services = {
|
||||
"media" = config.krops.secrets.media-proxy-auth.path;
|
||||
"scan" = config.krops.secrets.media-proxy-auth.path;
|
||||
"torrent" = config.krops.secrets.torrent-proxy-auth.path;
|
||||
"media" = config.sops.secrets.media-proxy-auth.path;
|
||||
"torrent" = config.sops.secrets.torrent-proxy-auth.path;
|
||||
};
|
||||
in
|
||||
{
|
||||
options.sbruder.media-proxy.enable = lib.mkEnableOption "media proxy";
|
||||
|
||||
config = lib.mkIf config.sbruder.media-proxy.enable {
|
||||
krops.secrets = {
|
||||
torrent-proxy-auth.group = "nginx";
|
||||
media-proxy-auth.group = "nginx";
|
||||
sops.secrets = {
|
||||
torrent-proxy-auth.owner = "nginx";
|
||||
media-proxy-auth.owner = "nginx";
|
||||
};
|
||||
users.users.nginx.extraGroups = [ "keys" ];
|
||||
systemd.services.nginx.serviceConfig.SupplementaryGroups = lib.singleton config.users.groups.keys.name;
|
||||
|
||||
# otherwise name resolution fails
|
||||
systemd.services.nginx.after = [ "network-online.target" ];
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
virtualHosts.media-proxy = {
|
||||
|
@ -27,7 +28,7 @@ in
|
|||
];
|
||||
locations = {
|
||||
"/".extraConfig = ''
|
||||
rewrite ^/__assets/(.*)$ /media/__assets/$1;
|
||||
rewrite ^/__nginx-interactive-index-assets__/(.*)$ /media/__nginx-interactive-index-assets__/$1;
|
||||
'';
|
||||
} // lib.mapAttrs'
|
||||
(name: secret: {
|
||||
|
|
72
modules/mullvad/default.nix
Normal file
72
modules/mullvad/default.nix
Normal file
|
@ -0,0 +1,72 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
relays = builtins.fromJSON (builtins.readFile ./relays.json);
|
||||
|
||||
cfg = config.sbruder.mullvad;
|
||||
|
||||
relayConfigs = lib.mapAttrs'
|
||||
(name: configuration: lib.nameValuePair "mullvad-${name}.conf" (with configuration; ''
|
||||
[Interface]
|
||||
DNS = ${cfg.dnsServer}
|
||||
|
||||
[Peer]
|
||||
Endpoint = ${if cfg.ipVersion == 4 then endpoint4 else endpoint6}:${toString cfg.port}
|
||||
PublicKey = ${pubkey}
|
||||
AllowedIPs = 0.0.0.0/0,::0/0
|
||||
''))
|
||||
relays;
|
||||
|
||||
# Creating 100+ files in a separate derivation each has too much overhead
|
||||
relayConfigFiles = pkgs.runCommandNoCC "etc-wireguard-mullvad" { } (''
|
||||
mkdir $out
|
||||
'' + (lib.concatStringsSep
|
||||
"\n"
|
||||
(lib.mapAttrsToList
|
||||
(name: content: ''
|
||||
cat > $out/${lib.escapeShellArg name} << EOF
|
||||
${content}
|
||||
EOF
|
||||
'')
|
||||
relayConfigs)));
|
||||
in
|
||||
{
|
||||
options.sbruder.mullvad = {
|
||||
enable = lib.mkEnableOption "wg-quick compatible configuration files in /etc/wireguard for Mullvad VPN";
|
||||
dnsServer = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "193.138.218.74";
|
||||
};
|
||||
ipVersion = lib.mkOption {
|
||||
type = lib.types.enum [ 4 6 ];
|
||||
default = 4;
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 51820;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment = {
|
||||
etc = builtins.listToAttrs
|
||||
(map
|
||||
(name: lib.nameValuePair "wireguard/${name}" { source = "${relayConfigFiles}/${name}"; })
|
||||
(lib.attrNames relayConfigs));
|
||||
|
||||
systemPackages = lib.singleton (pkgs.stdenv.mkDerivation {
|
||||
name = "mullvad-on-demand";
|
||||
|
||||
src = ./mullvad.sh;
|
||||
|
||||
dontUnpack = true;
|
||||
dontBuild = true;
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
install -D $src $out/bin/mullvad
|
||||
runHook postInstall
|
||||
'';
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
60
modules/mullvad/mullvad.sh
Executable file
60
modules/mullvad/mullvad.sh
Executable file
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/env bash
|
||||
# This reads wg-quick compatible configuration files from
|
||||
# /etc/wireguard/mullvad-LOCATION.conf
|
||||
#
|
||||
# Since they are autogenerated by nix and therefore world-readable, they do not
|
||||
# include secrets like the private key and client address. Instead, they are
|
||||
# manually added after wg-quick set up the tunnel by retrieving them with
|
||||
# pass(1) from web/mullvad.net/wireguard.
|
||||
#
|
||||
# Format of pass entry:
|
||||
# PrivateKey: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=
|
||||
# Address4: 10.0.0.1/32
|
||||
# Address6: fd00::1/128
|
||||
set -euo pipefail
|
||||
|
||||
if (( $# < 1 )); then
|
||||
echo "USAGE: $0 LOCATION|off" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
INTERFACE="mullvad-$1"
|
||||
|
||||
cmd() {
|
||||
echo "[#] $*" >&2
|
||||
sudo "$@"
|
||||
}
|
||||
|
||||
for interface in /sys/class/net/*; do
|
||||
interface="${interface#/sys/class/net/}"
|
||||
[[ $interface =~ ^mullvad-(v6-)?[a-z]{2}[0-9]*$ ]] && cmd wg-quick down "$interface"
|
||||
done
|
||||
|
||||
if [ "$1" != "off" ]; then
|
||||
# Make sure gpg-agent is unlocked so the period where the interface exists but
|
||||
# no private key is set is minised.
|
||||
pass web/mullvad.net/wireguard >/dev/null
|
||||
|
||||
cmd wg-quick up "$INTERFACE"
|
||||
pass web/mullvad.net/wireguard | while read -r line; do
|
||||
key="${line%%: *}"
|
||||
value="${line#*: }"
|
||||
case "$key" in
|
||||
PrivateKey)
|
||||
cmd wg set "$INTERFACE" private-key /dev/stdin <<< "$value"
|
||||
continue
|
||||
;;
|
||||
Address4)
|
||||
cmd ip -4 address add "$value" dev "$INTERFACE"
|
||||
continue
|
||||
;;
|
||||
Address6)
|
||||
cmd ip -6 address add "$value" dev "$INTERFACE"
|
||||
continue
|
||||
;;
|
||||
*)
|
||||
echo "Invalid key '$key'"
|
||||
exit 1
|
||||
esac
|
||||
done
|
||||
fi
|
2142
modules/mullvad/relays.json
Normal file
2142
modules/mullvad/relays.json
Normal file
File diff suppressed because it is too large
Load diff
12
modules/mullvad/update.sh
Executable file
12
modules/mullvad/update.sh
Executable file
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env bash
|
||||
# This gets the current wireguard relay list from mullvad’s API and transforms
|
||||
# it into a format that takes up less space than the original response.
|
||||
set -euo pipefail
|
||||
curl -s 'https://api.mullvad.net/www/relays/wireguard/' | jq '. | map({
|
||||
key: .hostname | split("-")[0],
|
||||
value: {
|
||||
endpoint4: .ipv4_addr_in,
|
||||
endpoint6: .ipv6_addr_in,
|
||||
pubkey: .pubkey
|
||||
}
|
||||
}) | from_entries' > relays.json
|
|
@ -1,7 +1,9 @@
|
|||
{ config, lib, ... }:
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
lib.mkIf config.sbruder.gui.enable {
|
||||
networking.networkmanager = {
|
||||
enable = true;
|
||||
};
|
||||
networking.networkmanager.enable = true;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
networkmanagerapplet
|
||||
];
|
||||
}
|
||||
|
|
69
modules/nginx-interactive-index/default.nix
Normal file
69
modules/nginx-interactive-index/default.nix
Normal file
|
@ -0,0 +1,69 @@
|
|||
# This module implements an option with the same structure as the nginx module
|
||||
# but does not extend the nginx module since that would cause infinite
|
||||
# recursion.
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
enabledLocations = lib.fold
|
||||
(x: a: a ++ x)
|
||||
[ ]
|
||||
(lib.mapAttrsToList
|
||||
(vhostName: vhostConfig: lib.mapAttrsToList
|
||||
(locationName: locationConfig: [ vhostName locationName ])
|
||||
(lib.filterAttrs
|
||||
(_: location: location.enable)
|
||||
vhostConfig.locations))
|
||||
config.services.nginx-interactive-index.virtualHosts);
|
||||
in
|
||||
{
|
||||
options.services.nginx-interactive-index.virtualHosts = with lib.types; lib.mkOption {
|
||||
default = { };
|
||||
type = attrsOf (submodule {
|
||||
options = {
|
||||
locations = lib.mkOption {
|
||||
default = { };
|
||||
type = attrsOf (submodule {
|
||||
options = {
|
||||
enable = lib.mkEnableOption "interactive directory index";
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
config.services.nginx.virtualHosts = lib.fold
|
||||
(x: a: a // x)
|
||||
{ }
|
||||
(map
|
||||
(path:
|
||||
let
|
||||
vhost = lib.elemAt path 0;
|
||||
location = lib.elemAt path 1;
|
||||
assetsPath = "${location}__nginx-interactive-index-assets__";
|
||||
in
|
||||
{
|
||||
"${vhost}".locations = {
|
||||
"${location}" = {
|
||||
extraConfig = ''
|
||||
autoindex on;
|
||||
autoindex_exact_size on;
|
||||
add_before_body ${assetsPath}/header.html;
|
||||
'';
|
||||
};
|
||||
"${assetsPath}/" = {
|
||||
alias = "${builtins.filterSource
|
||||
(path: type: baseNameOf path != "default.nix")
|
||||
./.}/";
|
||||
};
|
||||
"=${assetsPath}/header.html" = {
|
||||
alias = pkgs.writeText "nginx-interactive-index-${location}-header.html" ''
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="${assetsPath}/listing.css">
|
||||
<script src="${assetsPath}/listing.js"></script>
|
||||
'';
|
||||
};
|
||||
};
|
||||
})
|
||||
enabledLocations);
|
||||
}
|
48
modules/nginx-interactive-index/listing.css
Normal file
48
modules/nginx-interactive-index/listing.css
Normal file
|
@ -0,0 +1,48 @@
|
|||
body, html {
|
||||
background-color: #fdf6e3;
|
||||
color: #657b83;
|
||||
font-family: "TeX Gyre Heros", "Roboto", "Helvetica", "Arial", sans-serif;
|
||||
}
|
||||
|
||||
tr.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
tr.zebra-stripe {
|
||||
background: #eee8d5;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 0.1em 0.5em;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
background: #eee8d5;
|
||||
border-bottom: 1px solid #657b83;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #586e75;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #073642;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#search-field {
|
||||
width: 100%;
|
||||
border: none;
|
||||
margin-bottom: 15px;
|
||||
background: #eee8d5;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
hr {
|
||||
display: none;
|
||||
}
|
91
modules/nginx-interactive-index/listing.js
Normal file
91
modules/nginx-interactive-index/listing.js
Normal file
|
@ -0,0 +1,91 @@
|
|||
document.addEventListener('DOMContentLoaded', () => {
|
||||
function humanFileSize(bytes) {
|
||||
const thresh = 1024
|
||||
if(Math.abs(bytes) < thresh) {
|
||||
return bytes + ' B'
|
||||
}
|
||||
const units = ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB']
|
||||
var u = -1
|
||||
do {
|
||||
bytes /= thresh
|
||||
++u
|
||||
} while(Math.abs(bytes) >= thresh && u < units.length - 1)
|
||||
return bytes.toFixed(1)+' '+units[u]
|
||||
}
|
||||
|
||||
|
||||
function textToA(line) {
|
||||
let outerElement = document.createElement('div')
|
||||
outerElement.innerHTML = line
|
||||
return outerElement.getElementsByTagName('a')[0]
|
||||
}
|
||||
|
||||
function parseLine(line) {
|
||||
const href = textToA(line).href
|
||||
const filename = href.substr(-1) === '/' ? decodeURIComponent(href.split('/').slice(-2, -1)[0]) : decodeURIComponent(href.split('/').pop())
|
||||
const size = line.split(' ').pop()
|
||||
return {
|
||||
href: href,
|
||||
filename: filename,
|
||||
size: size
|
||||
}
|
||||
}
|
||||
|
||||
function processLine(line) {
|
||||
meta = parseLine(line)
|
||||
return `<tr><td><a href="${meta.href}">${meta.filename}</a></td><td>${meta.size === '-' ? '-' : humanFileSize(meta.size)}</td></tr>`
|
||||
}
|
||||
|
||||
function addZebraStripes(rows) {
|
||||
// this should be done in CSS, but AFAIU it does not support limiting
|
||||
// :nth-child to elements matching a previous :not selector
|
||||
rows.forEach((row, idx) => {
|
||||
if (idx % 2 === 0) {
|
||||
row.classList.add("zebra-stripe")
|
||||
} else {
|
||||
row.classList.remove("zebra-stripe")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const collator = new Intl.Collator('kn', {numeric: true})
|
||||
|
||||
// transform plain text to table
|
||||
document.querySelector('pre').outerHTML = '<table><thead><tr><th>Name</th><th>Size</th></tr></thead><tbody><tr><td><a href="..">..</a></td><td>-</td></tr>' + document.querySelector('pre').innerHTML
|
||||
.split('\n')
|
||||
.filter(line => line !== '')
|
||||
.filter(line => line !== '<a href="../">../</a>')
|
||||
.map(processLine)
|
||||
.sort(collator.compare)
|
||||
.join('\n') + '</tbody></table>'
|
||||
|
||||
let searchField = document.createElement('input')
|
||||
searchField.id = 'search-field'
|
||||
searchField.autofocus = true
|
||||
document.querySelector('body').insertBefore(searchField, document.querySelector('table'))
|
||||
|
||||
const rows = Array.from(document.querySelectorAll('tbody tr'))
|
||||
|
||||
addZebraStripes(rows)
|
||||
|
||||
document.querySelector('#search-field').addEventListener("input", e => {
|
||||
const searchValue = e.target.value.toLowerCase()
|
||||
rows.forEach(row => {
|
||||
const file = row.querySelector('td:nth-child(1) a').innerText
|
||||
if (!file.toLowerCase().includes(searchValue)) {
|
||||
row.classList.add("hidden")
|
||||
} else {
|
||||
row.classList.remove("hidden")
|
||||
}
|
||||
})
|
||||
|
||||
const visibleRows = rows.filter(row => !row.classList.contains("hidden"))
|
||||
if (visibleRows.length === 1) {
|
||||
const target = visibleRows[0].querySelector('td a').href
|
||||
if (target.substr(-1) === '/') {
|
||||
window.location = target
|
||||
}
|
||||
}
|
||||
addZebraStripes(visibleRows)
|
||||
})
|
||||
})
|
30
modules/nginx.nix
Normal file
30
modules/nginx.nix
Normal file
|
@ -0,0 +1,30 @@
|
|||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.sbruder.nginx;
|
||||
in
|
||||
{
|
||||
options.sbruder.nginx = {
|
||||
hardening.enable = lib.mkEnableOption "nginx hardening";
|
||||
privacy.enable = (lib.mkEnableOption "nginx privacy options") // { default = true; };
|
||||
};
|
||||
|
||||
config = lib.mkMerge [
|
||||
(lib.mkIf cfg.hardening.enable {
|
||||
services.nginx.commonHttpConfig = ''
|
||||
map $scheme $hsts_header {
|
||||
https "max-age=31536000";
|
||||
}
|
||||
add_header Strict-Transport-Security $hsts_header;
|
||||
|
||||
add_header Referrer-Policy strict-origin;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
'';
|
||||
})
|
||||
(lib.mkIf cfg.privacy.enable {
|
||||
services.nginx.commonHttpConfig = ''
|
||||
access_log off;
|
||||
'';
|
||||
})
|
||||
];
|
||||
}
|
91
modules/nix.nix
Normal file
91
modules/nix.nix
Normal file
|
@ -0,0 +1,91 @@
|
|||
{ config, inputs, lib, pkgs, ... }:
|
||||
let
|
||||
# Adapted from https://nixos.wiki/wiki/Overlays
|
||||
overlaysCompat = pkgs.writeTextFile {
|
||||
name = "overlays-compat";
|
||||
destination = "/overlays.nix";
|
||||
text = /* nix */ ''
|
||||
self: super:
|
||||
with super.lib;
|
||||
let
|
||||
# Load the system config and get the `nixpkgs.overlays` option
|
||||
# This fails gracefully if getFlake is not available
|
||||
overlays = if builtins.hasAttr "getFlake" builtins
|
||||
then (builtins.getFlake "/var/src/config").nixosConfigurations.${config.networking.hostName}.config.nixpkgs.overlays
|
||||
else [ ];
|
||||
in
|
||||
# Apply all overlays to the input of the current "main" overlay
|
||||
foldl' (flip extends) (_: super) overlays self
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
sops.secrets = lib.mkIf config.sbruder.trusted {
|
||||
binary-cache-secret-key = { };
|
||||
nix-netrc = {
|
||||
group = "wheel";
|
||||
mode = "0440";
|
||||
};
|
||||
};
|
||||
|
||||
nix = {
|
||||
# nix with flake support
|
||||
package = pkgs.nixFlakes;
|
||||
|
||||
registry = with inputs; {
|
||||
nixpkgs.flake = nixpkgs;
|
||||
nixpkgs-unstable.flake = nixpkgs-unstable;
|
||||
};
|
||||
|
||||
nixPath = [
|
||||
"nixpkgs=${inputs.nixpkgs}"
|
||||
"nixpkgs-overlays=${overlaysCompat}"
|
||||
];
|
||||
# Make sudoers trusted nix users
|
||||
trustedUsers = [ "@wheel" ];
|
||||
|
||||
binaryCaches = [
|
||||
"https://nix-cache.sbruder.de/"
|
||||
];
|
||||
binaryCachePublicKeys = [
|
||||
"nix-cache.sbruder.de-1:bU13eF6IMMW2hgO7StgB6JCAoZPeAQ27NAzV0kru1XM="
|
||||
];
|
||||
|
||||
# On-the-fly optimisation of nix store
|
||||
autoOptimiseStore = true;
|
||||
extraOptions = ''
|
||||
experimental-features = nix-command flakes
|
||||
'' + lib.optionalString config.sbruder.trusted ''
|
||||
# Binary cache upload
|
||||
secret-key-files = ${config.sops.secrets.binary-cache-secret-key.path}
|
||||
netrc-file = ${config.sops.secrets.nix-netrc.path}
|
||||
'' + lib.optionalString config.sbruder.full ''
|
||||
# Keep output of derivations with gc root
|
||||
keep-outputs = true
|
||||
keep-derivations = true
|
||||
'';
|
||||
|
||||
# Make nix build in background less noticeable
|
||||
daemonCPUSchedPolicy = "batch";
|
||||
daemonIOSchedPriority = 5; # 0-7
|
||||
};
|
||||
|
||||
nixpkgs.overlays = with inputs; [
|
||||
self.overlay
|
||||
nixpkgs-overlay.overlay
|
||||
(final: prev: {
|
||||
unstable = import nixpkgs-unstable {
|
||||
inherit (config.nixpkgs)
|
||||
config
|
||||
overlays
|
||||
system;
|
||||
};
|
||||
})
|
||||
|
||||
AriaNg.overlay
|
||||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
cached-nix-shell
|
||||
];
|
||||
}
|
34
modules/pipewire.nix
Normal file
34
modules/pipewire.nix
Normal file
|
@ -0,0 +1,34 @@
|
|||
{ config, lib, modulesPath, pkgs, ... }:
|
||||
let
|
||||
bluetoothSupport = config.sbruder.full;
|
||||
in
|
||||
lib.mkIf config.sbruder.gui.enable {
|
||||
sound.enable = true;
|
||||
security.rtkit.enable = true;
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
|
||||
pulse.enable = true;
|
||||
alsa = {
|
||||
enable = true;
|
||||
support32Bit = true;
|
||||
};
|
||||
|
||||
media-session = {
|
||||
config = {
|
||||
bluez-monitor = {
|
||||
"bluez5.enable-hw-volume" = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
helvum # patch panel
|
||||
pavucontrol
|
||||
pulseaudio # pacmd and pactl
|
||||
];
|
||||
|
||||
hardware.bluetooth.enable = lib.mkDefault bluetoothSupport;
|
||||
services.blueman.enable = lib.mkDefault bluetoothSupport;
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
enable = config.sbruder.wireguard.home.enable;
|
||||
listenAddress = config.sbruder.wireguard.home.address;
|
||||
enabledCollectors = [ "systemd" ];
|
||||
disabledCollectors = [ "rapl" ];
|
||||
};
|
||||
|
||||
systemd.services.prometheus-node-exporter.after = [ "wireguard-wg-home.service" ];
|
||||
|
|
|
@ -8,22 +8,22 @@ in
|
|||
type = lib.types.attrsOf lib.types.str;
|
||||
description = "Known public keys that can be used in the configuration";
|
||||
default = {
|
||||
"simon@nunotaba" = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCwMo0mYcTU1Y4BKpEUsvKAtcTPq3ylKaw+ZjUxNg9VqU5gDy2TDUfWk2FjM2VYcqQJ9ZaNGKE1S18fRU7ZHrcgtFPMgAuji87yOKojH74cwz9ZRf5ZiluWBmR3dFd7kddqHUKVS8utpiQuTLIyQwpgmUHA81IasWXuB2pHaI6HGntMlJTm1CvpcQvwKsDBqJ2bFjFMk6EDgAZWXyooQgthYAfmc+YfAX5T9fWKiqFnEJ0ryN3/RngJZe65HWV8WZwY1CxgKQhOZuRcPdkTEQlUk9Qu0JbVa2sTgdYDpw/Dz0ma+h4rxOrH63MD6Cf0pFgOwLeZVSmXqKTjXVaH1QkHWRat88J8Q6MM6LlhLx/48VcQshhIssAZ37YoW2W0NxnGSM7YtlwTVe+w7rU//cS5TyIQa4joq2pnIh4uurbNkIULa4Q2t2nEMzlqI9gEE9DK1ctOcuCyFOerNZD0yRZ5Rs8WouDLL1PR6ps4czK2N7h2MXABcELuVwX+sdxwFgf6AJaRvrlw4qIOohpeX48FhzZfcI9Cqvnakm+O42J3qXuUDVc6/NjE9zBku3dNaeseGv9CQxtvyVDq6o9MRDiFror3yEiN0Fwou7CXBfXrbeb7MvahsRxSKkSDY0uA+AXmsm1UwdArjEcEMsS1JeFQCdX1yR/Z5xzj2gx60NcR4w==";
|
||||
"simon@sayuri" = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC1kQUoPII8A9/bgPA+OrZGQLPA8MxkdmPSCCsfGMh9qRZfF7BSD8W6VdE/28tLw+39QeUl1+/9VuVvGjZBP1zBAbKIcKx4DjtgxpNXCsfWMjXFtpTGk2dyl71CaY5n72YlADxXYwtEvuwfNixgE2yTCefMbBsfwqYC0GZGiDlFtjxdg+RuUC8jU++C+WFUFct9gj9ieQ0LWjud+Oh0AF0JhyGnou+wVZIIO8mwo7Cc5xiPldXhbc13XiNC3mpNGCLFj+nh1feazk8TeAVDBps6xaDkOd+hDwTBQh8LoimePK7MiShzLvC38Vd/sim5ym/IqY634CjqBDGCMp1KXnqHUTT8CqeifMv10+aRJKUPevVkO3nEE3VoSPt7Ui9ZzLnL4qhZyygoBau+PvD2WCWm+gRwBkvU1uNrYKi4HIGhB/gXcYHKJimqJwLMyqG5Wv1jfuhn3ZZN+uNqTgdAznGgPRU1Q/Mx6nMEDiQip78qdYEc0YGwdb/TldEL6aHRjuNuZPpTW+zakQHiQTRb/0VdZT1bAwyT9yL0Uf40h706Kh/pKiSQ1yq1dlSdl3RlfedbqLqGjspds1iRSrSXyH2MBghPbz/SF7Vt4LW/tXF0rcyV7CU98ZvxJDWeN60OE0vPf/AT5udYyfPO1691y0F8jGKxGYYPg9R/Y5o7J24PbQ==";
|
||||
"simon@mayushii" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAJ7qUGZUjiDhQ6Se+aXr9DbgRTG2tx69owqVMkd2bna";
|
||||
};
|
||||
};
|
||||
trustedNames = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = "Names of trusted public keys, used to generate <literal>sbruder.pubkeys.trustedKeys</literal>";
|
||||
default = [
|
||||
"simon@nunotaba"
|
||||
"simon@sayuri"
|
||||
"simon@mayushii"
|
||||
];
|
||||
};
|
||||
trustedKeys = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = "Trusted public keys, automatically generated from <literal>sbruder.pubkeys.trustedNames</literal>";
|
||||
default = builtins.map
|
||||
default = map
|
||||
(name: cfg.keys."${name}")
|
||||
cfg.trustedNames;
|
||||
};
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
lib.mkIf config.sbruder.gui.enable {
|
||||
sound.enable = true;
|
||||
hardware.pulseaudio = {
|
||||
enable = true;
|
||||
package = pkgs.pulseaudioFull;
|
||||
extraModules = [
|
||||
pkgs.pulseaudio-modules-bt # Non-standard codecs for bluetooth
|
||||
];
|
||||
daemon.config = {
|
||||
"default-sample-format" = "s16le";
|
||||
"default-sample-rate" = "48000";
|
||||
"alternate-sample-rate" = "44100";
|
||||
"resample-method" = "soxr-hq";
|
||||
"flat-volumes" = "no";
|
||||
};
|
||||
};
|
||||
|
||||
# Bluetooth support
|
||||
hardware.bluetooth.enable = true;
|
||||
services.blueman.enable = true;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
pavucontrol
|
||||
];
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./intel.nix
|
||||
./system.nix
|
||||
];
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue