nix machine / user configurations

Compare changes

Choose any two refs to compare.

Changed files
+6184 -3607
_sources
dns
hosts
chernobog
dzwonek
modules
trimounts
wolumonde
pkgs-set
secrets
users
+90 -50
_sources/generated.json
··· 22 22 }, 23 23 "blog": { 24 24 "cargoLocks": null, 25 - "date": "2025-10-11", 25 + "date": "2025-12-26", 26 26 "extract": null, 27 27 "name": "blog", 28 28 "passthru": null, ··· 32 32 "fetchSubmodules": false, 33 33 "leaveDotGit": false, 34 34 "name": null, 35 - "rev": "4705c8e9339683f0ed947224de5be50a41399bfd", 36 - "sha256": "sha256-Zv1R9k4483aZQS0uhBm4jmnGmpOS1fJc10rsXntdz5I=", 35 + "rev": "95c18d69c811a6483df1a2c6b727f696db39858e", 36 + "sha256": "sha256-VeX7C0PQdhQu14xxeCftFUFWO7MhssvulC319s82Jt4=", 37 37 "sparseCheckout": [], 38 38 "type": "git", 39 39 "url": "https://tangled.org/@ptr.pet/endpoint" 40 40 }, 41 - "version": "4705c8e9339683f0ed947224de5be50a41399bfd" 41 + "version": "95c18d69c811a6483df1a2c6b727f696db39858e" 42 + }, 43 + "clickee": { 44 + "cargoLocks": null, 45 + "date": "2025-09-14", 46 + "extract": null, 47 + "name": "clickee", 48 + "passthru": null, 49 + "pinned": false, 50 + "src": { 51 + "deepClone": false, 52 + "fetchSubmodules": false, 53 + "leaveDotGit": false, 54 + "name": null, 55 + "rev": "ca379a35ac60cc80fa4bf68a27ee0c30724ad324", 56 + "sha256": "sha256-NuXYKiCzicWJxwHg4mQYYMUhOd83o+cYjqrUiSKjDEs=", 57 + "sparseCheckout": [], 58 + "type": "git", 59 + "url": "https://tangled.org/@ptr.pet/clickee" 60 + }, 61 + "version": "ca379a35ac60cc80fa4bf68a27ee0c30724ad324" 42 62 }, 43 63 "clickee-proxy": { 44 64 "cargoLocks": null, ··· 62 82 }, 63 83 "disko": { 64 84 "cargoLocks": null, 65 - "date": "2025-11-25", 85 + "date": "2025-12-19", 66 86 "extract": null, 67 87 "name": "disko", 68 88 "passthru": null, ··· 74 94 "name": null, 75 95 "owner": "nix-community", 76 96 "repo": "disko", 77 - "rev": "aecba248f9a7d68c5d1ed15de2d1c8a4c994a3c5", 78 - "sha256": "sha256-xanUzIb0tf3kJ+PoOFmXEXV1jM3PjkDT/TQ5DYeNYRc=", 97 + "rev": "916506443ecd0d0b4a0f4cf9d40a3c22ce39b378", 98 + "sha256": "sha256-P0kM+5o+DKnB6raXgFEk3azw8Wqg5FL6wyl9jD+G5a4=", 79 99 "sparseCheckout": [], 80 100 "type": "github" 81 101 }, 82 - "version": "aecba248f9a7d68c5d1ed15de2d1c8a4c994a3c5" 102 + "version": "916506443ecd0d0b4a0f4cf9d40a3c22ce39b378" 103 + }, 104 + "dysnomia": { 105 + "cargoLocks": null, 106 + "date": "2025-12-22", 107 + "extract": null, 108 + "name": "dysnomia", 109 + "passthru": null, 110 + "pinned": false, 111 + "src": { 112 + "deepClone": false, 113 + "fetchSubmodules": false, 114 + "leaveDotGit": false, 115 + "name": null, 116 + "rev": "1f371223d2ffe80385c63119b325d8da7a4c7e7e", 117 + "sha256": "sha256-hUFMvmKEO65yw8Igkf4323t6uvKukaojQMNm+8tN4rc=", 118 + "sparseCheckout": [], 119 + "type": "git", 120 + "url": "https://tangled.org/@ptr.pet/dysnomia" 121 + }, 122 + "version": "1f371223d2ffe80385c63119b325d8da7a4c7e7e" 83 123 }, 84 124 "facter": { 85 125 "cargoLocks": null, 86 - "date": "2025-11-04", 126 + "date": "2025-12-24", 87 127 "extract": null, 88 128 "name": "facter", 89 129 "passthru": null, ··· 95 135 "name": null, 96 136 "owner": "nix-community", 97 137 "repo": "nixos-facter-modules", 98 - "rev": "fa695bff9ec37fd5bbd7ee3181dbeb5f97f53c96", 99 - "sha256": "sha256-iaRf6n0KPl9hndnIft3blm1YTAyxSREV1oX0MFZ6Tk4=", 138 + "rev": "e796d536e3d83de74267069e179dc620a608ed7d", 139 + "sha256": "sha256-Ud9v49ZPsoDBFuyJSQ2Mpw1ZgAH/aMwUwwzrVoetNus=", 100 140 "sparseCheckout": [], 101 141 "type": "github" 102 142 }, 103 - "version": "fa695bff9ec37fd5bbd7ee3181dbeb5f97f53c96" 143 + "version": "e796d536e3d83de74267069e179dc620a608ed7d" 104 144 }, 105 145 "gomod2nix": { 106 146 "cargoLocks": null, ··· 125 165 }, 126 166 "home": { 127 167 "cargoLocks": null, 128 - "date": "2025-11-26", 168 + "date": "2025-12-27", 129 169 "extract": null, 130 170 "name": "home", 131 171 "passthru": null, ··· 137 177 "name": null, 138 178 "owner": "nix-community", 139 179 "repo": "home-manager", 140 - "rev": "9651819d75f6c7ffaf8a9227490ac704f29659f0", 141 - "sha256": "sha256-iUM9ktarEzThkayyZrzQ7oycPshAY2XRQqVKz0xX/L0=", 180 + "rev": "4067ca1ffb6425b8597eafb63a84b171e0192d2b", 181 + "sha256": "sha256-Ok0jocJ82JriaMDtYEytR8oWcxADlX5WcWXULrN4czA=", 142 182 "sparseCheckout": [], 143 183 "type": "github" 144 184 }, 145 - "version": "9651819d75f6c7ffaf8a9227490ac704f29659f0" 185 + "version": "4067ca1ffb6425b8597eafb63a84b171e0192d2b" 146 186 }, 147 187 "limbusart": { 148 188 "cargoLocks": null, ··· 160 200 "sha256": "sha256-xATZz/sHYHkEXjwcmq1DSntclWxnDIKCpH314MaL63U=", 161 201 "sparseCheckout": [], 162 202 "type": "git", 163 - "url": "https://git.gaze.systems/90008/limbusart.git" 203 + "url": "https://github.com/90-008/limbusart.git" 164 204 }, 165 205 "version": "7f29ab57b73eb8a4db7163fc7d19a71cf89c3d8b" 166 206 }, 167 207 "moonlight": { 168 208 "cargoLocks": null, 169 - "date": "2025-11-26", 209 + "date": "2025-12-16", 170 210 "extract": null, 171 211 "name": "moonlight", 172 212 "passthru": null, ··· 178 218 "name": null, 179 219 "owner": "moonlight-mod", 180 220 "repo": "moonlight", 181 - "rev": "059476af87f7335c05424b805833864d6d9ed0e3", 182 - "sha256": "sha256-Qur5AWl4Vx+It65DX+I+sc4lViz52OmXqvg+fL2t9I4=", 221 + "rev": "d0ad754cf0b9c5a34d7f69595f407c8199f988ce", 222 + "sha256": "sha256-qc4m7v8hGOMb9BVLuiQZAbgzHoKfVwEY7HUl9fsY/hE=", 183 223 "sparseCheckout": [], 184 224 "type": "github" 185 225 }, 186 - "version": "059476af87f7335c05424b805833864d6d9ed0e3" 226 + "version": "d0ad754cf0b9c5a34d7f69595f407c8199f988ce" 187 227 }, 188 228 "ncr": { 189 229 "cargoLocks": null, ··· 207 247 }, 208 248 "nixos-hardware": { 209 249 "cargoLocks": null, 210 - "date": "2025-11-25", 250 + "date": "2025-12-24", 211 251 "extract": null, 212 252 "name": "nixos-hardware", 213 253 "passthru": null, ··· 219 259 "name": null, 220 260 "owner": "NixOS", 221 261 "repo": "nixos-hardware", 222 - "rev": "da17006633ca9cda369be82893ae36824a2ddf1a", 223 - "sha256": "sha256-b1MtLQsQc4Ji1u08f+C6g5XrmLPkJQ1fhNkCt+0AERQ=", 262 + "rev": "c5db9569ac9cc70929c268ac461f4003e3e5ca80", 263 + "sha256": "sha256-UXVtN77D7pzKmzOotFTStgZBqpOcf8cO95FcupWp4Zo=", 224 264 "sparseCheckout": [], 225 265 "type": "github" 226 266 }, 227 - "version": "da17006633ca9cda369be82893ae36824a2ddf1a" 267 + "version": "c5db9569ac9cc70929c268ac461f4003e3e5ca80" 228 268 }, 229 269 "nixpkgs-xr": { 230 270 "cargoLocks": null, 231 - "date": "2025-11-27", 271 + "date": "2025-12-24", 232 272 "extract": null, 233 273 "name": "nixpkgs-xr", 234 274 "passthru": null, ··· 240 280 "name": null, 241 281 "owner": "nix-community", 242 282 "repo": "nixpkgs-xr", 243 - "rev": "cd67b4986ffb7c4b136b6d4286c94375c74867bc", 244 - "sha256": "sha256-D8d1g9aaZlTc/xZjbeaHJUwmJDAOqjqZNucMrq6wCKc=", 283 + "rev": "9e8efcd2c4ea906772dea99204a9819284a29b81", 284 + "sha256": "sha256-biwvZsCGC4vCXS6rzs3tUkELqqEXPko0E3R9IhYKavE=", 245 285 "sparseCheckout": [], 246 286 "type": "github" 247 287 }, 248 - "version": "cd67b4986ffb7c4b136b6d4286c94375c74867bc" 288 + "version": "9e8efcd2c4ea906772dea99204a9819284a29b81" 249 289 }, 250 290 "nsid-tracker": { 251 291 "cargoLocks": null, ··· 269 309 }, 270 310 "nucleus": { 271 311 "cargoLocks": null, 272 - "date": "2025-11-11", 312 + "date": "2025-12-27", 273 313 "extract": null, 274 314 "name": "nucleus", 275 315 "passthru": null, ··· 279 319 "fetchSubmodules": false, 280 320 "leaveDotGit": false, 281 321 "name": null, 282 - "rev": "a4f73517c1a76ed20b55f21618148b8afe0fa838", 283 - "sha256": "sha256-8WrGAr+aCIFCFuixtH1BSB5lMn+d/FqXsEFAmXY3HkU=", 322 + "rev": "2ad7bd0b2710896cdf31638c32ceacc02a226726", 323 + "sha256": "sha256-AXZhPcOvCCwFhntqLoZZtyaNTV6RQeS7I74RFzmFeiM=", 284 324 "sparseCheckout": [], 285 325 "type": "git", 286 326 "url": "https://tangled.org/@ptr.pet/nucleus" 287 327 }, 288 - "version": "a4f73517c1a76ed20b55f21618148b8afe0fa838" 328 + "version": "2ad7bd0b2710896cdf31638c32ceacc02a226726" 289 329 }, 290 330 "stylix": { 291 331 "cargoLocks": null, 292 - "date": "2025-11-26", 332 + "date": "2025-12-24", 293 333 "extract": null, 294 334 "name": "stylix", 295 335 "passthru": null, ··· 301 341 "name": null, 302 342 "owner": "nix-community", 303 343 "repo": "stylix", 304 - "rev": "70c444a10d0c9ef71a25580dfa79af9cd43f3a5e", 305 - "sha256": "sha256-rofXPD/9TGpHveo1MTlUfpnF0MCG1/uHUB9f0rosdqc=", 344 + "rev": "551df12ee3ebac52c5712058bd97fd9faa4c3430", 345 + "sha256": "sha256-J2DDdRqSU4w9NNgkMfmMeaLIof5PXtS9RG7y6ckDvQE=", 306 346 "sparseCheckout": [], 307 347 "type": "github" 308 348 }, 309 - "version": "70c444a10d0c9ef71a25580dfa79af9cd43f3a5e" 349 + "version": "551df12ee3ebac52c5712058bd97fd9faa4c3430" 310 350 }, 311 351 "tangled": { 312 352 "cargoLocks": null, 313 - "date": "2025-11-24", 353 + "date": "2025-12-20", 314 354 "extract": null, 315 355 "name": "tangled", 316 356 "passthru": null, ··· 320 360 "fetchSubmodules": false, 321 361 "leaveDotGit": false, 322 362 "name": null, 323 - "rev": "7358ec6edfa4d17b8b8f543d99e83a4705901148", 324 - "sha256": "sha256-PzuWiW/nMxwQTX0i1bHwGazQF4ptLNI9OGwpmhDb9i0=", 363 + "rev": "716a5bc0dafb96bbf72fb6e07d20e251f97c9f4e", 364 + "sha256": "sha256-SGG97w/bvffP6zuJwbnFHK6tdfuWEzKNOfjGbh2PIj0=", 325 365 "sparseCheckout": [], 326 366 "type": "git", 327 - "url": "https://tangled.org/@tangled.org/core" 367 + "url": "https://tangled.org/ptr.pet/core" 328 368 }, 329 - "version": "7358ec6edfa4d17b8b8f543d99e83a4705901148" 369 + "version": "716a5bc0dafb96bbf72fb6e07d20e251f97c9f4e" 330 370 }, 331 371 "tangled-sqlite-lib": { 332 372 "cargoLocks": null, ··· 344 384 }, 345 385 "trill": { 346 386 "cargoLocks": null, 347 - "date": "2025-11-25", 387 + "date": "2025-12-25", 348 388 "extract": null, 349 389 "name": "trill", 350 390 "passthru": null, ··· 354 394 "fetchSubmodules": false, 355 395 "leaveDotGit": false, 356 396 "name": null, 357 - "rev": "c9604685156e009cebd0ddc3b31672455f635387", 358 - "sha256": "sha256-so9EHN0GQ7rFSmnLnpRap2RqRcklhe3C1HdyAKeR6No=", 397 + "rev": "d395ba493b4735f82db9ce99c7e7e8b671b38225", 398 + "sha256": "sha256-mxV02sfP7H2lv/xD9MkVHfp6F8dnYQly7rhTRpMEeiw=", 359 399 "sparseCheckout": [], 360 400 "type": "git", 361 401 "url": "https://tangled.org/@ptr.pet/trill" 362 402 }, 363 - "version": "c9604685156e009cebd0ddc3b31672455f635387" 403 + "version": "d395ba493b4735f82db9ce99c7e7e8b671b38225" 364 404 }, 365 405 "zen-browser": { 366 406 "cargoLocks": null, 367 - "date": "2025-11-26", 407 + "date": "2025-12-25", 368 408 "extract": null, 369 409 "name": "zen-browser", 370 410 "passthru": null, ··· 376 416 "name": null, 377 417 "owner": "0xc000022070", 378 418 "repo": "zen-browser-flake", 379 - "rev": "6f5d615393a5e923ea2883ef28e274031d1b1e1e", 380 - "sha256": "sha256-AEpt8JdKA4RVobRjaR7S2QP3bmUz8dhuWasB7mr9Ylo=", 419 + "rev": "98d8f48ba80a4b6e3b56addad850d57132301075", 420 + "sha256": "sha256-mGZBEN67mxeOsBhplBRLm6L+y++8jU46EEUYgemG1aQ=", 381 421 "sparseCheckout": [], 382 422 "type": "github" 383 423 }, 384 - "version": "6f5d615393a5e923ea2883ef28e274031d1b1e1e" 424 + "version": "98d8f48ba80a4b6e3b56addad850d57132301075" 385 425 } 386 426 }
+78 -50
_sources/generated.nix
··· 15 15 }; 16 16 blog = { 17 17 pname = "blog"; 18 - version = "4705c8e9339683f0ed947224de5be50a41399bfd"; 18 + version = "95c18d69c811a6483df1a2c6b727f696db39858e"; 19 19 src = fetchgit { 20 20 url = "https://tangled.org/@ptr.pet/endpoint"; 21 - rev = "4705c8e9339683f0ed947224de5be50a41399bfd"; 21 + rev = "95c18d69c811a6483df1a2c6b727f696db39858e"; 22 22 fetchSubmodules = false; 23 23 deepClone = false; 24 24 leaveDotGit = false; 25 25 sparseCheckout = [ ]; 26 - sha256 = "sha256-Zv1R9k4483aZQS0uhBm4jmnGmpOS1fJc10rsXntdz5I="; 26 + sha256 = "sha256-VeX7C0PQdhQu14xxeCftFUFWO7MhssvulC319s82Jt4="; 27 27 }; 28 - date = "2025-10-11"; 28 + date = "2025-12-26"; 29 + }; 30 + clickee = { 31 + pname = "clickee"; 32 + version = "ca379a35ac60cc80fa4bf68a27ee0c30724ad324"; 33 + src = fetchgit { 34 + url = "https://tangled.org/@ptr.pet/clickee"; 35 + rev = "ca379a35ac60cc80fa4bf68a27ee0c30724ad324"; 36 + fetchSubmodules = false; 37 + deepClone = false; 38 + leaveDotGit = false; 39 + sparseCheckout = [ ]; 40 + sha256 = "sha256-NuXYKiCzicWJxwHg4mQYYMUhOd83o+cYjqrUiSKjDEs="; 41 + }; 42 + date = "2025-09-14"; 29 43 }; 30 44 clickee-proxy = { 31 45 pname = "clickee-proxy"; ··· 43 57 }; 44 58 disko = { 45 59 pname = "disko"; 46 - version = "aecba248f9a7d68c5d1ed15de2d1c8a4c994a3c5"; 60 + version = "916506443ecd0d0b4a0f4cf9d40a3c22ce39b378"; 47 61 src = fetchFromGitHub { 48 62 owner = "nix-community"; 49 63 repo = "disko"; 50 - rev = "aecba248f9a7d68c5d1ed15de2d1c8a4c994a3c5"; 64 + rev = "916506443ecd0d0b4a0f4cf9d40a3c22ce39b378"; 51 65 fetchSubmodules = false; 52 - sha256 = "sha256-xanUzIb0tf3kJ+PoOFmXEXV1jM3PjkDT/TQ5DYeNYRc="; 66 + sha256 = "sha256-P0kM+5o+DKnB6raXgFEk3azw8Wqg5FL6wyl9jD+G5a4="; 53 67 }; 54 - date = "2025-11-25"; 68 + date = "2025-12-19"; 69 + }; 70 + dysnomia = { 71 + pname = "dysnomia"; 72 + version = "1f371223d2ffe80385c63119b325d8da7a4c7e7e"; 73 + src = fetchgit { 74 + url = "https://tangled.org/@ptr.pet/dysnomia"; 75 + rev = "1f371223d2ffe80385c63119b325d8da7a4c7e7e"; 76 + fetchSubmodules = false; 77 + deepClone = false; 78 + leaveDotGit = false; 79 + sparseCheckout = [ ]; 80 + sha256 = "sha256-hUFMvmKEO65yw8Igkf4323t6uvKukaojQMNm+8tN4rc="; 81 + }; 82 + date = "2025-12-22"; 55 83 }; 56 84 facter = { 57 85 pname = "facter"; 58 - version = "fa695bff9ec37fd5bbd7ee3181dbeb5f97f53c96"; 86 + version = "e796d536e3d83de74267069e179dc620a608ed7d"; 59 87 src = fetchFromGitHub { 60 88 owner = "nix-community"; 61 89 repo = "nixos-facter-modules"; 62 - rev = "fa695bff9ec37fd5bbd7ee3181dbeb5f97f53c96"; 90 + rev = "e796d536e3d83de74267069e179dc620a608ed7d"; 63 91 fetchSubmodules = false; 64 - sha256 = "sha256-iaRf6n0KPl9hndnIft3blm1YTAyxSREV1oX0MFZ6Tk4="; 92 + sha256 = "sha256-Ud9v49ZPsoDBFuyJSQ2Mpw1ZgAH/aMwUwwzrVoetNus="; 65 93 }; 66 - date = "2025-11-04"; 94 + date = "2025-12-24"; 67 95 }; 68 96 gomod2nix = { 69 97 pname = "gomod2nix"; ··· 79 107 }; 80 108 home = { 81 109 pname = "home"; 82 - version = "9651819d75f6c7ffaf8a9227490ac704f29659f0"; 110 + version = "4067ca1ffb6425b8597eafb63a84b171e0192d2b"; 83 111 src = fetchFromGitHub { 84 112 owner = "nix-community"; 85 113 repo = "home-manager"; 86 - rev = "9651819d75f6c7ffaf8a9227490ac704f29659f0"; 114 + rev = "4067ca1ffb6425b8597eafb63a84b171e0192d2b"; 87 115 fetchSubmodules = false; 88 - sha256 = "sha256-iUM9ktarEzThkayyZrzQ7oycPshAY2XRQqVKz0xX/L0="; 116 + sha256 = "sha256-Ok0jocJ82JriaMDtYEytR8oWcxADlX5WcWXULrN4czA="; 89 117 }; 90 - date = "2025-11-26"; 118 + date = "2025-12-27"; 91 119 }; 92 120 limbusart = { 93 121 pname = "limbusart"; 94 122 version = "7f29ab57b73eb8a4db7163fc7d19a71cf89c3d8b"; 95 123 src = fetchgit { 96 - url = "https://git.gaze.systems/90008/limbusart.git"; 124 + url = "https://github.com/90-008/limbusart.git"; 97 125 rev = "7f29ab57b73eb8a4db7163fc7d19a71cf89c3d8b"; 98 126 fetchSubmodules = false; 99 127 deepClone = false; ··· 105 133 }; 106 134 moonlight = { 107 135 pname = "moonlight"; 108 - version = "059476af87f7335c05424b805833864d6d9ed0e3"; 136 + version = "d0ad754cf0b9c5a34d7f69595f407c8199f988ce"; 109 137 src = fetchFromGitHub { 110 138 owner = "moonlight-mod"; 111 139 repo = "moonlight"; 112 - rev = "059476af87f7335c05424b805833864d6d9ed0e3"; 140 + rev = "d0ad754cf0b9c5a34d7f69595f407c8199f988ce"; 113 141 fetchSubmodules = false; 114 - sha256 = "sha256-Qur5AWl4Vx+It65DX+I+sc4lViz52OmXqvg+fL2t9I4="; 142 + sha256 = "sha256-qc4m7v8hGOMb9BVLuiQZAbgzHoKfVwEY7HUl9fsY/hE="; 115 143 }; 116 - date = "2025-11-26"; 144 + date = "2025-12-16"; 117 145 }; 118 146 ncr = { 119 147 pname = "ncr"; ··· 131 159 }; 132 160 nixos-hardware = { 133 161 pname = "nixos-hardware"; 134 - version = "da17006633ca9cda369be82893ae36824a2ddf1a"; 162 + version = "c5db9569ac9cc70929c268ac461f4003e3e5ca80"; 135 163 src = fetchFromGitHub { 136 164 owner = "NixOS"; 137 165 repo = "nixos-hardware"; 138 - rev = "da17006633ca9cda369be82893ae36824a2ddf1a"; 166 + rev = "c5db9569ac9cc70929c268ac461f4003e3e5ca80"; 139 167 fetchSubmodules = false; 140 - sha256 = "sha256-b1MtLQsQc4Ji1u08f+C6g5XrmLPkJQ1fhNkCt+0AERQ="; 168 + sha256 = "sha256-UXVtN77D7pzKmzOotFTStgZBqpOcf8cO95FcupWp4Zo="; 141 169 }; 142 - date = "2025-11-25"; 170 + date = "2025-12-24"; 143 171 }; 144 172 nixpkgs-xr = { 145 173 pname = "nixpkgs-xr"; 146 - version = "cd67b4986ffb7c4b136b6d4286c94375c74867bc"; 174 + version = "9e8efcd2c4ea906772dea99204a9819284a29b81"; 147 175 src = fetchFromGitHub { 148 176 owner = "nix-community"; 149 177 repo = "nixpkgs-xr"; 150 - rev = "cd67b4986ffb7c4b136b6d4286c94375c74867bc"; 178 + rev = "9e8efcd2c4ea906772dea99204a9819284a29b81"; 151 179 fetchSubmodules = false; 152 - sha256 = "sha256-D8d1g9aaZlTc/xZjbeaHJUwmJDAOqjqZNucMrq6wCKc="; 180 + sha256 = "sha256-biwvZsCGC4vCXS6rzs3tUkELqqEXPko0E3R9IhYKavE="; 153 181 }; 154 - date = "2025-11-27"; 182 + date = "2025-12-24"; 155 183 }; 156 184 nsid-tracker = { 157 185 pname = "nsid-tracker"; ··· 169 197 }; 170 198 nucleus = { 171 199 pname = "nucleus"; 172 - version = "a4f73517c1a76ed20b55f21618148b8afe0fa838"; 200 + version = "2ad7bd0b2710896cdf31638c32ceacc02a226726"; 173 201 src = fetchgit { 174 202 url = "https://tangled.org/@ptr.pet/nucleus"; 175 - rev = "a4f73517c1a76ed20b55f21618148b8afe0fa838"; 203 + rev = "2ad7bd0b2710896cdf31638c32ceacc02a226726"; 176 204 fetchSubmodules = false; 177 205 deepClone = false; 178 206 leaveDotGit = false; 179 207 sparseCheckout = [ ]; 180 - sha256 = "sha256-8WrGAr+aCIFCFuixtH1BSB5lMn+d/FqXsEFAmXY3HkU="; 208 + sha256 = "sha256-AXZhPcOvCCwFhntqLoZZtyaNTV6RQeS7I74RFzmFeiM="; 181 209 }; 182 - date = "2025-11-11"; 210 + date = "2025-12-27"; 183 211 }; 184 212 stylix = { 185 213 pname = "stylix"; 186 - version = "70c444a10d0c9ef71a25580dfa79af9cd43f3a5e"; 214 + version = "551df12ee3ebac52c5712058bd97fd9faa4c3430"; 187 215 src = fetchFromGitHub { 188 216 owner = "nix-community"; 189 217 repo = "stylix"; 190 - rev = "70c444a10d0c9ef71a25580dfa79af9cd43f3a5e"; 218 + rev = "551df12ee3ebac52c5712058bd97fd9faa4c3430"; 191 219 fetchSubmodules = false; 192 - sha256 = "sha256-rofXPD/9TGpHveo1MTlUfpnF0MCG1/uHUB9f0rosdqc="; 220 + sha256 = "sha256-J2DDdRqSU4w9NNgkMfmMeaLIof5PXtS9RG7y6ckDvQE="; 193 221 }; 194 - date = "2025-11-26"; 222 + date = "2025-12-24"; 195 223 }; 196 224 tangled = { 197 225 pname = "tangled"; 198 - version = "7358ec6edfa4d17b8b8f543d99e83a4705901148"; 226 + version = "716a5bc0dafb96bbf72fb6e07d20e251f97c9f4e"; 199 227 src = fetchgit { 200 - url = "https://tangled.org/@tangled.org/core"; 201 - rev = "7358ec6edfa4d17b8b8f543d99e83a4705901148"; 228 + url = "https://tangled.org/ptr.pet/core"; 229 + rev = "716a5bc0dafb96bbf72fb6e07d20e251f97c9f4e"; 202 230 fetchSubmodules = false; 203 231 deepClone = false; 204 232 leaveDotGit = false; 205 233 sparseCheckout = [ ]; 206 - sha256 = "sha256-PzuWiW/nMxwQTX0i1bHwGazQF4ptLNI9OGwpmhDb9i0="; 234 + sha256 = "sha256-SGG97w/bvffP6zuJwbnFHK6tdfuWEzKNOfjGbh2PIj0="; 207 235 }; 208 - date = "2025-11-24"; 236 + date = "2025-12-20"; 209 237 }; 210 238 tangled-sqlite-lib = { 211 239 pname = "tangled-sqlite-lib"; ··· 217 245 }; 218 246 trill = { 219 247 pname = "trill"; 220 - version = "c9604685156e009cebd0ddc3b31672455f635387"; 248 + version = "d395ba493b4735f82db9ce99c7e7e8b671b38225"; 221 249 src = fetchgit { 222 250 url = "https://tangled.org/@ptr.pet/trill"; 223 - rev = "c9604685156e009cebd0ddc3b31672455f635387"; 251 + rev = "d395ba493b4735f82db9ce99c7e7e8b671b38225"; 224 252 fetchSubmodules = false; 225 253 deepClone = false; 226 254 leaveDotGit = false; 227 255 sparseCheckout = [ ]; 228 - sha256 = "sha256-so9EHN0GQ7rFSmnLnpRap2RqRcklhe3C1HdyAKeR6No="; 256 + sha256 = "sha256-mxV02sfP7H2lv/xD9MkVHfp6F8dnYQly7rhTRpMEeiw="; 229 257 }; 230 - date = "2025-11-25"; 258 + date = "2025-12-25"; 231 259 }; 232 260 zen-browser = { 233 261 pname = "zen-browser"; 234 - version = "6f5d615393a5e923ea2883ef28e274031d1b1e1e"; 262 + version = "98d8f48ba80a4b6e3b56addad850d57132301075"; 235 263 src = fetchFromGitHub { 236 264 owner = "0xc000022070"; 237 265 repo = "zen-browser-flake"; 238 - rev = "6f5d615393a5e923ea2883ef28e274031d1b1e1e"; 266 + rev = "98d8f48ba80a4b6e3b56addad850d57132301075"; 239 267 fetchSubmodules = false; 240 - sha256 = "sha256-AEpt8JdKA4RVobRjaR7S2QP3bmUz8dhuWasB7mr9Ylo="; 268 + sha256 = "sha256-mGZBEN67mxeOsBhplBRLm6L+y++8jU46EEUYgemG1aQ="; 241 269 }; 242 - date = "2025-11-26"; 270 + date = "2025-12-25"; 243 271 }; 244 272 }
+90 -67
dns/dnsconfig.js
··· 1 1 var DSP_CLOUDFLARE = NewDnsProvider("cloudflare"); 2 + var DSP_PRIMARY = NewDnsProvider("hedns"); 2 3 var REG_NONE = NewRegistrar("none"); 3 4 4 - var WOLUMONDE_IP = "23.88.101.188"; 5 - var DZWONEK_IP = "94.237.26.47"; 5 + var DZWONEK_IP4 = "94.237.26.47"; 6 + var DZWONEK_IP6 = "2a04:3542:1000:910:6898:1dff:fea1:4b4b"; 7 + var DZWONEK_IPS = [DZWONEK_IP4, DZWONEK_IP6]; 8 + var TRIMOUNTS_IP4 = "159.195.58.28"; 9 + var TRIMOUNTS_IP6 = "2a0a:4cc0:c1:e83d::b00b"; 10 + var TRIMOUNTS_IPS = [TRIMOUNTS_IP4, TRIMOUNTS_IP6]; 11 + 12 + function host(name, ips, opts) { 13 + if (opts) 14 + return [ 15 + A(name, ips[0], opts), 16 + AAAA(name, ips[1], opts), 17 + ]; 18 + else 19 + return [ 20 + A(name, ips[0]), 21 + AAAA(name, ips[1]), 22 + ]; 23 + } 24 + 25 + function hosts(_names, ips, opts) { 26 + var names = []; 27 + if (typeof _names === "string") 28 + names.push(_names); 29 + else 30 + names = _names; 31 + 32 + var records = []; 33 + _.each(names, function (name) { 34 + _.each(host(name, ips, opts), function (r) { 35 + records.push(r); 36 + }); 37 + }); 38 + return records; 39 + } 40 + 41 + function TRIMOUNTS(names, opts) { 42 + return hosts(names, TRIMOUNTS_IPS, opts); 43 + } 44 + function DZWONEK(names, opts) { 45 + return hosts(names, DZWONEK_IPS, opts); 46 + } 47 + 48 + function IGNORE_ACME() { 49 + return IGNORE_NAME("_acme-challenge"); 50 + } 6 51 7 52 D( 8 53 "gaze.systems", 9 54 REG_NONE, 10 - DnsProvider(DSP_CLOUDFLARE), 11 - DefaultTTL(1), 12 - A("@", WOLUMONDE_IP, CF_PROXY_OFF), 13 - A("doc", WOLUMONDE_IP, CF_PROXY_OFF), 14 - A("git", WOLUMONDE_IP, CF_PROXY_OFF), 15 - A("limbus", WOLUMONDE_IP, CF_PROXY_OFF), 16 - A("pmart", WOLUMONDE_IP, CF_PROXY_OFF), 17 - // A("webhook", WOLUMONDE_IP, CF_PROXY_OFF), 18 - A("dash", WOLUMONDE_IP, CF_PROXY_OFF), // perses 19 - A("knot", WOLUMONDE_IP, CF_PROXY_OFF), 20 - A("spindle", WOLUMONDE_IP, CF_PROXY_OFF), 21 - A("skeetdeck", WOLUMONDE_IP, CF_PROXY_OFF), 22 - A("likes", WOLUMONDE_IP, CF_PROXY_OFF), 23 - A("id", WOLUMONDE_IP, CF_PROXY_OFF), 24 - A("test", WOLUMONDE_IP, CF_PROXY_OFF), 25 - // atp handles 26 - A("dawn", WOLUMONDE_IP, CF_PROXY_OFF), 27 - A("guestbook", WOLUMONDE_IP, CF_PROXY_OFF), 28 - A("drew", WOLUMONDE_IP, CF_PROXY_OFF), 29 - A("eris", WOLUMONDE_IP, CF_PROXY_OFF), 30 - // dzwonek 31 - A("vpn", DZWONEK_IP, CF_PROXY_OFF), 32 - // A("meow", WOLUMONDE_IP, CF_PROXY_OFF), 33 - // thing 34 - // TXT("id", "a data endpoint for entity with serial id /90008/."), 35 - // TXT("id", "entity linked here uses it/they pronouns. it can be referred to as /dusk/ or /dawn/."), 36 - // TXT("id", "this one is not a human, try to refer to it in third person. use /this one/, /this thing/, etc."), 37 - // TXT("id", "try connecting to https://gaze.systems/about for more information."), 55 + DnsProvider(DSP_PRIMARY), 56 + TRIMOUNTS( 57 + [ 58 + "@", "doc", "pmart", "dash", "id", 59 + "knot", "spindle", 60 + "guestbook", 61 + ], 62 + CF_PROXY_OFF, 63 + ), 64 + DZWONEK("vpn", CF_PROXY_OFF), 38 65 // github pages 39 66 CNAME("dev", "90-008.github.io."), 40 67 // fastmail ··· 44 71 MX("@", 10, "in1-smtp.messagingengine.com."), 45 72 MX("@", 20, "in2-smtp.messagingengine.com."), 46 73 TXT("@", "v=spf1 include:spf.messagingengine.com ?all"), 47 - TXT("_dmarc", "v=DMARC1; p=none;"), 74 + TXT("_dmarc", "v=DMARC1; p=reject;"), 48 75 // resend 49 76 MX("send.poke", 10, "feedback-smtp.us-east-1.amazonses.com."), 50 77 TXT( ··· 54 81 TXT("send.poke", "v=spf1 include:amazonses.com ~all"), 55 82 // atproto 56 83 TXT("_atproto.eris", "did=did:plc:bxjnsrfzozl365rsdo5yvuz5", TTL(60)), 57 - // TXT("_atproto", "did=did:plc:dfl62fgb7wtjj3fcbb72naae", TTL(60)), 58 - // TXT("_atproto.dusk", "did=did:plc:dfl62fgb7wtjj3fcbb72naae", TTL(60)), 84 + TXT("_atproto.drew", "did=did:plc:vo6ie3kd6xvpjlof4pnb2zzp", TTL(60)), 85 + IGNORE_ACME(), 59 86 ); 60 87 61 88 D( 62 89 "9.0.0.0.8.e.f.1.5.0.7.4.0.1.0.0.2.ip6.arpa", 63 90 REG_NONE, 64 91 DnsProvider(DSP_CLOUDFLARE), 65 - DefaultTTL(1), 66 - A("@", WOLUMONDE_IP, CF_PROXY_ON), 92 + TRIMOUNTS("@", CF_PROXY_ON), 67 93 TXT("@", "a data endpoint for entity with serial id /90008/."), 68 94 TXT( 69 95 "@", 70 - "entity linked here uses it/they pronouns. it can be referred to as /dusk/ or /dawn/.", 96 + "entity linked here uses it/that pronouns. it can also be referred to as /dawn/.", 71 97 ), 72 98 TXT( 73 99 "@", ··· 77 103 "@", 78 104 "try connecting to https://gaze.systems/about for more information.", 79 105 ), 80 - // atproto 81 - // TXT("_atproto", "did=did:plc:dfl62fgb7wtjj3fcbb72naae"), 106 + IGNORE_ACME(), 82 107 ); 83 108 84 109 D( 85 110 "poor.dog", 86 111 REG_NONE, 87 - DnsProvider(DSP_CLOUDFLARE), 88 - DefaultTTL(1), 89 - A("@", WOLUMONDE_IP, CF_PROXY_OFF), 112 + DnsProvider(DSP_PRIMARY), 113 + TRIMOUNTS("@", CF_PROXY_OFF), 90 114 TXT("@", "v=spf1 -all"), 91 115 TXT("_dmarc", "v=DMARC1; p=reject;"), 116 + TXT("_atproto", "did=did:plc:dfl62fgb7wtjj3fcbb72naae", TTL(60)), 117 + IGNORE_ACME(), 92 118 ); 93 119 94 - var EMAIL_TTL = 86400; 120 + var EMAIL_TTL = function () { return TTL(86400); }; 95 121 96 122 D( 97 123 "ptr.pet", 98 124 REG_NONE, 99 - DnsProvider(DSP_CLOUDFLARE), 100 - DefaultTTL(1), 101 - A("@", WOLUMONDE_IP, CF_PROXY_OFF), 102 - A("test", WOLUMONDE_IP, CF_PROXY_OFF), 103 - A("nucleus", DZWONEK_IP, CF_PROXY_OFF), 104 - A("trill", DZWONEK_IP, CF_PROXY_OFF), 125 + DnsProvider(DSP_PRIMARY), 126 + TRIMOUNTS(["@", "tunes"], CF_PROXY_OFF), 127 + DZWONEK(["nucleus", "trill", "dysnomia"], CF_PROXY_OFF), 105 128 // atproto 106 129 TXT("_atproto", "did=did:plc:dfl62fgb7wtjj3fcbb72naae"), 107 - A("nil", WOLUMONDE_IP, CF_PROXY_OFF), 108 130 TXT("_atproto.nil", "did=did:plc:dumbmutt4po52ept2tczimje"), 109 131 TXT("_atproto.june", "did=did:plc:y3z2rr7q5rywu4fjn3fmfyop"), 110 132 // june ··· 112 134 CNAME("*.june", "girlboss.ceo."), 113 135 // email 114 136 // verification 115 - TXT("@", "hosted-email-verify=zr04ylon", TTL(EMAIL_TTL)), 137 + TXT("@", "hosted-email-verify=zr04ylon", EMAIL_TTL()), 116 138 117 - MX("@", 10, "aspmx1.migadu.com.", TTL(EMAIL_TTL)), 118 - MX("@", 20, "aspmx2.migadu.com.", TTL(EMAIL_TTL)), 139 + MX("@", 10, "aspmx1.migadu.com.", EMAIL_TTL()), 140 + MX("@", 20, "aspmx2.migadu.com.", EMAIL_TTL()), 119 141 120 142 // DKIM 121 143 CNAME( 122 144 "key1._domainkey", 123 145 "key1.ptr.pet._domainkey.migadu.com.", 124 - TTL(EMAIL_TTL), 146 + EMAIL_TTL(), 125 147 ), 126 148 CNAME( 127 149 "key2._domainkey", 128 150 "key2.ptr.pet._domainkey.migadu.com.", 129 - TTL(EMAIL_TTL), 151 + EMAIL_TTL(), 130 152 ), 131 153 CNAME( 132 154 "key3._domainkey", 133 155 "key3.ptr.pet._domainkey.migadu.com.", 134 - TTL(EMAIL_TTL), 156 + EMAIL_TTL(), 135 157 ), 136 158 137 159 // SPF 138 - TXT("@", "v=spf1 include:spf.migadu.com -all", TTL(EMAIL_TTL)), 160 + TXT("@", "v=spf1 include:spf.migadu.com -all", EMAIL_TTL()), 139 161 140 162 // DMARC 141 163 TXT( 142 164 "_dmarc", 143 165 "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; fo=1; pct=100; rua=mailto:infrastructure@ptr.pet; ruf=mailto:infrastructure@ptr.pet", 144 - TTL(EMAIL_TTL), 166 + EMAIL_TTL(), 145 167 ), 146 168 147 169 // configuration 148 170 TXT( 149 171 "@", 150 172 "mailconf=https://autoconfig.migadu.com/mail/config-v1.1.xml", 151 - TTL(EMAIL_TTL), 173 + EMAIL_TTL(), 152 174 ), 153 175 154 176 // TLS reporting 155 177 TXT( 156 178 "_smtp._tls", 157 179 "v=TLSRPTv1; rua=mailto:infrastructure@ptr.pet", 158 - TTL(EMAIL_TTL), 180 + EMAIL_TTL(), 159 181 ), 160 182 161 183 // mta-sts 162 - A("mta-sts", WOLUMONDE_IP, CF_PROXY_OFF), 163 - TXT("_mta-sts", "v=STSv1; id=20250930T1945", TTL(EMAIL_TTL)), 184 + TRIMOUNTS("mta-sts", CF_PROXY_OFF), 185 + TXT("_mta-sts", "v=STSv1; id=20250930T1945", EMAIL_TTL()), 164 186 165 187 // autoconfig 166 - A("autoconfig", WOLUMONDE_IP, CF_PROXY_OFF), 167 - A("autodiscover", WOLUMONDE_IP, CF_PROXY_OFF), 188 + TRIMOUNTS(["autoconfig", "autodiscover"], CF_PROXY_OFF), 168 189 169 190 // autodiscovery 170 191 SRV( ··· 173 194 1, 174 195 443, 175 196 "autodiscover.migadu.com.", 176 - TTL(EMAIL_TTL), 197 + EMAIL_TTL(), 177 198 ), 178 - SRV("_submissions._tcp", 0, 1, 465, "smtp.migadu.com.", TTL(EMAIL_TTL)), 179 - SRV("_imaps._tcp", 0, 1, 993, "imap.migadu.com.", TTL(EMAIL_TTL)), 180 - SRV("_pop3s._tcp", 0, 1, 995, "pop.migadu.com.", TTL(EMAIL_TTL)), 199 + SRV("_submissions._tcp", 0, 1, 465, "smtp.migadu.com.", EMAIL_TTL()), 200 + SRV("_imaps._tcp", 0, 1, 993, "imap.migadu.com.", EMAIL_TTL()), 201 + SRV("_pop3s._tcp", 0, 1, 995, "pop.migadu.com.", EMAIL_TTL()), 202 + 203 + IGNORE_ACME(), 181 204 );
+22 -25
flake.lock
··· 9 9 "rust-overlay": "rust-overlay" 10 10 }, 11 11 "locked": { 12 - "lastModified": 1764153295, 13 - "narHash": "sha256-Y+Cp19zLo5JZVLSbzpyCTSK1bVYfE3Leuut6nQVkdR4=", 12 + "lastModified": 1765204341, 13 + "narHash": "sha256-7xd45skcuLCu2DHxVvU+W/z+7CUOjyv+QPtT4PLZaIU=", 14 14 "owner": "chaotic-cx", 15 15 "repo": "nyx", 16 - "rev": "29c49282c9b2e8216004a87086494defe401fee8", 16 + "rev": "aacb796ccd42be1555196c20013b9b674b71df75", 17 17 "type": "github" 18 18 }, 19 19 "original": { ··· 45 45 ] 46 46 }, 47 47 "locked": { 48 - "lastModified": 1764075860, 49 - "narHash": "sha256-KYEIHCBBw+/lwKsJNRNoUxBB4ZY2LK0G0T8f+0i65q0=", 48 + "lastModified": 1764998300, 49 + "narHash": "sha256-fZatn/KLfHLDXnF0wy7JxXqGaZmGDTVufT4o/AOlj44=", 50 50 "owner": "nix-community", 51 51 "repo": "home-manager", 52 - "rev": "295d90e22d557ccc3049dc92460b82f372cd3892", 52 + "rev": "27a6182347ccae90a88231ae0dc5dfa7d15815bb", 53 53 "type": "github" 54 54 }, 55 55 "original": { ··· 67 67 ] 68 68 }, 69 69 "locked": { 70 - "lastModified": 1763714684, 71 - "narHash": "sha256-ZNJPAaeSYQTDgvwwE8XHhCz4HiHqYoUyoXdoBE2nxug=", 70 + "lastModified": 1764922999, 71 + "narHash": "sha256-LSvUxKm6S6ZAd/otQSkAHd3+8KJhi8OwGJGSe0K//B8=", 72 72 "owner": "Jovian-Experiments", 73 73 "repo": "Jovian-NixOS", 74 - "rev": "6178d787ee61b8586fdb0ccb8644fbfd5317d0f3", 74 + "rev": "9b9ead1b5591b68f4048e7205ba1397bc85ce6c4", 75 75 "type": "github" 76 76 }, 77 77 "original": { ··· 105 105 }, 106 106 "nixpkgs": { 107 107 "locked": { 108 - "lastModified": 1763966396, 109 - "narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=", 108 + "lastModified": 1764950072, 109 + "narHash": "sha256-BmPWzogsG2GsXZtlT+MTcAWeDK5hkbGRZTeZNW42fwA=", 110 110 "owner": "NixOS", 111 111 "repo": "nixpkgs", 112 - "rev": "5ae3b07d8d6527c42f17c876e404993199144b6a", 112 + "rev": "f61125a668a320878494449750330ca58b78c557", 113 113 "type": "github" 114 114 }, 115 115 "original": { ··· 121 121 }, 122 122 "nixpkgs_2": { 123 123 "locked": { 124 - "lastModified": 1763966396, 125 - "narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=", 126 - "owner": "NixOS", 127 - "repo": "nixpkgs", 128 - "rev": "5ae3b07d8d6527c42f17c876e404993199144b6a", 129 - "type": "github" 124 + "lastModified": 1766651565, 125 + "narHash": "sha256-gtanTxYMENOVHWdS4QgxxKGPaSqvcNJVw0KBfaF5/Bo=", 126 + "rev": "3e2499d5539c16d0d173ba53552a4ff8547f4539", 127 + "type": "tarball", 128 + "url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre916364.3e2499d5539c/nixexprs.tar.xz?lastModified=1766651565&rev=3e2499d5539c16d0d173ba53552a4ff8547f4539" 130 129 }, 131 130 "original": { 132 - "owner": "NixOS", 133 - "ref": "nixos-unstable", 134 - "repo": "nixpkgs", 135 - "type": "github" 131 + "type": "tarball", 132 + "url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz" 136 133 } 137 134 }, 138 135 "root": { ··· 149 146 ] 150 147 }, 151 148 "locked": { 152 - "lastModified": 1764038373, 153 - "narHash": "sha256-M6w2wNBRelcavoDAyFL2iO4NeWknD40ASkH1S3C0YGM=", 149 + "lastModified": 1765075567, 150 + "narHash": "sha256-KFDCdQcHJ0hE3Nt5Gm5enRIhmtEifAjpxgUQ3mzSJpA=", 154 151 "owner": "oxalica", 155 152 "repo": "rust-overlay", 156 - "rev": "ab3536fe850211a96673c6ffb2cb88aab8071cc9", 153 + "rev": "769156779b41e8787a46ca3d7d76443aaf68be6f", 157 154 "type": "github" 158 155 }, 159 156 "original": {
+1 -1
flake.nix
··· 1 1 { 2 2 description = "config!!!"; 3 3 4 - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 4 + inputs.nixpkgs.url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"; 5 5 inputs.chaotic.url = "github:chaotic-cx/nyx/nyxpkgs-unstable"; 6 6 7 7 outputs =
+1 -3
hosts/chernobog/default.nix
··· 49 49 noto-fonts 50 50 noto-fonts-cjk-serif 51 51 noto-fonts-cjk-sans 52 - noto-fonts-emoji 52 + noto-fonts-color-emoji 53 53 font-awesome 54 54 source-han-serif 55 55 source-han-sans 56 - source-han-sans-japanese 57 - source-han-serif-japanese 58 56 comic-mono 59 57 comic-relief 60 58 ];
+22 -2
hosts/chernobog/modules/vr.nix
··· 25 25 }; 26 26 }; 27 27 28 - # programs.envision.enable = true; 28 + environment.systemPackages = with pkgs; [ wlx-overlay-s eepyxr wayvr-dashboard xrizer ]; 29 29 30 - environment.systemPackages = with pkgs; [ wlx-overlay-s eepyxr wayvr-dashboard ]; 30 + home-manager.sharedModules = [{ 31 + xdg.configFile."openvr/openvrpaths.vrpath".text = '' 32 + { 33 + "config" : 34 + [ 35 + "/home/mayer/.local/share/Steam/config" 36 + ], 37 + "external_drivers" : null, 38 + "jsonid" : "vrpathreg", 39 + "log" : 40 + [ 41 + "/home/mayer/.local/share/Steam/logs" 42 + ], 43 + "runtime" : 44 + [ 45 + "${pkgs.xrizer}/lib/xrizer" 46 + ], 47 + "version" : 1 48 + } 49 + ''; 50 + }]; 31 51 }
+1 -1
hosts/default.nix
··· 29 29 systems = { 30 30 # lungmen = "x86_64-linux"; 31 31 # tkaronto = "x86_64-linux"; 32 - wolumonde = allPkgsSets.x86_64-linux; 32 + # wolumonde = allPkgsSets.x86_64-linux; 33 33 # wsl = allPkgsSets.x86_64-linux; 34 34 dzwonek = allPkgsSets.x86_64-linux; 35 35 volsinii = allPkgsSets.x86_64-linux;
+22
hosts/dzwonek/modules/dysnomia.nix
··· 1 + {terra, ...}: 2 + let 3 + rootDomain = "vpn.gaze.systems"; 4 + domain = "dysnomia.ptr.pet"; 5 + in 6 + { 7 + security.acme.certs.${rootDomain}.extraDomainNames = [domain]; 8 + services.nginx.virtualHosts.${domain} = { 9 + useACMEHost = rootDomain; 10 + forceSSL = true; 11 + quic = true; 12 + kTLS = true; 13 + locations."/" = { 14 + root = terra.dysnomia; 15 + tryFiles = "$uri $uri/ /index.html"; 16 + extraConfig = '' 17 + add_header Cross-Origin-Embedder-Policy "require-corp"; 18 + add_header Cross-Origin-Opener-Policy "same-origin"; 19 + ''; 20 + }; 21 + }; 22 + }
+2 -2
hosts/dzwonek/modules/headscale.nix/default.nix
··· 25 25 }; 26 26 hosts = { 27 27 chernobog = "100.64.0.8"; 28 - wolumonde = "100.64.0.2"; 29 28 higashi = "100.64.0.5"; 29 + trimounts = "100.64.0.7"; 30 30 }; 31 31 rules = lib.mkBefore [ 32 32 { ··· 45 45 dst = [ "tag:private-infra:*" ]; 46 46 } 47 47 { 48 - src = [ "wolumonde" ]; 48 + src = [ "trimounts" ]; 49 49 dst = [ "chernobog:*" ]; 50 50 } 51 51 {
-3
hosts/dzwonek/modules/nginx.nix
··· 1 1 { 2 - lib, 3 2 inputs, 4 - pkgs, 5 3 ... 6 4 }: 7 5 { 8 6 services.nginx = { 9 7 enable = true; 10 - package = pkgs.nginxQuic; 11 8 recommendedTlsSettings = true; 12 9 recommendedOptimisation = true; 13 10 recommendedGzipSettings = true;
-2
hosts/trimounts/default.nix
··· 28 28 pkgs.gitMinimal 29 29 ]; 30 30 31 - networking.firewall.enable = true; 32 - 33 31 system.stateVersion = "25.11"; 34 32 }
+1 -1
hosts/trimounts/disk-config.nix
··· 33 33 extraArgs = [ "-f" ]; # Override existing partition 34 34 mountpoint = "/"; 35 35 mountOptions = [ 36 - "compress=zstd" 36 + "compress-force=zstd:3" 37 37 "noatime" 38 38 ]; 39 39 };
+28
hosts/trimounts/modules/arpa.nix
··· 1 + { pkgs, ... }: 2 + let 3 + index = pkgs.writeText "index.txt" '' 4 + hi there~ 5 + 6 + you are currently interfacing with one of the data endpoints 7 + of entity with serial id /90008/. you may want to open a 8 + connection to https://gaze.systems/about for more data. 9 + 10 + /discord 90.008/ 11 + /bsky @ptr.pet/ 12 + /email 90008@gaze.systems/ 13 + 14 + /dig +short TXT 9.0.0.0.8.e.f.1.5.0.7.4.0.1.0.0.2.ip6.arpa/ 15 + ''; 16 + root = pkgs.runCommand "root" { } '' 17 + mkdir -p $out 18 + ln -s ${index} $out/index.txt 19 + ''; 20 + in 21 + { 22 + services.nginx.virtualHosts."9.0.0.0.8.e.f.1.5.0.7.4.0.1.0.0.2.ip6.arpa" = { 23 + inherit root; 24 + locations."/".index = "index.txt"; 25 + quic = true; 26 + kTLS = true; 27 + }; 28 + }
+38
hosts/trimounts/modules/atproto.nix
··· 1 + { pkgs, lib, ... }: 2 + let 3 + getFileType = name: if lib.hasSuffix ".json" name then "application/json" else "text/plain"; 4 + mkWellKnownCfg = files: { 5 + quic = true; 6 + kTLS = true; 7 + locations = ( 8 + lib.mapAttrs' (name: file: { 9 + name = "=/.well-known/${name}"; 10 + value = { 11 + extraConfig = '' 12 + alias ${file}; 13 + add_header access-control-allow-origin *; 14 + default_type ${getFileType name}; 15 + ''; 16 + }; 17 + }) files 18 + ); 19 + }; 20 + mkDidWebCfg = domain: { 21 + "${domain}" = 22 + (mkWellKnownCfg { 23 + "did.json" = ../../../secrets/${domain}.did; 24 + "atproto-did" = pkgs.writeText "server" "did:web:${domain}"; 25 + }) 26 + // (lib.optionalAttrs (lib.hasSuffix "gaze.systems" domain) { 27 + useACMEHost = "gaze.systems"; 28 + forceSSL = true; 29 + quic = true; 30 + kTLS = true; 31 + }); 32 + }; 33 + guestbookDid = "guestbook.gaze.systems"; 34 + in 35 + { 36 + security.acme.certs."gaze.systems".extraDomainNames = [guestbookDid]; 37 + services.nginx.virtualHosts = mkDidWebCfg guestbookDid; 38 + }
+32
hosts/trimounts/modules/clickee-proxy.nix
··· 1 + { config, terra, ... }: 2 + let 3 + port = 7145; 4 + in 5 + { 6 + age.secrets.clickeeProxyConfig = { 7 + file = ../../../secrets/clickeeProxyConfig.age; 8 + }; 9 + 10 + systemd.services.clickee-proxy = { 11 + description = "clickee-proxy"; 12 + wantedBy = [ "multi-user.target" ]; 13 + after = [ "network.target" ]; 14 + environment = { 15 + PORT = toString port; 16 + }; 17 + serviceConfig = { 18 + DynamicUser = true; 19 + ExecStart = "${terra.clickee-proxy}/bin/clickee-proxy"; 20 + Restart = "on-failure"; 21 + RestartSec = 5; 22 + EnvironmentFile = config.age.secrets.clickeeProxyConfig.path; 23 + }; 24 + }; 25 + 26 + services.nginx.virtualHosts."poor.dog" = { 27 + locations."/click".proxyPass = "http://localhost:${toString port}"; 28 + }; 29 + services.nginx.virtualHosts."ptr.pet" = { 30 + locations."/click".proxyPass = "http://localhost:${toString port}"; 31 + }; 32 + }
+58
hosts/trimounts/modules/email.nix
··· 1 + { pkgs, ... }: 2 + { 3 + security.acme.certs."ptr.pet".extraDomainNames = [ 4 + "mta-sts.ptr.pet" 5 + "autoconfig.ptr.pet" 6 + "autodiscover.ptr.pet" 7 + ]; 8 + services.nginx.virtualHosts."ptr.pet" = { 9 + useACMEHost = "ptr.pet"; 10 + quic = true; 11 + kTLS = true; 12 + forceSSL = true; 13 + locations."/mail/config-v1.1.xml" = { 14 + return = "301 https://autoconfig.migadu.com/mail/config-v1.1.xml"; 15 + }; 16 + locations."/Autodiscover/Autodiscover.xml" = { 17 + return = "301 https://autodiscover.migadu.com/Autodiscover/Autodiscover.xml"; 18 + }; 19 + }; 20 + services.nginx.virtualHosts."mta-sts.ptr.pet" = 21 + let 22 + file = pkgs.writeText "mta-sts.txt" '' 23 + version: STSv1 24 + mode: enforce 25 + mx: aspmx1.migadu.com 26 + mx: aspmx2.migadu.com 27 + max_age: 31557600 28 + ''; 29 + in 30 + { 31 + useACMEHost = "ptr.pet"; 32 + quic = true; 33 + kTLS = true; 34 + forceSSL = true; 35 + locations."=/.well-known/mta-sts.txt".extraConfig = '' 36 + alias ${file}; 37 + default_type text/plain; 38 + ''; 39 + }; 40 + services.nginx.virtualHosts."autoconfig.ptr.pet" = { 41 + useACMEHost = "ptr.pet"; 42 + quic = true; 43 + kTLS = true; 44 + forceSSL = true; 45 + locations."/" = { 46 + return = "301 https://autoconfig.migadu.com$request_uri"; 47 + }; 48 + }; 49 + services.nginx.virtualHosts."autodiscover.ptr.pet" = { 50 + useACMEHost = "ptr.pet"; 51 + quic = true; 52 + kTLS = true; 53 + forceSSL = true; 54 + locations."/" = { 55 + return = "301 https://autodiscover.migadu.com$request_uri"; 56 + }; 57 + }; 58 + }
+33
hosts/trimounts/modules/fluentbit.nix
··· 1 + { 2 + pkgs, 3 + config, 4 + lib, 5 + ... 6 + }: 7 + { 8 + services.fluent-bit = { 9 + enable = true; 10 + settings = { 11 + service.flush = 1; 12 + pipeline.inputs = [ 13 + { 14 + name = "node_exporter_metrics"; 15 + tag = "metrics.node"; 16 + scrape_interval = 5; 17 + } 18 + # { 19 + # name = "dummy"; 20 + # tag = "logs.dummy"; 21 + # dummy = ''{"_msg": "dummy"}''; 22 + # } 23 + { 24 + name = "fluentbit_metrics"; 25 + tag = "metrics.fluentbit"; 26 + scrape_interval = 5; 27 + } 28 + ]; 29 + }; 30 + }; 31 + 32 + systemd.services.fluent-bit.serviceConfig.StateDirectory = "fluent-bit"; 33 + }
+28
hosts/trimounts/modules/hedgedoc.nix
··· 1 + { config, ... }: 2 + let 3 + cfg = config.services.hedgedoc.settings; 4 + in 5 + { 6 + services.hedgedoc = { 7 + enable = true; 8 + settings = { 9 + port = 3333; 10 + domain = "doc.gaze.systems"; 11 + protocolUseSSL = true; 12 + allowEmailRegister = false; 13 + allowAnonymous = false; 14 + allowAnonymousEdits = true; 15 + allowFreeURL = true; 16 + requireFreeURLAuthentication = true; 17 + }; 18 + }; 19 + 20 + security.acme.certs."gaze.systems".extraDomainNames = [ cfg.domain ]; 21 + services.nginx.virtualHosts.${cfg.domain} = { 22 + useACMEHost = "gaze.systems"; 23 + forceSSL = true; 24 + quic = true; 25 + kTLS = true; 26 + locations."/".proxyPass = "http://${cfg.host}:${toString cfg.port}"; 27 + }; 28 + }
+47
hosts/trimounts/modules/limbusart.nix
··· 1 + { 2 + inputs, 3 + pkgs, 4 + lib, 5 + ... 6 + }: 7 + let 8 + pkg = pkgs.callPackage "${inputs.limbusart}/package.nix" { }; 9 + domain = "pmart.gaze.systems"; 10 + in 11 + { 12 + systemd.services.limbusart = { 13 + description = "limbusart"; 14 + wantedBy = [ "multi-user.target" ]; 15 + after = [ "network.target" ]; 16 + serviceConfig = lib.mkMerge [ 17 + { 18 + User = "limbusart"; 19 + ExecStart = "${pkg}/bin/limbusart"; 20 + Restart = "on-failure"; 21 + RestartSec = 5; 22 + WorkingDirectory = "/var/lib/limbusart"; 23 + EnvironmentFile = pkgs.writeText "limbusart.conf" '' 24 + ARTS_PATH="arts.txt" 25 + SITE_TITLE="random pm art" 26 + EMBED_TITLE="random pm art here!!" 27 + EMBED_DESC="click NOW to see random pm art" 28 + EMBED_COLOR="#bd0000" 29 + ''; 30 + } 31 + ]; 32 + }; 33 + users.users.limbusart = { 34 + isSystemUser = true; 35 + group = "limbusart"; 36 + }; 37 + users.groups.limbusart = { }; 38 + 39 + security.acme.certs."gaze.systems".extraDomainNames = [domain]; 40 + services.nginx.virtualHosts.${domain} = { 41 + useACMEHost = "gaze.systems"; 42 + forceSSL = true; 43 + quic = true; 44 + kTLS = true; 45 + locations."/".proxyPass = "http://localhost:3000"; 46 + }; 47 + }
+3
hosts/trimounts/modules/mosh.nix
··· 1 + { 2 + programs.mosh.enable = true; 3 + }
+31
hosts/trimounts/modules/navidrome.nix
··· 1 + {config, ...}: 2 + let 3 + domain = "tunes.ptr.pet"; 4 + in { 5 + services.navidrome = { 6 + enable = true; 7 + openFirewall = false; 8 + settings = { 9 + MusicFolder = "/music"; 10 + Port = 9999; 11 + Address = "0.0.0.0"; 12 + ListenBrainz = { 13 + Enabled = true; 14 + BaseURL = "https://piper.kittysay.xyz/1"; 15 + }; 16 + EnableSharing = true; 17 + }; 18 + }; 19 + 20 + security.acme.certs."ptr.pet".extraDomainNames = [domain]; 21 + services.nginx.virtualHosts.${domain} = { 22 + quic = true; 23 + kTLS = true; 24 + useACMEHost = "ptr.pet"; 25 + forceSSL = true; 26 + locations."/" = { 27 + proxyPass = with config.services.navidrome.settings; "http://${Address}:${toString Port}"; 28 + proxyWebsockets = true; 29 + }; 30 + }; 31 + }
+15
hosts/trimounts/modules/networking.nix
··· 1 + { 2 + networking.enableIPv6 = true; 3 + networking.interfaces.ens3 = { 4 + ipv6.addresses = [{ 5 + address = "2a0a:4cc0:c1:e83d::b00b"; 6 + prefixLength = 64; 7 + }]; 8 + }; 9 + networking.defaultGateway6 = { 10 + address = "fe80::1"; 11 + interface = "ens3"; 12 + }; 13 + 14 + networking.firewall.enable = true; 15 + }
+131
hosts/trimounts/modules/nginx.nix
··· 1 + { 2 + config, 3 + lib, 4 + inputs, 5 + ... 6 + }: 7 + { 8 + services.nginx = { 9 + enable = true; 10 + recommendedTlsSettings = true; 11 + recommendedOptimisation = true; 12 + recommendedGzipSettings = true; 13 + recommendedProxySettings = true; 14 + # /nginx_status 15 + statusPage = true; 16 + }; 17 + 18 + networking.firewall.allowedTCPPorts = [ 80 443 ]; 19 + 20 + # output json logs so we can consume them more easily 21 + services.nginx.appendHttpConfig = '' 22 + log_format json_logs escape=json '{' 23 + '"_msg":"request completed",' 24 + '"time":"$time_local",' 25 + '"req.remoteAddr":"$remote_addr",' 26 + '"req.method":"$request_method",' 27 + '"req.url":"$uri",' 28 + '"req.httpVersion":"$server_protocol",' 29 + '"res.statusCode":$status,' 30 + '"res.bodySize":$body_bytes_sent,' 31 + '"req.headers.id":"$request_id",' 32 + '"req.headers.referer":"$http_referer",' 33 + '"req.headers.user-agent":"$http_user_agent",' 34 + '"requestTime":$request_time' 35 + '}'; 36 + access_log /var/log/nginx/access.log json_logs; 37 + ''; 38 + 39 + users.users.nginx.extraGroups = [ "acme" ]; 40 + 41 + age.secrets.bunnyApiKey.file = ../../../secrets/bunnyApiKey.age; 42 + security.acme = { 43 + acceptTerms = true; 44 + defaults = { 45 + group = "nginx"; 46 + email = (import "${inputs.self}/personal.nix").emails.primary; 47 + webroot = "/var/lib/acme/acme-challenge"; 48 + }; 49 + certs."poor.dog" = { }; 50 + certs."ptr.pet" = { }; 51 + certs."gaze.systems" = { }; 52 + }; 53 + services.nginx.virtualHosts."gaze.systems" = { 54 + quic = true; 55 + kTLS = true; 56 + useACMEHost = "gaze.systems"; 57 + forceSSL = true; 58 + }; 59 + services.nginx.virtualHosts."poor.dog" = { 60 + quic = true; 61 + kTLS = true; 62 + useACMEHost = "poor.dog"; 63 + forceSSL = true; 64 + }; 65 + services.nginx.virtualHosts."ptr.pet" = { 66 + quic = true; 67 + kTLS = true; 68 + useACMEHost = "ptr.pet"; 69 + forceSSL = true; 70 + }; 71 + 72 + services.fluent-bit.settings = { 73 + parsers = [ 74 + { 75 + name = "nginx_json"; 76 + format = "json"; 77 + time_key = "time"; 78 + time_format = "%d/%b/%Y:%H:%M:%S %z"; 79 + } 80 + ]; 81 + pipeline = { 82 + inputs = [ 83 + { 84 + name = "nginx_metrics"; 85 + tag = "metrics.nginx"; 86 + status_url = "/nginx_status"; 87 + nginx_plus = false; 88 + } 89 + { 90 + name = "tail"; 91 + tag = "logs.nginx"; 92 + path = "/var/log/nginx/*.log"; 93 + db = "/var/lib/fluent-bit/nginx-access.db"; 94 + "db.locking" = true; 95 + buffer_chunk_size = "4m"; 96 + buffer_max_size = "32m"; 97 + parser = "nginx_json"; 98 + } 99 + ]; 100 + filters = [ 101 + { 102 + name = "modify"; 103 + match = "logs.nginx"; 104 + Add = [ "name nginx" ]; 105 + } 106 + ]; 107 + }; 108 + }; 109 + 110 + # need so fluent-bit can access nginx 111 + systemd.services.fluent-bit.serviceConfig.SupplementaryGroups = lib.mkForce "systemd-journal nginx"; 112 + 113 + services.vmalert.instances."".rules.groups = [ 114 + { 115 + name = "nginx-logs"; 116 + type = "vlogs"; 117 + interval = "1m"; 118 + rules = [ 119 + { 120 + record = "nginx_request_count"; 121 + expr = "name:nginx | stats (res.statusCode) count() as total_requests"; 122 + } 123 + { 124 + record = "nginx_request_latency"; 125 + # filter out subscribeRepos requests because they are long polling http L 126 + expr = "name:nginx | filter req.url:!/xrpc/com.atproto.sync.subscribeRepos | stats avg(requestTime) avg, quantile(0.5, requestTime) p50, quantile(0.9, requestTime) p90, quantile(0.99, requestTime) p99"; 127 + } 128 + ]; 129 + } 130 + ]; 131 + }
+65
hosts/trimounts/modules/nsid-tracker.disabled
··· 1 + { 2 + pkgs, 3 + terra, 4 + inputs, 5 + ... 6 + }: 7 + let 8 + client-modules = pkgs.callPackage "${inputs.nsid-tracker}/nix/client-modules.nix" { }; 9 + client = pkgs.callPackage "${inputs.nsid-tracker}/nix/client.nix" { 10 + PUBLIC_API_URL = "gaze.systems/nsid-tracker/api"; 11 + inherit client-modules; 12 + }; 13 + # server = terra.nsid-tracker-server; 14 + port = 3713; 15 + in 16 + { 17 + systemd.services.nsid-tracker-client = { 18 + description = "nsid-tracker-client"; 19 + wantedBy = [ "multi-user.target" ]; 20 + after = [ "network.target" ]; 21 + environment = { 22 + # ORIGIN = "https://gaze.systems"; 23 + PORT = toString port; 24 + }; 25 + serviceConfig = { 26 + DynamicUser = true; 27 + ExecStart = "${client}/bin/website"; 28 + Restart = "on-failure"; 29 + RestartSec = 5; 30 + WorkingDirectory = "/var/lib/nsid-tracker"; 31 + }; 32 + }; 33 + 34 + systemd.services.nsid-tracker-keep-alive = { 35 + description = "keeps nsid-tracker peer connection alive"; 36 + wantedBy = [ "multi-user.target" ]; 37 + after = [ "network.target" ]; 38 + serviceConfig = { 39 + Type = "oneshot"; 40 + ExecStart = "${pkgs.curl}/bin/curl http://dusk-devel-mobi:${toString port}/events"; 41 + }; 42 + }; 43 + systemd.timers.nsid-tracker-keep-alive.timerConfig = { 44 + OnBootSec = "5 min"; 45 + OnUnitActiveSec = "5 min"; 46 + Unit = "nsid-tracker-keep-alive.service"; 47 + }; 48 + 49 + services.nginx.virtualHosts."gaze.systems" = { 50 + locations."/nsid-tracker/api" = { 51 + proxyPass = "http://100.64.0.6:${toString port}/"; 52 + proxyWebsockets = true; 53 + extraConfig = '' 54 + rewrite ^/nsid-tracker/api/(.*) /$1 break; 55 + ''; 56 + }; 57 + locations."/nsid-tracker".return = "301 /nsid-tracker/"; 58 + locations."/nsid-tracker/" = { 59 + proxyPass = "http://localhost:${toString port}/"; 60 + extraConfig = '' 61 + rewrite ^/nsid-tracker/(.*)$ /$1 break; 62 + ''; 63 + }; 64 + }; 65 + }
+121
hosts/trimounts/modules/pds.nix
··· 1 + { lib, config, ... }: 2 + let 3 + pdsLocalhost = "http://localhost:${toString config.services.bluesky-pds.settings.PDS_PORT}"; 4 + in 5 + { 6 + age.secrets.pdsConfig.file = ../../../secrets/pdsConfig.age; 7 + 8 + services.nginx.virtualHosts.${config.services.bluesky-pds.settings.PDS_HOSTNAME} = { 9 + useACMEHost = "gaze.systems"; 10 + forceSSL = true; 11 + locations = { 12 + # we need to proxy /xrpc for pds to work 13 + # silly but i want root domain >:3 14 + "/xrpc" = { 15 + proxyPass = pdsLocalhost; 16 + proxyWebsockets = true; 17 + # pass ws headers so we can actually proxy the ws 18 + extraConfig = '' 19 + proxy_set_header id $request_id; 20 + client_max_body_size 100M; 21 + ''; 22 + # higher prio just to make sure 23 + priority = 100; 24 + }; 25 + "/xrpc/app.bsky.unspecced.getAgeAssuranceState".extraConfig = '' 26 + default_type application/json; 27 + add_header access-control-allow-headers "authorization,dpop,atproto-accept-labelers,atproto-proxy" always; 28 + add_header access-control-allow-origin "*" always; 29 + return 200 '{"lastInitiatedAt":"2025-07-14T14:22:43.912Z","status":"assured"}'; 30 + ''; 31 + } 32 + # others 33 + // (lib.genAttrs 34 + [ 35 + "/account" 36 + "/@atproto" 37 + "/oauth" 38 + "=/.well-known/oauth-protected-resource" 39 + "=/.well-known/oauth-authorization-server" 40 + ] 41 + (_: { 42 + proxyPass = pdsLocalhost; 43 + # higher prio just to make sure 44 + priority = 100; 45 + }) 46 + ); 47 + }; 48 + # setup pds stuff 49 + services.bluesky-pds = { 50 + enable = true; 51 + settings = { 52 + PDS_HOSTNAME = "gaze.systems"; 53 + PDS_PORT = 1334; 54 + 55 + PDS_SERVICE_NAME = ''"gazing at the sky"''; 56 + PDS_LOGO_URL = "https://gaze.systems/icons/gaze_site.webp"; 57 + 58 + PDS_RATE_LIMITS_ENABLED = "true"; 59 + PDS_INVITE_REQUIRED = "true"; 60 + 61 + PDS_DID_PLC_URL = "https://plc.directory"; 62 + PDS_BSKY_APP_VIEW_URL = "https://api.bsky.app"; 63 + PDS_BSKY_APP_VIEW_DID = "did:web:api.bsky.app"; 64 + PDS_REPORT_SERVICE_URL = "https://mod.bsky.app"; 65 + PDS_REPORT_SERVICE_DID = "did:plc:ar7c4by46qjdydhdevvrndac"; 66 + PDS_CRAWLERS = "https://bsky.network"; 67 + }; 68 + environmentFiles = [ config.age.secrets.pdsConfig.path ]; 69 + }; 70 + 71 + services.fluent-bit.settings = { 72 + parsers = [ 73 + { 74 + name = "pds_json"; 75 + format = "json"; 76 + time_key = "time"; 77 + time_strict = false; 78 + } 79 + ]; 80 + pipeline = { 81 + inputs = [ 82 + { 83 + name = "systemd"; 84 + tag = "logs.pds"; 85 + systemd_filter = "_SYSTEMD_UNIT=bluesky-pds.service"; 86 + } 87 + ]; 88 + filters = [ 89 + { 90 + name = "parser"; 91 + match = "logs.pds"; 92 + key_name = "MESSAGE"; 93 + parser = "pds_json"; 94 + } 95 + { 96 + name = "modify"; 97 + match = "logs.pds"; 98 + Rename = [ "msg _msg" ]; 99 + } 100 + ]; 101 + }; 102 + }; 103 + 104 + services.vmalert.instances."".rules.groups = [ 105 + { 106 + name = "pds-logs"; 107 + type = "vlogs"; 108 + interval = "1m"; 109 + rules = [ 110 + { 111 + record = "pds_request_count"; 112 + expr = "name:pds | stats (res.statusCode) count() as total_requests"; 113 + } 114 + { 115 + record = "pds_response_latency"; 116 + expr = "name:pds | stats avg(responseTime) avg, quantile(0.5, responseTime) p50, quantile(0.9, responseTime) p90, quantile(0.99, responseTime) p99"; 117 + } 118 + ]; 119 + } 120 + ]; 121 + }
+2
hosts/trimounts/modules/perses.nix/dashboards/.gitignore
··· 1 + # folder used to store the results of the `percli dac build` command 2 + built
+28
hosts/trimounts/modules/perses.nix/dashboards/go.mod
··· 1 + module dash 2 + 3 + go 1.24.2 4 + 5 + require ( 6 + github.com/beorn7/perks v1.0.1 // indirect 7 + github.com/cespare/xxhash/v2 v2.3.0 // indirect 8 + github.com/go-jose/go-jose/v4 v4.0.5 // indirect 9 + github.com/jpillora/backoff v1.0.0 // indirect 10 + github.com/muhlemmer/gu v0.3.1 // indirect 11 + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 12 + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect 13 + github.com/perses/perses v0.50.3 // indirect 14 + github.com/prometheus/client_golang v1.20.5 // indirect 15 + github.com/prometheus/client_model v0.6.1 // indirect 16 + github.com/prometheus/common v0.63.0 // indirect 17 + github.com/prometheus/procfs v0.15.1 // indirect 18 + github.com/zitadel/oidc/v3 v3.36.1 // indirect 19 + github.com/zitadel/schema v1.3.0 // indirect 20 + golang.org/x/crypto v0.36.0 // indirect 21 + golang.org/x/net v0.35.0 // indirect 22 + golang.org/x/oauth2 v0.28.0 // indirect 23 + golang.org/x/sys v0.31.0 // indirect 24 + golang.org/x/text v0.23.0 // indirect 25 + google.golang.org/protobuf v1.36.5 // indirect 26 + gopkg.in/yaml.v2 v2.4.0 // indirect 27 + gopkg.in/yaml.v3 v3.0.1 // indirect 28 + )
+45
hosts/trimounts/modules/perses.nix/dashboards/go.sum
··· 1 + github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 2 + github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 3 + github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 4 + github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 5 + github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= 6 + github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= 7 + github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= 8 + github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= 9 + github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM= 10 + github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM= 11 + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 12 + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 13 + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= 14 + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 15 + github.com/perses/perses v0.50.3 h1:BHlU9qkCFCUSP4HP5p9GwophWcxm5Vnu6Fsrx8Fb/+w= 16 + github.com/perses/perses v0.50.3/go.mod h1:oqfHLOrXERvEqECShqXPjHXqVukQxcoaaTM6ySRF7hU= 17 + github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= 18 + github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= 19 + github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= 20 + github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= 21 + github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= 22 + github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= 23 + github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= 24 + github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= 25 + github.com/zitadel/oidc/v3 v3.36.1 h1:1AT1NqKKEqAwx4GmKJZ9fYkWH2WIn/VKMfQ46nBtRf0= 26 + github.com/zitadel/oidc/v3 v3.36.1/go.mod h1:dApGZLvWZTHRuxmcbQlW5d2XVjVYR3vGOdq536igmTs= 27 + github.com/zitadel/schema v1.3.0 h1:kQ9W9tvIwZICCKWcMvCEweXET1OcOyGEuFbHs4o5kg0= 28 + github.com/zitadel/schema v1.3.0/go.mod h1:NptN6mkBDFvERUCvZHlvWmmME+gmZ44xzwRXwhzsbtc= 29 + golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= 30 + golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= 31 + golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= 32 + golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= 33 + golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= 34 + golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= 35 + golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= 36 + golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 37 + golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= 38 + golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= 39 + google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= 40 + google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 41 + gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 42 + gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 43 + gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 44 + gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 45 + gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+334
hosts/trimounts/modules/perses.nix/dashboards/wolumonde.go
··· 1 + package main 2 + 3 + import ( 4 + "flag" 5 + "time" 6 + 7 + "github.com/perses/perses/go-sdk" 8 + "github.com/perses/perses/go-sdk/common" 9 + dash "github.com/perses/perses/go-sdk/dashboard" 10 + "github.com/perses/perses/go-sdk/panel" 11 + panels "github.com/perses/perses/go-sdk/panel-group" 12 + "github.com/perses/perses/go-sdk/panel/bar" 13 + "github.com/perses/perses/go-sdk/panel/gauge" 14 + "github.com/perses/perses/go-sdk/panel/stat" 15 + "github.com/perses/perses/go-sdk/prometheus/query" 16 + 17 + timeSeries "github.com/perses/perses/go-sdk/panel/time-series" 18 + // promDs "github.com/perses/perses/go-sdk/prometheus/datasource" 19 + ) 20 + 21 + func main() { 22 + flag.Parse() 23 + exec := sdk.NewExec() 24 + 25 + var loadPanel = panels.AddPanel("load over 5 min", 26 + timeSeries.Chart( 27 + timeSeries.WithYAxis( 28 + timeSeries.YAxis{ 29 + Max: 2.0, 30 + }, 31 + ), 32 + ), 33 + panel.AddQuery( 34 + query.PromQL( 35 + "node_load5", 36 + query.SeriesNameFormat("load"), 37 + ), 38 + ), 39 + ) 40 + var cpuPanel = panels.AddPanel("cpu usage", 41 + timeSeries.Chart( 42 + timeSeries.WithYAxis( 43 + timeSeries.YAxis{ 44 + Format: &common.Format{ 45 + Unit: "percent", 46 + }, 47 + Max: 100.0, 48 + }, 49 + ), 50 + ), 51 + panel.AddQuery( 52 + query.PromQL( 53 + `sum by (cpu) (rate(node_cpu_seconds_total{mode=~"user|system"}[1m])) * 100`, 54 + query.SeriesNameFormat("cpu {{cpu}}"), 55 + ), 56 + ), 57 + ) 58 + var memoryPanel = panels.AddPanel("memory usage", 59 + timeSeries.Chart( 60 + timeSeries.WithYAxis( 61 + timeSeries.YAxis{ 62 + Format: &common.Format{ 63 + Unit: "bytes", 64 + }, 65 + Max: 4000000000, 66 + }, 67 + ), 68 + ), 69 + panel.AddQuery( 70 + query.PromQL( 71 + "node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes", 72 + query.SeriesNameFormat("current memory usage"), 73 + ), 74 + ), 75 + ) 76 + 77 + var diskPanel = panels.AddPanel("disk usage /", 78 + timeSeries.Chart( 79 + timeSeries.WithYAxis( 80 + timeSeries.YAxis{ 81 + Format: &common.Format{ 82 + Unit: "bytes", 83 + }, 84 + Max: 38000000000, 85 + }, 86 + ), 87 + ), 88 + panel.AddQuery( 89 + query.PromQL( 90 + `node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}`, 91 + query.SeriesNameFormat("disk usage"), 92 + ), 93 + ), 94 + ) 95 + 96 + // Gauge versions (percent unit) 97 + var loadGaugePanel = panels.AddPanel("load over 5 min", 98 + gauge.Chart( 99 + gauge.Format(common.Format{Unit: "percent"}), 100 + gauge.Max(100), 101 + gauge.Calculation(common.MeanCalculation), 102 + ), 103 + panel.AddQuery( 104 + query.PromQL( 105 + "node_load5 * 100 / count(count(node_cpu_seconds_total) by (cpu))", 106 + query.SeriesNameFormat("load %"), 107 + ), 108 + ), 109 + ) 110 + var cpuGaugePanel = panels.AddPanel("cpu usage", 111 + gauge.Chart( 112 + gauge.Format(common.Format{Unit: "percent"}), 113 + gauge.Max(100), 114 + gauge.Calculation(common.MeanCalculation), 115 + ), 116 + panel.AddQuery( 117 + query.PromQL( 118 + `sum by (cpu) (rate(node_cpu_seconds_total{mode=~"user|system"}[1m])) * 100`, 119 + query.SeriesNameFormat("cpu {{cpu}}"), 120 + ), 121 + ), 122 + ) 123 + var memoryGaugePanel = panels.AddPanel("memory usage", 124 + gauge.Chart( 125 + gauge.Format(common.Format{Unit: "percent"}), 126 + gauge.Max(100), 127 + gauge.Calculation(common.MeanCalculation), 128 + ), 129 + panel.AddQuery( 130 + query.PromQL( 131 + "(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) * 100 / node_memory_MemTotal_bytes", 132 + query.SeriesNameFormat("memory usage %"), 133 + ), 134 + ), 135 + ) 136 + var diskGaugePanel = panels.AddPanel("disk usage /", 137 + gauge.Chart( 138 + gauge.Format(common.Format{Unit: "percent"}), 139 + gauge.Max(100), 140 + ), 141 + panel.AddQuery( 142 + query.PromQL( 143 + `(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}) * 100 / node_filesystem_size_bytes{mountpoint="/"}`, 144 + query.SeriesNameFormat("disk usage %"), 145 + ), 146 + ), 147 + ) 148 + 149 + var resPanels = dash.AddPanelGroup("resource usage", 150 + panels.PanelsPerLine(4), 151 + loadGaugePanel, cpuGaugePanel, memoryGaugePanel, diskGaugePanel, 152 + loadPanel, cpuPanel, memoryPanel, diskPanel, 153 + ) 154 + 155 + var nginxPanel = panels.AddPanel("nginx requests / min", 156 + timeSeries.Chart( 157 + timeSeries.WithYAxis( 158 + timeSeries.YAxis{ 159 + Format: &common.Format{ 160 + Unit: "decimal", 161 + }, 162 + }, 163 + ), 164 + timeSeries.WithVisual(timeSeries.Visual{ 165 + Display: timeSeries.BarDisplay, 166 + Palette: timeSeries.Palette{ 167 + Mode: timeSeries.CategoricalMode, 168 + }, 169 + Stack: timeSeries.AllStack, 170 + }), 171 + timeSeries.WithLegend(timeSeries.Legend{ 172 + Position: timeSeries.BottomPosition, 173 + Size: timeSeries.SmallSize, 174 + }), 175 + ), 176 + panel.AddQuery( 177 + query.PromQL( 178 + "nginx_request_count", 179 + query.SeriesNameFormat("{{res.statusCode}}"), 180 + ), 181 + ), 182 + ) 183 + 184 + var nginxLatencyPanel = panels.AddPanel("nginx latency / min", 185 + timeSeries.Chart( 186 + timeSeries.WithYAxis( 187 + timeSeries.YAxis{ 188 + Format: &common.Format{ 189 + Unit: "seconds", 190 + }, 191 + Max: 0.5, 192 + }, 193 + ), 194 + ), 195 + panel.AddQuery( 196 + query.PromQL( 197 + "nginx_request_latency", 198 + query.SeriesNameFormat("{{stats_result}}"), 199 + ), 200 + ), 201 + ) 202 + 203 + var nginxPanels = dash.AddPanelGroup("nginx metrics", 204 + panels.PanelsPerLine(3), 205 + nginxPanel, 206 + nginxLatencyPanel, 207 + ) 208 + 209 + var pdsPanel = panels.AddPanel("pds requests / min", 210 + timeSeries.Chart( 211 + timeSeries.WithYAxis( 212 + timeSeries.YAxis{ 213 + Format: &common.Format{ 214 + Unit: "decimal", 215 + }, 216 + }, 217 + ), 218 + timeSeries.WithVisual(timeSeries.Visual{ 219 + Display: timeSeries.BarDisplay, 220 + Palette: timeSeries.Palette{ 221 + Mode: timeSeries.CategoricalMode, 222 + }, 223 + Stack: timeSeries.AllStack, 224 + }), 225 + timeSeries.WithLegend(timeSeries.Legend{ 226 + Position: timeSeries.BottomPosition, 227 + Size: timeSeries.SmallSize, 228 + }), 229 + ), 230 + panel.AddQuery( 231 + query.PromQL( 232 + "pds_request_count", 233 + query.SeriesNameFormat("{{res.statusCode}}"), 234 + ), 235 + ), 236 + ) 237 + 238 + var pdsLatencyPanel = panels.AddPanel("pds latency / min", 239 + timeSeries.Chart( 240 + timeSeries.WithYAxis( 241 + timeSeries.YAxis{ 242 + Format: &common.Format{ 243 + Unit: "milliseconds", 244 + }, 245 + Max: 500, 246 + }, 247 + ), 248 + ), 249 + panel.AddQuery( 250 + query.PromQL( 251 + "pds_response_latency", 252 + query.SeriesNameFormat("{{stats_result}}"), 253 + ), 254 + ), 255 + ) 256 + 257 + var pdsPanels = dash.AddPanelGroup("pds metrics", 258 + panels.PanelsPerLine(3), 259 + pdsPanel, 260 + pdsLatencyPanel, 261 + ) 262 + 263 + var anubisForgejoPanel = panels.AddPanel("anubis policy actions", 264 + bar.Chart(), 265 + panel.AddQuery( 266 + query.PromQL( 267 + "anubis_policy_results", 268 + query.SeriesNameFormat("{{action}}: {{rule}}"), 269 + ), 270 + ), 271 + ) 272 + 273 + var forgejoPanels = dash.AddPanelGroup("forgejo", 274 + panels.PanelsPerLine(3), 275 + anubisForgejoPanel, 276 + ) 277 + 278 + var gazesys_visit_panel = panels.AddPanel("gazesys visits", 279 + bar.Chart(), 280 + panel.AddQuery( 281 + query.PromQL( 282 + "gazesys_visit_real_total + gazesys_visit_fake_total", 283 + query.SeriesNameFormat("total visits"), 284 + ), 285 + ), 286 + panel.AddQuery( 287 + query.PromQL( 288 + "gazesys_visit_fake_total", 289 + query.SeriesNameFormat("(ai) bot visits"), 290 + ), 291 + ), 292 + panel.AddQuery( 293 + query.PromQL( 294 + "gazesys_visit_real_total", 295 + query.SeriesNameFormat("real visits"), 296 + ), 297 + ), 298 + ) 299 + 300 + var gazesys_pet_panel = panels.AddPanel("gazesys pet", 301 + stat.Chart( 302 + stat.Format(common.Format{ 303 + Unit: "decimal", 304 + ShortValues: true, 305 + DecimalPlaces: 0, 306 + }), 307 + ), 308 + panel.AddQuery( 309 + query.PromQL( 310 + "gazesys_pet_bounce_total", 311 + query.SeriesNameFormat("bounce count"), 312 + ), 313 + ), 314 + panel.AddQuery( 315 + query.PromQL( 316 + "gazesys_pet_distance_total", 317 + query.SeriesNameFormat("distance travelled"), 318 + ), 319 + ), 320 + ) 321 + 322 + var gazesys_panels = dash.AddPanelGroup("gazesys", 323 + panels.PanelsPerLine(3), 324 + gazesys_visit_panel, gazesys_pet_panel, 325 + ) 326 + 327 + builder, buildErr := dash.New("wolumonde", 328 + dash.ProjectName("private-infra"), 329 + dash.Duration(30*time.Minute), 330 + dash.RefreshInterval(time.Minute), 331 + resPanels, nginxPanels, pdsPanels, gazesys_panels, forgejoPanels, 332 + ) 333 + exec.BuildDashboard(builder, buildErr) 334 + }
+104
hosts/trimounts/modules/perses.nix/default.nix
··· 1 + { 2 + pkgs, 3 + config, 4 + ... 5 + }: 6 + let 7 + domain = "dash.gaze.systems"; 8 + port = 7412; 9 + user = "perses"; 10 + 11 + provisionFolder = "provisioning"; 12 + provisioningFolder = "${config.users.users.${user}.home}/${provisionFolder}"; 13 + 14 + persesConfig = { 15 + database.file = { 16 + folder = config.users.users.${user}.home; 17 + extension = "json"; 18 + }; 19 + provisioning.folders = [ provisioningFolder ]; 20 + security = { 21 + enable_auth = true; 22 + authentication = { 23 + providers = { 24 + enable_native = false; 25 + oidc = [ 26 + { 27 + slug_id = "pocketid"; 28 + name = "Pocket ID"; 29 + client_id = "aa583db6-e03c-4490-853a-7f2b3e089fbe"; 30 + issuer = config.services.pocket-id.settings.APP_URL; 31 + scopes = [ "openid profile email" ]; 32 + } 33 + ]; 34 + }; 35 + disable_sign_up = false; 36 + }; 37 + cookie = { 38 + same_site = "strict"; 39 + secure = true; 40 + }; 41 + }; 42 + }; 43 + persesConfigYaml = pkgs.writers.writeYAML "config.yaml" persesConfig; 44 + 45 + secrets = config.age.secrets; 46 + in 47 + { 48 + environment.systemPackages = [ pkgs.perses ]; 49 + 50 + users.users.${user} = { 51 + isNormalUser = true; 52 + group = user; 53 + home = "/var/lib/${user}"; 54 + createHome = true; 55 + uid = 1001; 56 + }; 57 + users.groups.${user} = { 58 + gid = 976; 59 + }; 60 + 61 + age.secrets.persesSecret = { 62 + file = ../../../../secrets/persesSecret.age; 63 + owner = user; 64 + group = user; 65 + }; 66 + 67 + systemd.services.perses = { 68 + description = "perses"; 69 + after = [ 70 + "network.target" 71 + "pocket-id.service" 72 + ]; 73 + requires = [ "pocket-id.service" ]; 74 + serviceConfig = { 75 + ExecStart = "${pkgs.perses}/bin/perses --config=${persesConfigYaml} --web.listen-address=:${toString port} --log.level=info"; 76 + EnvironmentFile = secrets.persesSecret.path; 77 + WorkingDirectory = config.users.users.${user}.home; 78 + }; 79 + }; 80 + systemd.services.perses.preStart = '' 81 + rm -rf ${provisioningFolder} && mkdir -p ${provisioningFolder} 82 + cp -f ${./provision}/* ${provisioningFolder} 83 + ''; 84 + 85 + security.acme.certs."gaze.systems".extraDomainNames = [ domain ]; 86 + services.nginx.virtualHosts.${domain} = { 87 + useACMEHost = "gaze.systems"; # TODO: write a module to define vhosts for subdomains 88 + quic = true; 89 + kTLS = true; 90 + forceSSL = true; 91 + locations."/" = { 92 + proxyPass = "http://localhost:${toString port}"; 93 + }; 94 + }; 95 + 96 + # scrape perses metrics 97 + services.victoriametrics.prometheusConfig.scrape_configs = [ 98 + { 99 + job_name = "perses"; 100 + metrics_path = "/metrics"; 101 + static_configs = [ { targets = [ "localhost:${toString port}" ]; } ]; 102 + } 103 + ]; 104 + }
+3
hosts/trimounts/modules/perses.nix/provision/1-private-infra.yaml
··· 1 + kind: Project 2 + metadata: 3 + name: private-infra
+9
hosts/trimounts/modules/perses.nix/provision/2-admin-role.yaml
··· 1 + - kind: GlobalRole 2 + metadata: 3 + name: admin 4 + spec: 5 + permissions: 6 + - actions: 7 + - '*' 8 + scopes: 9 + - '*'
+8
hosts/trimounts/modules/perses.nix/provision/3-admin-bind-role.yaml
··· 1 + - kind: GlobalRoleBinding 2 + metadata: 3 + name: admin 4 + spec: 5 + role: admin 6 + subjects: 7 + - kind: User 8 + name: 90008
+12
hosts/trimounts/modules/perses.nix/provision/4-victoria.yaml
··· 1 + - kind: GlobalDatasource 2 + metadata: 3 + name: victoria 4 + spec: 5 + default: true 6 + plugin: 7 + kind: PrometheusDatasource 8 + spec: 9 + proxy: 10 + kind: HTTPProxy 11 + spec: 12 + url: http://localhost:8428
+12
hosts/trimounts/modules/perses.nix/provision/6-guest-role.yaml
··· 1 + - kind: GlobalRole 2 + metadata: 3 + name: guest 4 + spec: 5 + permissions: 6 + - actions: 7 + - 'read' 8 + scopes: 9 + - 'Dashboard' 10 + - 'Project' 11 + - 'Datasource' 12 + - 'GlobalDatasource'
+8
hosts/trimounts/modules/perses.nix/provision/7-guest-role-bind.yaml
··· 1 + - kind: GlobalRoleBinding 2 + metadata: 3 + name: guest 4 + spec: 5 + role: guest 6 + subjects: 7 + - kind: User 8 + name: sorryu02
+454
hosts/trimounts/modules/perses.nix/provision/90-wolumonde.yaml
··· 1 + kind: Dashboard 2 + metadata: 3 + name: wolumonde 4 + createdAt: 0001-01-01T00:00:00Z 5 + updatedAt: 0001-01-01T00:00:00Z 6 + version: 0 7 + project: private-infra 8 + spec: 9 + panels: 10 + "0_0": 11 + kind: Panel 12 + spec: 13 + display: 14 + name: load over 5 min 15 + plugin: 16 + kind: GaugeChart 17 + spec: 18 + calculation: mean 19 + format: 20 + unit: percent 21 + max: 100 22 + queries: 23 + - kind: TimeSeriesQuery 24 + spec: 25 + plugin: 26 + kind: PrometheusTimeSeriesQuery 27 + spec: 28 + query: node_load5 * 100 / count(count(node_cpu_seconds_total) by (cpu)) 29 + seriesNameFormat: load % 30 + "0_1": 31 + kind: Panel 32 + spec: 33 + display: 34 + name: cpu usage 35 + plugin: 36 + kind: GaugeChart 37 + spec: 38 + calculation: mean 39 + format: 40 + unit: percent 41 + max: 100 42 + queries: 43 + - kind: TimeSeriesQuery 44 + spec: 45 + plugin: 46 + kind: PrometheusTimeSeriesQuery 47 + spec: 48 + query: sum by (cpu) (rate(node_cpu_seconds_total{mode=~"user|system"}[1m])) * 100 49 + seriesNameFormat: cpu {{cpu}} 50 + "0_2": 51 + kind: Panel 52 + spec: 53 + display: 54 + name: memory usage 55 + plugin: 56 + kind: GaugeChart 57 + spec: 58 + calculation: mean 59 + format: 60 + unit: percent 61 + max: 100 62 + queries: 63 + - kind: TimeSeriesQuery 64 + spec: 65 + plugin: 66 + kind: PrometheusTimeSeriesQuery 67 + spec: 68 + query: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) * 100 / node_memory_MemTotal_bytes 69 + seriesNameFormat: memory usage % 70 + "0_3": 71 + kind: Panel 72 + spec: 73 + display: 74 + name: disk usage / 75 + plugin: 76 + kind: GaugeChart 77 + spec: 78 + calculation: last 79 + format: 80 + unit: percent 81 + max: 100 82 + queries: 83 + - kind: TimeSeriesQuery 84 + spec: 85 + plugin: 86 + kind: PrometheusTimeSeriesQuery 87 + spec: 88 + query: (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}) * 100 / node_filesystem_size_bytes{mountpoint="/"} 89 + seriesNameFormat: disk usage % 90 + "0_4": 91 + kind: Panel 92 + spec: 93 + display: 94 + name: load over 5 min 95 + plugin: 96 + kind: TimeSeriesChart 97 + spec: 98 + yAxis: 99 + max: 2 100 + queries: 101 + - kind: TimeSeriesQuery 102 + spec: 103 + plugin: 104 + kind: PrometheusTimeSeriesQuery 105 + spec: 106 + query: node_load5 107 + seriesNameFormat: load 108 + "0_5": 109 + kind: Panel 110 + spec: 111 + display: 112 + name: cpu usage 113 + plugin: 114 + kind: TimeSeriesChart 115 + spec: 116 + yAxis: 117 + format: 118 + unit: percent 119 + max: 100 120 + queries: 121 + - kind: TimeSeriesQuery 122 + spec: 123 + plugin: 124 + kind: PrometheusTimeSeriesQuery 125 + spec: 126 + query: sum by (cpu) (rate(node_cpu_seconds_total{mode=~"user|system"}[1m])) * 100 127 + seriesNameFormat: cpu {{cpu}} 128 + "0_6": 129 + kind: Panel 130 + spec: 131 + display: 132 + name: memory usage 133 + plugin: 134 + kind: TimeSeriesChart 135 + spec: 136 + yAxis: 137 + format: 138 + unit: bytes 139 + max: 4e+09 140 + queries: 141 + - kind: TimeSeriesQuery 142 + spec: 143 + plugin: 144 + kind: PrometheusTimeSeriesQuery 145 + spec: 146 + query: node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes 147 + seriesNameFormat: current memory usage 148 + "0_7": 149 + kind: Panel 150 + spec: 151 + display: 152 + name: disk usage / 153 + plugin: 154 + kind: TimeSeriesChart 155 + spec: 156 + yAxis: 157 + format: 158 + unit: bytes 159 + max: 3.8e+10 160 + queries: 161 + - kind: TimeSeriesQuery 162 + spec: 163 + plugin: 164 + kind: PrometheusTimeSeriesQuery 165 + spec: 166 + query: node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"} 167 + seriesNameFormat: disk usage 168 + "1_0": 169 + kind: Panel 170 + spec: 171 + display: 172 + name: nginx requests / min 173 + plugin: 174 + kind: TimeSeriesChart 175 + spec: 176 + legend: 177 + position: bottom 178 + size: small 179 + yAxis: 180 + format: 181 + unit: decimal 182 + visual: 183 + display: bar 184 + palette: 185 + mode: categorical 186 + stack: all 187 + queries: 188 + - kind: TimeSeriesQuery 189 + spec: 190 + plugin: 191 + kind: PrometheusTimeSeriesQuery 192 + spec: 193 + query: nginx_request_count 194 + seriesNameFormat: '{{res.statusCode}}' 195 + "1_1": 196 + kind: Panel 197 + spec: 198 + display: 199 + name: nginx latency / min 200 + plugin: 201 + kind: TimeSeriesChart 202 + spec: 203 + yAxis: 204 + format: 205 + unit: seconds 206 + max: 0.5 207 + queries: 208 + - kind: TimeSeriesQuery 209 + spec: 210 + plugin: 211 + kind: PrometheusTimeSeriesQuery 212 + spec: 213 + query: nginx_request_latency 214 + seriesNameFormat: '{{stats_result}}' 215 + "2_0": 216 + kind: Panel 217 + spec: 218 + display: 219 + name: pds requests / min 220 + plugin: 221 + kind: TimeSeriesChart 222 + spec: 223 + legend: 224 + position: bottom 225 + size: small 226 + yAxis: 227 + format: 228 + unit: decimal 229 + visual: 230 + display: bar 231 + palette: 232 + mode: categorical 233 + stack: all 234 + queries: 235 + - kind: TimeSeriesQuery 236 + spec: 237 + plugin: 238 + kind: PrometheusTimeSeriesQuery 239 + spec: 240 + query: pds_request_count 241 + seriesNameFormat: '{{res.statusCode}}' 242 + "2_1": 243 + kind: Panel 244 + spec: 245 + display: 246 + name: pds latency / min 247 + plugin: 248 + kind: TimeSeriesChart 249 + spec: 250 + yAxis: 251 + format: 252 + unit: milliseconds 253 + max: 500 254 + queries: 255 + - kind: TimeSeriesQuery 256 + spec: 257 + plugin: 258 + kind: PrometheusTimeSeriesQuery 259 + spec: 260 + query: pds_response_latency 261 + seriesNameFormat: '{{stats_result}}' 262 + "3_0": 263 + kind: Panel 264 + spec: 265 + display: 266 + name: gazesys visits 267 + plugin: 268 + kind: BarChart 269 + spec: 270 + calculation: last 271 + queries: 272 + - kind: TimeSeriesQuery 273 + spec: 274 + plugin: 275 + kind: PrometheusTimeSeriesQuery 276 + spec: 277 + query: gazesys_visit_real_total + gazesys_visit_fake_total 278 + seriesNameFormat: total visits 279 + - kind: TimeSeriesQuery 280 + spec: 281 + plugin: 282 + kind: PrometheusTimeSeriesQuery 283 + spec: 284 + query: gazesys_visit_fake_total 285 + seriesNameFormat: (ai) bot visits 286 + - kind: TimeSeriesQuery 287 + spec: 288 + plugin: 289 + kind: PrometheusTimeSeriesQuery 290 + spec: 291 + query: gazesys_visit_real_total 292 + seriesNameFormat: real visits 293 + "3_1": 294 + kind: Panel 295 + spec: 296 + display: 297 + name: gazesys pet 298 + plugin: 299 + kind: StatChart 300 + spec: 301 + calculation: last 302 + format: 303 + unit: decimal 304 + shortValues: true 305 + queries: 306 + - kind: TimeSeriesQuery 307 + spec: 308 + plugin: 309 + kind: PrometheusTimeSeriesQuery 310 + spec: 311 + query: gazesys_pet_bounce_total 312 + seriesNameFormat: bounce count 313 + - kind: TimeSeriesQuery 314 + spec: 315 + plugin: 316 + kind: PrometheusTimeSeriesQuery 317 + spec: 318 + query: gazesys_pet_distance_total 319 + seriesNameFormat: distance travelled 320 + "4_0": 321 + kind: Panel 322 + spec: 323 + display: 324 + name: anubis policy actions 325 + plugin: 326 + kind: BarChart 327 + spec: 328 + calculation: last 329 + queries: 330 + - kind: TimeSeriesQuery 331 + spec: 332 + plugin: 333 + kind: PrometheusTimeSeriesQuery 334 + spec: 335 + query: anubis_policy_results 336 + seriesNameFormat: '{{action}}: {{rule}}' 337 + layouts: 338 + - kind: Grid 339 + spec: 340 + display: 341 + title: resource usage 342 + items: 343 + - x: 0 344 + "y": 0 345 + width: 6 346 + height: 6 347 + content: 348 + $ref: '#/spec/panels/0_0' 349 + - x: 6 350 + "y": 0 351 + width: 6 352 + height: 6 353 + content: 354 + $ref: '#/spec/panels/0_1' 355 + - x: 12 356 + "y": 0 357 + width: 6 358 + height: 6 359 + content: 360 + $ref: '#/spec/panels/0_2' 361 + - x: 18 362 + "y": 0 363 + width: 6 364 + height: 6 365 + content: 366 + $ref: '#/spec/panels/0_3' 367 + - x: 0 368 + "y": 6 369 + width: 6 370 + height: 6 371 + content: 372 + $ref: '#/spec/panels/0_4' 373 + - x: 6 374 + "y": 6 375 + width: 6 376 + height: 6 377 + content: 378 + $ref: '#/spec/panels/0_5' 379 + - x: 12 380 + "y": 6 381 + width: 6 382 + height: 6 383 + content: 384 + $ref: '#/spec/panels/0_6' 385 + - x: 18 386 + "y": 6 387 + width: 6 388 + height: 6 389 + content: 390 + $ref: '#/spec/panels/0_7' 391 + - kind: Grid 392 + spec: 393 + display: 394 + title: nginx metrics 395 + items: 396 + - x: 0 397 + "y": 0 398 + width: 8 399 + height: 6 400 + content: 401 + $ref: '#/spec/panels/1_0' 402 + - x: 8 403 + "y": 0 404 + width: 8 405 + height: 6 406 + content: 407 + $ref: '#/spec/panels/1_1' 408 + - kind: Grid 409 + spec: 410 + display: 411 + title: pds metrics 412 + items: 413 + - x: 0 414 + "y": 0 415 + width: 8 416 + height: 6 417 + content: 418 + $ref: '#/spec/panels/2_0' 419 + - x: 8 420 + "y": 0 421 + width: 8 422 + height: 6 423 + content: 424 + $ref: '#/spec/panels/2_1' 425 + - kind: Grid 426 + spec: 427 + display: 428 + title: gazesys 429 + items: 430 + - x: 0 431 + "y": 0 432 + width: 8 433 + height: 6 434 + content: 435 + $ref: '#/spec/panels/3_0' 436 + - x: 8 437 + "y": 0 438 + width: 8 439 + height: 6 440 + content: 441 + $ref: '#/spec/panels/3_1' 442 + - kind: Grid 443 + spec: 444 + display: 445 + title: forgejo 446 + items: 447 + - x: 0 448 + "y": 0 449 + width: 8 450 + height: 6 451 + content: 452 + $ref: '#/spec/panels/4_0' 453 + duration: 30m 454 + refreshInterval: 1m
+30
hosts/trimounts/modules/pocket-id.nix
··· 1 + { config, ... }: 2 + let 3 + domain = "id.gaze.systems"; 4 + in 5 + { 6 + services.pocket-id = { 7 + enable = true; 8 + settings = { 9 + APP_URL = "https://${domain}"; 10 + TRUST_PROXY = true; 11 + PORT = 6823; 12 + ANALYTICS_DISABLED = true; 13 + }; 14 + }; 15 + 16 + security.acme.certs."gaze.systems".extraDomainNames = [ domain ]; 17 + 18 + services.nginx.virtualHosts.${domain} = { 19 + useACMEHost = "gaze.systems"; 20 + forceSSL = true; 21 + quic = true; 22 + kTLS = true; 23 + locations."/".proxyPass = "http://localhost:${toString config.services.pocket-id.settings.PORT}"; 24 + locations."/".extraConfig = '' 25 + proxy_busy_buffers_size 512k; 26 + proxy_buffers 4 512k; 27 + proxy_buffer_size 256k; 28 + ''; 29 + }; 30 + }
+6
hosts/trimounts/modules/tangled.nix/default.nix
··· 1 + { 2 + imports = [ 3 + ./knot.nix 4 + ./spindle.nix 5 + ]; 6 + }
+39
hosts/trimounts/modules/tangled.nix/knot.nix
··· 1 + { 2 + config, 3 + inputs, 4 + terra, 5 + ... 6 + }: 7 + let 8 + knotCfg = config.services.tangled.knot; 9 + in 10 + { 11 + imports = [ 12 + "${inputs.tangled}/nix/modules/knot.nix" 13 + ]; 14 + 15 + services.tangled.knot = { 16 + enable = true; 17 + package = terra.tangled-knot; 18 + gitUser = "git"; 19 + motdFile = ./motd; 20 + server = { 21 + listenAddr = "0.0.0.0:7777"; 22 + hostname = "knot.gaze.systems"; 23 + owner = "did:plc:dfl62fgb7wtjj3fcbb72naae"; 24 + }; 25 + }; 26 + 27 + security.acme.certs."gaze.systems".extraDomainNames = [ knotCfg.server.hostname ]; 28 + 29 + services.nginx.virtualHosts.${knotCfg.server.hostname} = { 30 + useACMEHost = "gaze.systems"; 31 + forceSSL = true; 32 + quic = true; 33 + kTLS = true; 34 + locations."/" = { 35 + proxyPass = "http://${knotCfg.server.listenAddr}"; 36 + proxyWebsockets = true; 37 + }; 38 + }; 39 + }
+5
hosts/trimounts/modules/tangled.nix/motd
··· 1 + 2 + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ 3 + ┃ *paws at your commits* arf :3c ┃ 4 + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ 5 +
+64
hosts/trimounts/modules/tangled.nix/spindle.nix
··· 1 + { 2 + lib, 3 + config, 4 + inputs, 5 + terra, 6 + ... 7 + }: 8 + let 9 + spindleCfg = config.services.tangled.spindle; 10 + in 11 + { 12 + imports = [ 13 + "${inputs.tangled}/nix/modules/spindle.nix" 14 + ]; 15 + 16 + services.tangled.spindle = { 17 + enable = true; 18 + package = terra.tangled-spindle; 19 + server = { 20 + listenAddr = "0.0.0.0:7391"; 21 + hostname = "spindle.gaze.systems"; 22 + owner = "did:plc:dfl62fgb7wtjj3fcbb72naae"; 23 + # secrets = { 24 + # provider = "openbao"; 25 + # openbao.proxyAddr = "http://spindle.bao.lan.gaze.systems"; 26 + # }; 27 + secrets.provider = "sqlite"; 28 + }; 29 + }; 30 + users.users.spindle = { 31 + group = "spindle"; 32 + isSystemUser = true; 33 + }; 34 + users.groups.spindle = { }; 35 + users.groups.podman.members = [ "spindle" ]; 36 + systemd.services.spindle = { 37 + # after = lib.mkForce [ "network.target" "openbao-proxy-spindle.service" ]; 38 + serviceConfig = { 39 + User = "spindle"; 40 + Group = "spindle"; 41 + }; 42 + }; 43 + 44 + security.acme.certs."gaze.systems".extraDomainNames = [ spindleCfg.server.hostname ]; 45 + 46 + services.nginx.virtualHosts.${spindleCfg.server.hostname} = { 47 + useACMEHost = "gaze.systems"; 48 + forceSSL = true; 49 + quic = true; 50 + kTLS = true; 51 + locations."/" = { 52 + proxyPass = "http://${spindleCfg.server.listenAddr}"; 53 + proxyWebsockets = true; 54 + }; 55 + }; 56 + 57 + virtualisation.docker.enable = lib.mkForce false; 58 + virtualisation.podman = { 59 + enable = true; 60 + autoPrune.enable = true; 61 + dockerCompat = true; 62 + dockerSocket.enable = true; 63 + }; 64 + }
+10
hosts/trimounts/modules/transmission.nix
··· 1 + { 2 + services.transmission = { 3 + enable = true; 4 + openPeerPorts = true; 5 + openRPCPort = false; # we use tailscale 6 + settings = { 7 + watch-dir-enabled = true; 8 + }; 9 + }; 10 + }
+70
hosts/trimounts/modules/victoria.nix
··· 1 + { lib, config, ... }: 2 + let 3 + # syslogUdp = 5113; 4 + metricsPort = 8428; 5 + logsPort = 9428; 6 + in 7 + { 8 + services.victoriametrics = { 9 + enable = true; 10 + listenAddress = ":${toString metricsPort}"; 11 + }; 12 + 13 + services.victorialogs = { 14 + enable = true; 15 + listenAddress = ":${toString logsPort}"; 16 + # extraOptions = ["-syslog.listenAddr.udp=:${toString syslogUdp}" "-journald.maxRequestSize=1024000000"]; 17 + }; 18 + 19 + services.vmalert.instances."" = { 20 + enable = true; 21 + settings = 22 + let 23 + l = "http://localhost"; 24 + in 25 + { 26 + "datasource.url" = "${l}${config.services.victorialogs.listenAddress}"; 27 + "remoteWrite.url" = "${l}${config.services.victoriametrics.listenAddress}"; 28 + "remoteRead.url" = "${l}${config.services.victoriametrics.listenAddress}"; 29 + "rule.defaultRuleType" = "vlogs"; 30 + }; 31 + }; 32 + 33 + services.fluent-bit.settings.pipeline.outputs = [ 34 + # write metrics to victoriametrics via prometheus 35 + { 36 + name = "prometheus_remote_write"; 37 + match = "metrics.*"; 38 + port = lib.removePrefix ":" config.services.victoriametrics.listenAddress; 39 + uri = "/api/v1/write"; 40 + } 41 + { 42 + name = "http"; 43 + match = "logs.*"; 44 + port = lib.removePrefix ":" config.services.victorialogs.listenAddress; 45 + uri = "/insert/jsonline?_stream_fields=stream&_msg_field=log&_time_field=date"; 46 + format = "json_lines"; 47 + json_date_format = "iso8601"; 48 + } 49 + # write logs via syslog 50 + # { 51 + # name = "syslog"; 52 + # match = "*.log"; 53 + # port = syslogUdp; 54 + # syslog_maxsize = 4096; 55 + # syslog_severity_key = "severity"; 56 + # syslog_facility_key = "facility"; 57 + # syslog_hostname_key = "hostname"; 58 + # syslog_appname_key = "appname"; 59 + # syslog_procid_key = "procid"; 60 + # syslog_msgid_key = "msgid"; 61 + # syslog_sd_key = "sd"; 62 + # syslog_message_key = "message"; 63 + # } 64 + ]; 65 + 66 + # services.journald.upload = { 67 + # enable = true; 68 + # settings.Upload.URL = "http://localhost${config.services.victorialogs.listenAddress}/insert/journald"; 69 + # }; 70 + }
+96
hosts/trimounts/modules/website.nix
··· 1 + { 2 + config, 3 + pkgs, 4 + inputs, 5 + ... 6 + }: 7 + let 8 + PUBLIC_BASE_URL = "https://gaze.systems"; 9 + modules = (pkgs.callPackage "${inputs.blog}/nix/modules.nix" { }).overrideAttrs (_: { 10 + # outputHash = "sha256-rzfSfiK8FSNFR+1QTwM/ltLZBprG9BoQsPmOt6IdXFc="; 11 + }); 12 + pkg = pkgs.callPackage "${inputs.blog}/nix" { 13 + inherit PUBLIC_BASE_URL; 14 + eunomia-modules = modules; 15 + }; 16 + port = 3003; 17 + vhostConfig = { 18 + locations."/".proxyPass = "http://localhost:${toString port}"; 19 + locations."/annoy/ws/" = { 20 + proxyWebsockets = true; 21 + proxyPass = "http://100.64.0.9:3111/"; 22 + extraConfig = '' 23 + rewrite ^/annoy/ws/(.*) /$1 break; 24 + ''; 25 + }; 26 + locations."/annoy/ws" = { 27 + proxyWebsockets = true; 28 + proxyPass = "http://100.64.0.9:3111/"; 29 + extraConfig = '' 30 + rewrite ^/annoy/ws(.*) /$1 break; 31 + ''; 32 + }; 33 + extraConfig = '' 34 + if ($http_user_agent ~* "Synapse") { 35 + return 403; 36 + } 37 + ''; 38 + }; 39 + in 40 + { 41 + users.users.website = { 42 + isSystemUser = true; 43 + group = "website"; 44 + }; 45 + users.groups.website = { }; 46 + 47 + age.secrets.websiteConfig.file = ../../../secrets/websiteConfig.age; 48 + 49 + systemd.services.website = { 50 + description = "website"; 51 + wantedBy = [ "multi-user.target" ]; 52 + after = [ "network.target" ]; 53 + environment = { 54 + HOME = "/var/lib/website"; 55 + ORIGIN = PUBLIC_BASE_URL; 56 + PORT = toString port; 57 + WEBSITE_DATA_DIR = "/var/lib/website"; 58 + VITE_CLOUDINARY_CLOUD_NAME = "dgtwf7mar"; 59 + }; 60 + serviceConfig = { 61 + User = "website"; 62 + ExecStart = "${pkg}/bin/eunomia"; 63 + Restart = "on-failure"; 64 + RestartSec = 5; 65 + WorkingDirectory = "/var/lib/website"; 66 + EnvironmentFile = config.age.secrets.websiteConfig.path; 67 + KillSignal = "SIGKILL"; 68 + }; 69 + }; 70 + 71 + # systemd.services.annoy-keep-alive = { 72 + # description = "keeps annoy peer connection alive"; 73 + # wantedBy = [ "multi-user.target" ]; 74 + # after = [ "network.target" ]; 75 + # serviceConfig = { 76 + # Type = "oneshot"; 77 + # ExecStart = "${pkgs.curl}/bin/curl http://100.64.0.1:3111/"; 78 + # }; 79 + # }; 80 + # systemd.timers.annoy-keep-alive.timerConfig = { 81 + # OnBootSec = "5 min"; 82 + # OnUnitActiveSec = "5 min"; 83 + # Unit = "annoy-keep-alive.service"; 84 + # }; 85 + 86 + services.nginx.virtualHosts."gaze.systems" = vhostConfig; 87 + services.nginx.virtualHosts."ptr.pet" = vhostConfig; 88 + services.nginx.virtualHosts."poor.dog" = vhostConfig; 89 + 90 + # services.nginx.virtualHosts."poor.dog" = { 91 + # locations."=/".return = "301 https://gaze.systems$request_uri"; 92 + # }; 93 + # services.nginx.virtualHosts."ptr.pet" = { 94 + # locations."=/".return = "301 https://gaze.systems$request_uri"; 95 + # }; 96 + }
+28
hosts/wolumonde/modules/arpa.disabled
··· 1 + { pkgs, ... }: 2 + let 3 + index = pkgs.writeText "index.txt" '' 4 + hi there~ 5 + 6 + you are currently interfacing with one of the data endpoints 7 + of entity with serial id /90008/. you may want to open a 8 + connection to https://gaze.systems/about for more data. 9 + 10 + /discord 90.008/ 11 + /bsky @poor.dog/ 12 + /email 90008@gaze.systems/ 13 + 14 + /dig +short TXT 9.0.0.0.8.e.f.1.5.0.7.4.0.1.0.0.2.ip6.arpa/ 15 + ''; 16 + root = pkgs.runCommand "root" { } '' 17 + mkdir -p $out 18 + ln -s ${index} $out/index.txt 19 + ''; 20 + in 21 + { 22 + services.nginx.virtualHosts."9.0.0.0.8.e.f.1.5.0.7.4.0.1.0.0.2.ip6.arpa" = { 23 + inherit root; 24 + locations."/".index = "index.txt"; 25 + quic = true; 26 + kTLS = true; 27 + }; 28 + }
-28
hosts/wolumonde/modules/arpa.nix
··· 1 - { pkgs, ... }: 2 - let 3 - index = pkgs.writeText "index.txt" '' 4 - hi there~ 5 - 6 - you are currently interfacing with one of the data endpoints 7 - of entity with serial id /90008/. you may want to open a 8 - connection to https://gaze.systems/about for more data. 9 - 10 - /discord 90.008/ 11 - /bsky @poor.dog/ 12 - /email 90008@gaze.systems/ 13 - 14 - /dig +short TXT 9.0.0.0.8.e.f.1.5.0.7.4.0.1.0.0.2.ip6.arpa/ 15 - ''; 16 - root = pkgs.runCommand "root" { } '' 17 - mkdir -p $out 18 - ln -s ${index} $out/index.txt 19 - ''; 20 - in 21 - { 22 - services.nginx.virtualHosts."9.0.0.0.8.e.f.1.5.0.7.4.0.1.0.0.2.ip6.arpa" = { 23 - inherit root; 24 - locations."/".index = "index.txt"; 25 - quic = true; 26 - kTLS = true; 27 - }; 28 - }
+67
hosts/wolumonde/modules/atproto.disabled
··· 1 + { pkgs, lib, ... }: 2 + let 3 + getFileType = name: if lib.hasSuffix ".json" name then "application/json" else "text/plain"; 4 + mkWellKnownCfg = files: { 5 + quic = true; 6 + kTLS = true; 7 + locations = ( 8 + lib.mapAttrs' (name: file: { 9 + name = "=/.well-known/${name}"; 10 + value = { 11 + extraConfig = '' 12 + alias ${file}; 13 + add_header access-control-allow-origin *; 14 + default_type ${getFileType name}; 15 + ''; 16 + }; 17 + }) files 18 + ); 19 + }; 20 + mkHandleCfg = 21 + rootDomain: did: 22 + (mkWellKnownCfg { 23 + "atproto-did" = pkgs.writeText "server" did; 24 + }) 25 + // { 26 + useACMEHost = rootDomain; 27 + forceSSL = true; 28 + quic = true; 29 + kTLS = true; 30 + }; 31 + mkDidWebCfg = domain: { 32 + "${domain}" = 33 + (mkWellKnownCfg { 34 + "did.json" = ../../../secrets/${domain}.did; 35 + "atproto-did" = pkgs.writeText "server" "did:web:${domain}"; 36 + }) 37 + // (lib.optionalAttrs (lib.hasSuffix "gaze.systems" domain) { 38 + useACMEHost = "gaze.systems"; 39 + forceSSL = true; 40 + quic = true; 41 + kTLS = true; 42 + }); 43 + }; 44 + dawnDid = "dawn.gaze.systems"; 45 + guestbookDid = "guestbook.gaze.systems"; 46 + in 47 + { 48 + security.acme.certs."gaze.systems".extraDomainNames = [ 49 + dawnDid 50 + guestbookDid 51 + "drew.gaze.systems" 52 + "test.gaze.systems" 53 + "eris.gaze.systems" 54 + ]; 55 + services.nginx.virtualHosts = { 56 + "test.gaze.systems" = mkHandleCfg "gaze.systems" "did:web:dawn.gaze.systems"; 57 + "poor.dog" = mkHandleCfg "poor.dog" "did:plc:dfl62fgb7wtjj3fcbb72naae"; 58 + "ptr.pet" = mkHandleCfg "ptr.pet" "did:plc:dfl62fgb7wtjj3fcbb72naae"; 59 + "nil.ptr.pet" = mkHandleCfg "ptr.pet" "did:plc:dumbmutt4po52ept2tczimje"; 60 + "june.ptr.pet" = mkHandleCfg "ptr.pet" "did:plc:y3z2rr7q5rywu4fjn3fmfyop"; 61 + "drew.gaze.systems" = mkHandleCfg "gaze.systems" "did:plc:vo6ie3kd6xvpjlof4pnb2zzp"; 62 + "eris.gaze.systems" = mkHandleCfg "gaze.systems" "did:plc:bxjnsrfzozl365rsdo5yvuz5"; 63 + } 64 + // (mkDidWebCfg dawnDid) 65 + // (mkDidWebCfg guestbookDid); 66 + # // (mkDidWebCfg "9.0.0.0.8.e.f.1.5.0.7.4.0.1.0.0.2.ip6.arpa"); 67 + }
-67
hosts/wolumonde/modules/atproto.nix
··· 1 - { pkgs, lib, ... }: 2 - let 3 - getFileType = name: if lib.hasSuffix ".json" name then "application/json" else "text/plain"; 4 - mkWellKnownCfg = files: { 5 - quic = true; 6 - kTLS = true; 7 - locations = ( 8 - lib.mapAttrs' (name: file: { 9 - name = "=/.well-known/${name}"; 10 - value = { 11 - extraConfig = '' 12 - alias ${file}; 13 - add_header access-control-allow-origin *; 14 - default_type ${getFileType name}; 15 - ''; 16 - }; 17 - }) files 18 - ); 19 - }; 20 - mkHandleCfg = 21 - rootDomain: did: 22 - (mkWellKnownCfg { 23 - "atproto-did" = pkgs.writeText "server" did; 24 - }) 25 - // { 26 - useACMEHost = rootDomain; 27 - forceSSL = true; 28 - quic = true; 29 - kTLS = true; 30 - }; 31 - mkDidWebCfg = domain: { 32 - "${domain}" = 33 - (mkWellKnownCfg { 34 - "did.json" = ../../../secrets/${domain}.did; 35 - "atproto-did" = pkgs.writeText "server" "did:web:${domain}"; 36 - }) 37 - // (lib.optionalAttrs (lib.hasSuffix "gaze.systems" domain) { 38 - useACMEHost = "gaze.systems"; 39 - forceSSL = true; 40 - quic = true; 41 - kTLS = true; 42 - }); 43 - }; 44 - dawnDid = "dawn.gaze.systems"; 45 - guestbookDid = "guestbook.gaze.systems"; 46 - in 47 - { 48 - security.acme.certs."gaze.systems".extraDomainNames = [ 49 - dawnDid 50 - guestbookDid 51 - "drew.gaze.systems" 52 - "test.gaze.systems" 53 - "eris.gaze.systems" 54 - ]; 55 - services.nginx.virtualHosts = { 56 - "test.gaze.systems" = mkHandleCfg "gaze.systems" "did:web:dawn.gaze.systems"; 57 - "poor.dog" = mkHandleCfg "poor.dog" "did:plc:dfl62fgb7wtjj3fcbb72naae"; 58 - "ptr.pet" = mkHandleCfg "ptr.pet" "did:plc:dfl62fgb7wtjj3fcbb72naae"; 59 - "nil.ptr.pet" = mkHandleCfg "ptr.pet" "did:plc:dumbmutt4po52ept2tczimje"; 60 - "june.ptr.pet" = mkHandleCfg "ptr.pet" "did:plc:y3z2rr7q5rywu4fjn3fmfyop"; 61 - "drew.gaze.systems" = mkHandleCfg "gaze.systems" "did:plc:vo6ie3kd6xvpjlof4pnb2zzp"; 62 - "eris.gaze.systems" = mkHandleCfg "gaze.systems" "did:plc:bxjnsrfzozl365rsdo5yvuz5"; 63 - } 64 - // (mkDidWebCfg dawnDid) 65 - // (mkDidWebCfg guestbookDid); 66 - # // (mkDidWebCfg "9.0.0.0.8.e.f.1.5.0.7.4.0.1.0.0.2.ip6.arpa"); 67 - }
-83
hosts/wolumonde/modules/blog.nix
··· 1 - { 2 - config, 3 - pkgs, 4 - inputs, 5 - ... 6 - }: 7 - let 8 - PUBLIC_BASE_URL = "https://gaze.systems"; 9 - modules = (pkgs.callPackage "${inputs.blog}/nix/modules.nix" { }).overrideAttrs (_: { 10 - outputHash = "sha256-rzfSfiK8FSNFR+1QTwM/ltLZBprG9BoQsPmOt6IdXFc="; 11 - }); 12 - pkg = pkgs.callPackage "${inputs.blog}/nix" { 13 - inherit PUBLIC_BASE_URL; 14 - gazesys-modules = modules; 15 - }; 16 - port = 3003; 17 - in 18 - { 19 - users.users.website = { 20 - isSystemUser = true; 21 - group = "website"; 22 - }; 23 - users.groups.website = { }; 24 - 25 - systemd.services.website = { 26 - description = "website"; 27 - wantedBy = [ "multi-user.target" ]; 28 - after = [ "network.target" ]; 29 - environment = { 30 - HOME = "/var/lib/website"; 31 - ORIGIN = PUBLIC_BASE_URL; 32 - PORT = toString port; 33 - WEBSITE_DATA_DIR = "/var/lib/website"; 34 - VITE_CLOUDINARY_CLOUD_NAME = "dgtwf7mar"; 35 - }; 36 - serviceConfig = { 37 - User = "website"; 38 - ExecStart = "${pkg}/bin/website"; 39 - Restart = "on-failure"; 40 - RestartSec = 5; 41 - WorkingDirectory = "/var/lib/website"; 42 - EnvironmentFile = config.age.secrets.websiteConfig.path; 43 - KillSignal = "SIGKILL"; 44 - }; 45 - }; 46 - 47 - # systemd.services.annoy-keep-alive = { 48 - # description = "keeps annoy peer connection alive"; 49 - # wantedBy = [ "multi-user.target" ]; 50 - # after = [ "network.target" ]; 51 - # serviceConfig = { 52 - # Type = "oneshot"; 53 - # ExecStart = "${pkgs.curl}/bin/curl http://100.64.0.1:3111/"; 54 - # }; 55 - # }; 56 - # systemd.timers.annoy-keep-alive.timerConfig = { 57 - # OnBootSec = "5 min"; 58 - # OnUnitActiveSec = "5 min"; 59 - # Unit = "annoy-keep-alive.service"; 60 - # }; 61 - 62 - services.nginx.virtualHosts."gaze.systems" = { 63 - locations."/".proxyPass = "http://localhost:${toString port}"; 64 - locations."/annoy/ws/" = { 65 - proxyWebsockets = true; 66 - proxyPass = "http://100.64.0.9:3111/"; 67 - extraConfig = '' 68 - rewrite ^/annoy/ws/(.*) /$1 break; 69 - ''; 70 - }; 71 - locations."/annoy/ws" = { 72 - proxyWebsockets = true; 73 - proxyPass = "http://100.64.0.9:3111/"; 74 - extraConfig = '' 75 - rewrite ^/annoy/ws(.*) /$1 break; 76 - ''; 77 - }; 78 - }; 79 - 80 - services.nginx.virtualHosts."poor.dog" = { 81 - locations."/".return = "301 https://gaze.systems$request_uri"; 82 - }; 83 - }
+29
hosts/wolumonde/modules/clickee-proxy.disabled
··· 1 + { config, terra, ... }: 2 + let 3 + port = 7145; 4 + in 5 + { 6 + age.secrets.clickeeProxyConfig = { 7 + file = ../../../secrets/clickeeProxyConfig.age; 8 + }; 9 + 10 + systemd.services.clickee-proxy = { 11 + description = "clickee-proxy"; 12 + wantedBy = [ "multi-user.target" ]; 13 + after = [ "network.target" ]; 14 + environment = { 15 + PORT = toString port; 16 + }; 17 + serviceConfig = { 18 + DynamicUser = true; 19 + ExecStart = "${terra.clickee-proxy}/bin/clickee-proxy"; 20 + Restart = "on-failure"; 21 + RestartSec = 5; 22 + EnvironmentFile = config.age.secrets.clickeeProxyConfig.path; 23 + }; 24 + }; 25 + 26 + services.nginx.virtualHosts."poor.dog" = { 27 + locations."/click".proxyPass = "http://localhost:${toString port}"; 28 + }; 29 + }
-29
hosts/wolumonde/modules/clickee-proxy.nix
··· 1 - { config, terra, ... }: 2 - let 3 - port = 7145; 4 - in 5 - { 6 - age.secrets.clickeeProxyConfig = { 7 - file = ../../../secrets/clickeeProxyConfig.age; 8 - }; 9 - 10 - systemd.services.clickee-proxy = { 11 - description = "clickee-proxy"; 12 - wantedBy = [ "multi-user.target" ]; 13 - after = [ "network.target" ]; 14 - environment = { 15 - PORT = toString port; 16 - }; 17 - serviceConfig = { 18 - DynamicUser = true; 19 - ExecStart = "${terra.clickee-proxy}/bin/clickee-proxy"; 20 - Restart = "on-failure"; 21 - RestartSec = 5; 22 - EnvironmentFile = config.age.secrets.clickeeProxyConfig.path; 23 - }; 24 - }; 25 - 26 - services.nginx.virtualHosts."poor.dog" = { 27 - locations."/click".proxyPass = "http://localhost:${toString port}"; 28 - }; 29 - }
+65
hosts/wolumonde/modules/email.disabled
··· 1 + { pkgs, ... }: 2 + { 3 + security.acme.certs."ptr.pet".extraDomainNames = [ 4 + "mta-sts.ptr.pet" 5 + "autoconfig.ptr.pet" 6 + "autodiscover.ptr.pet" 7 + "test.ptr.pet" 8 + ]; 9 + services.nginx.virtualHosts."test.ptr.pet" = { 10 + useACMEHost = "ptr.pet"; 11 + quic = true; 12 + kTLS = true; 13 + forceSSL = true; 14 + }; 15 + services.nginx.virtualHosts."ptr.pet" = { 16 + useACMEHost = "ptr.pet"; 17 + quic = true; 18 + kTLS = true; 19 + forceSSL = true; 20 + locations."/mail/config-v1.1.xml" = { 21 + return = "301 https://autoconfig.migadu.com/mail/config-v1.1.xml"; 22 + }; 23 + locations."/Autodiscover/Autodiscover.xml" = { 24 + return = "301 https://autodiscover.migadu.com/Autodiscover/Autodiscover.xml"; 25 + }; 26 + }; 27 + services.nginx.virtualHosts."mta-sts.ptr.pet" = 28 + let 29 + file = pkgs.writeText "mta-sts.txt" '' 30 + version: STSv1 31 + mode: enforce 32 + mx: aspmx1.migadu.com 33 + mx: aspmx2.migadu.com 34 + max_age: 31557600 35 + ''; 36 + in 37 + { 38 + useACMEHost = "ptr.pet"; 39 + quic = true; 40 + kTLS = true; 41 + forceSSL = true; 42 + locations."=/.well-known/mta-sts.txt".extraConfig = '' 43 + alias ${file}; 44 + default_type text/plain; 45 + ''; 46 + }; 47 + services.nginx.virtualHosts."autoconfig.ptr.pet" = { 48 + useACMEHost = "ptr.pet"; 49 + quic = true; 50 + kTLS = true; 51 + forceSSL = true; 52 + locations."/" = { 53 + return = "301 https://autoconfig.migadu.com$request_uri"; 54 + }; 55 + }; 56 + services.nginx.virtualHosts."autodiscover.ptr.pet" = { 57 + useACMEHost = "ptr.pet"; 58 + quic = true; 59 + kTLS = true; 60 + forceSSL = true; 61 + locations."/" = { 62 + return = "301 https://autodiscover.migadu.com$request_uri"; 63 + }; 64 + }; 65 + }
-65
hosts/wolumonde/modules/email.nix
··· 1 - { pkgs, ... }: 2 - { 3 - security.acme.certs."ptr.pet".extraDomainNames = [ 4 - "mta-sts.ptr.pet" 5 - "autoconfig.ptr.pet" 6 - "autodiscover.ptr.pet" 7 - "test.ptr.pet" 8 - ]; 9 - services.nginx.virtualHosts."test.ptr.pet" = { 10 - useACMEHost = "ptr.pet"; 11 - quic = true; 12 - kTLS = true; 13 - forceSSL = true; 14 - }; 15 - services.nginx.virtualHosts."ptr.pet" = { 16 - useACMEHost = "ptr.pet"; 17 - quic = true; 18 - kTLS = true; 19 - forceSSL = true; 20 - locations."/mail/config-v1.1.xml" = { 21 - return = "301 https://autoconfig.migadu.com/mail/config-v1.1.xml"; 22 - }; 23 - locations."/Autodiscover/Autodiscover.xml" = { 24 - return = "301 https://autodiscover.migadu.com/Autodiscover/Autodiscover.xml"; 25 - }; 26 - }; 27 - services.nginx.virtualHosts."mta-sts.ptr.pet" = 28 - let 29 - file = pkgs.writeText "mta-sts.txt" '' 30 - version: STSv1 31 - mode: enforce 32 - mx: aspmx1.migadu.com 33 - mx: aspmx2.migadu.com 34 - max_age: 31557600 35 - ''; 36 - in 37 - { 38 - useACMEHost = "ptr.pet"; 39 - quic = true; 40 - kTLS = true; 41 - forceSSL = true; 42 - locations."=/.well-known/mta-sts.txt".extraConfig = '' 43 - alias ${file}; 44 - default_type text/plain; 45 - ''; 46 - }; 47 - services.nginx.virtualHosts."autoconfig.ptr.pet" = { 48 - useACMEHost = "ptr.pet"; 49 - quic = true; 50 - kTLS = true; 51 - forceSSL = true; 52 - locations."/" = { 53 - return = "301 https://autoconfig.migadu.com$request_uri"; 54 - }; 55 - }; 56 - services.nginx.virtualHosts."autodiscover.ptr.pet" = { 57 - useACMEHost = "ptr.pet"; 58 - quic = true; 59 - kTLS = true; 60 - forceSSL = true; 61 - locations."/" = { 62 - return = "301 https://autodiscover.migadu.com$request_uri"; 63 - }; 64 - }; 65 - }
+33
hosts/wolumonde/modules/fluentbit.disabled
··· 1 + { 2 + pkgs, 3 + config, 4 + lib, 5 + ... 6 + }: 7 + { 8 + services.fluent-bit = { 9 + enable = true; 10 + settings = { 11 + service.flush = 1; 12 + pipeline.inputs = [ 13 + { 14 + name = "node_exporter_metrics"; 15 + tag = "metrics.node"; 16 + scrape_interval = 5; 17 + } 18 + # { 19 + # name = "dummy"; 20 + # tag = "logs.dummy"; 21 + # dummy = ''{"_msg": "dummy"}''; 22 + # } 23 + { 24 + name = "fluentbit_metrics"; 25 + tag = "metrics.fluentbit"; 26 + scrape_interval = 5; 27 + } 28 + ]; 29 + }; 30 + }; 31 + 32 + systemd.services.fluent-bit.serviceConfig.StateDirectory = "fluent-bit"; 33 + }
-33
hosts/wolumonde/modules/fluentbit.nix
··· 1 - { 2 - pkgs, 3 - config, 4 - lib, 5 - ... 6 - }: 7 - { 8 - services.fluent-bit = { 9 - enable = true; 10 - settings = { 11 - service.flush = 1; 12 - pipeline.inputs = [ 13 - { 14 - name = "node_exporter_metrics"; 15 - tag = "metrics.node"; 16 - scrape_interval = 5; 17 - } 18 - # { 19 - # name = "dummy"; 20 - # tag = "logs.dummy"; 21 - # dummy = ''{"_msg": "dummy"}''; 22 - # } 23 - { 24 - name = "fluentbit_metrics"; 25 - tag = "metrics.fluentbit"; 26 - scrape_interval = 5; 27 - } 28 - ]; 29 - }; 30 - }; 31 - 32 - systemd.services.fluent-bit.serviceConfig.StateDirectory = "fluent-bit"; 33 - }
+98
hosts/wolumonde/modules/forgejo.disabled/default.nix
··· 1 + { 2 + pkgs, 3 + lib, 4 + config, 5 + ... 6 + }: 7 + let 8 + forgejoCfg = config.services.forgejo.settings; 9 + anubisCfg = config.services.anubis.instances."forgejo".settings; 10 + in 11 + { 12 + services.forgejo = { 13 + enable = true; 14 + package = pkgs.forgejo; 15 + lfs.enable = true; 16 + settings = { 17 + DEFAULT.APP_NAME = "awruff ^^"; 18 + server = { 19 + DOMAIN = "git.gaze.systems"; 20 + ROOT_URL = "https://git.gaze.systems/"; 21 + HTTP_PORT = 9008; 22 + }; 23 + service = { 24 + DISABLE_REGISTRATION = true; 25 + }; 26 + security.REVERSE_PROXY_TRUSTED_PROXIES = "127.0.0.0/8,::1/128"; 27 + session.COOKIE_SECURE = true; 28 + ui = { 29 + DEFAULT_SHOW_FULL_NAME = true; 30 + DEFAULT_THEME = "edge-dark"; 31 + THEMES = "edge-dark,forgejo-dark"; 32 + THEME_COLOR_META_TAG = "#333644"; 33 + }; 34 + "ui.meta" = { 35 + DESCRIPTION = "nyan? arf!!!! :3"; 36 + }; 37 + metrics.ENABLED = true; 38 + }; 39 + }; 40 + 41 + # copy custom data stuff 42 + systemd.services.forgejo.preStart = 43 + let 44 + customDir = "${config.services.forgejo.stateDir}/custom"; 45 + getCustomDir = name: "${customDir}/${name}"; 46 + makeCopyCommand = dir: '' 47 + mkdir -p ${customDir} 48 + rm -rf ${getCustomDir dir} 49 + cp -r --no-preserve=mode,ownership ${./${dir}} ${getCustomDir dir} 50 + ''; 51 + in 52 + lib.concatMapStrings makeCopyCommand [ 53 + "templates" 54 + "public" 55 + ]; 56 + 57 + security.acme.certs."gaze.systems".extraDomainNames = [ forgejoCfg.server.DOMAIN ]; 58 + services.nginx.virtualHosts.${forgejoCfg.server.DOMAIN} = { 59 + useACMEHost = "gaze.systems"; 60 + forceSSL = true; 61 + quic = true; 62 + kTLS = true; 63 + # disallow metrics for public 64 + locations."/metrics".return = "403"; 65 + locations."/" = { 66 + extraConfig = '' 67 + client_max_body_size 1000m; 68 + ''; 69 + proxyPass = "http://localhost${anubisCfg.BIND}"; 70 + }; 71 + }; 72 + 73 + services.anubis.instances."forgejo".settings = { 74 + BIND = ":6293"; 75 + BIND_NETWORK = "tcp"; 76 + METRICS_BIND = ":9090"; 77 + METRICS_BIND_NETWORK = "tcp"; 78 + TARGET = "http://localhost:${toString forgejoCfg.server.HTTP_PORT}"; 79 + WEBMASTER_EMAIL = "90008@gaze.systems"; 80 + SERVE_ROBOTS_TXT = true; 81 + OG_PASSTHROUGH = true; 82 + DIFFICULTY = 4; 83 + }; 84 + 85 + # scrape forgejo metrics 86 + services.victoriametrics.prometheusConfig.scrape_configs = [ 87 + { 88 + job_name = "forgejo"; 89 + metrics_path = "/metrics"; 90 + static_configs = [ { targets = [ "localhost:${toString forgejoCfg.server.HTTP_PORT}" ]; } ]; 91 + } 92 + { 93 + job_name = "anubis_forgejo"; 94 + metrics_path = "/metrics"; 95 + static_configs = [ { targets = [ "localhost${anubisCfg.METRICS_BIND}" ]; } ]; 96 + } 97 + ]; 98 + }
+995
hosts/wolumonde/modules/forgejo.disabled/public/assets/css/theme-edge-dark.css
··· 1 + @import "https://cdn.jsdelivr.net/npm/comic-mono@0.0.1/index.css"; 2 + @font-face { 3 + font-family: 'Comic Sans'; 4 + font-style: normal; 5 + font-display: swap; 6 + src: url('../fonts/comic.woff2') format('woff2'); 7 + } 8 + @font-face { 9 + font-family: 'Comic Sans'; 10 + font-style: normal; 11 + font-weight: bold; 12 + font-display: swap; 13 + src: url('../fonts/comicbd.woff2') format('woff2'); 14 + } 15 + @font-face { 16 + font-family: 'Comic Sans'; 17 + font-style: italic; 18 + font-display: swap; 19 + src: url('../fonts/comici.woff2') format('woff2'); 20 + } 21 + :root { 22 + --fonts-proportional: "Comic Sans", sans-serif !important; 23 + --fonts-monospace: "Comic Mono", monospace !important; 24 + } 25 + .chroma .hl{background-color:#3f424d}.chroma .ln,.chroma .lnt{color:#7f7f7f} 26 + 27 + .chroma .k{color:#f63} 28 + 29 + .chroma .kc{color:#fa1} 30 + 31 + .chroma .kd{color:#9daccc} 32 + 33 + .chroma .kn{color:#fa1} 34 + 35 + .chroma .kp{color:#5f8700} 36 + 37 + .chroma .kr{color:#f63} 38 + 39 + .chroma .kt{color:#9daccc} 40 + 41 + .chroma .na{color:#8a8a8a} 42 + 43 + .chroma .bp,.chroma .nb{color:#9daccc} 44 + 45 + .chroma .nc,.chroma .no{color:#fa1} 46 + 47 + .chroma .nd{color:#9daccc} 48 + 49 + .chroma .ni{color:#fa1} 50 + 51 + .chroma .ne{color:#af8700} 52 + 53 + .chroma .nf{color:#9daccc} 54 + 55 + .chroma .nl,.chroma .nn{color:#fa1} 56 + 57 + .chroma .nt,.chroma .nv,.chroma .nx{color:#9daccc} 58 + 59 + .chroma .vc{color:#f81} 60 + 61 + .chroma .vg,.chroma .vi{color:#fa1} 62 + 63 + .chroma .s,.chroma .sa{color:#1af} 64 + 65 + .chroma .sb{color:#a0cc75} 66 + 67 + .chroma .dl,.chroma .sc{color:#1af} 68 + 69 + .chroma .sd{color:#6a737d} 70 + 71 + .chroma .s2{color:#a0cc75} 72 + 73 + .chroma .se{color:#f63} 74 + 75 + .chroma .sh{color:#1af} 76 + 77 + .chroma .si,.chroma .sx{color:#fa1} 78 + 79 + .chroma .sr{color:#97c} 80 + 81 + .chroma .s1{color:#a0cc75} 82 + 83 + .chroma .ss{color:#fa1} 84 + 85 + .chroma .il,.chroma .m,.chroma .mb,.chroma .mf,.chroma .mh,.chroma .mi,.chroma .mo{color:#1af} 86 + 87 + .chroma .o{color:#f63} 88 + 89 + .chroma .ow{color:#5f8700} 90 + 91 + .chroma .c,.chroma .c1,.chroma .ch,.chroma .cm{color:#6a737d} 92 + 93 + .chroma .cs{color:#637d} 94 + 95 + .chroma .cp,.chroma .cpf{color:#fc6} 96 + 97 + .chroma .gd{color:#fff;background-color:#5f3737} 98 + 99 + .chroma .ge{color:#ef5} 100 + 101 + .chroma .gr{color:#f33} 102 + 103 + .chroma .gh{color:#fa1} 104 + 105 + .chroma .gi{color:#fff;background-color:#3a523a} 106 + 107 + .chroma .go{color:#888888} 108 + 109 + .chroma .gp{color:#555555} 110 + 111 + .chroma .gu{color:#9daccc} 112 + 113 + .chroma .gt{color:#f63} 114 + 115 + .chroma .w{color:#bbbbbb} 116 + 117 + :root { 118 + --color-primary: #ccc; 119 + --color-primary-dark-1: #c5c5c5; 120 + --color-primary-dark-2: #bebebe; 121 + --color-primary-dark-3: #b7b7b7; 122 + --color-primary-dark-4: #b0b0b0; 123 + --color-primary-dark-5: #a9a9a9; 124 + --color-primary-dark-6: #a2a2a2; 125 + --color-primary-dark-7: #9b9b9b; 126 + --color-primary-light-1: #d3d3d3; 127 + --color-primary-light-2: #d9d9d9; 128 + --color-primary-light-3: #e0e0e0; 129 + --color-primary-light-4: #e7e7e7; 130 + --color-primary-light-5: #eeeeee; 131 + --color-primary-light-6: #f5f5f5; 132 + --color-primary-light-7: #fff; 133 + --color-primary-alpha-10: #afb0b119; 134 + --color-primary-alpha-20: #afb0b133; 135 + --color-primary-alpha-30: #afb0b14b; 136 + --color-primary-alpha-40: #afb0b166; 137 + --color-primary-alpha-50: #afb0b180; 138 + --color-primary-alpha-60: #afb0b199; 139 + --color-primary-alpha-70: #afb0b1b3; 140 + --color-primary-alpha-80: #afb0b1cc; 141 + --color-primary-alpha-90: #afb0b1e1; 142 + --color-secondary: #000; 143 + --color-secondary-dark-1: #141414; 144 + --color-secondary-dark-2: #0b0c0e; 145 + --color-secondary-dark-3: #17181c; 146 + --color-secondary-dark-4: #22242a; 147 + --color-secondary-dark-5: #2d3139; 148 + --color-secondary-dark-6: #393d47; 149 + --color-secondary-dark-7: #444955; 150 + --color-secondary-dark-7: #4f5563; 151 + --color-secondary-dark-8: #5b6171; 152 + --color-secondary-dark-8: #666d7f; 153 + --color-secondary-dark-9: #71798e; 154 + --color-secondary-dark-10: #808799; 155 + --color-secondary-dark-11: #8e94a4; 156 + --color-secondary-light-1: #373b46; 157 + --color-secondary-light-2: #292c34; 158 + --color-secondary-light-3: #1c1e23; 159 + --color-secondary-light-4: #0e0f11; 160 + --color-secondary-alpha-10: #45454519; 161 + --color-secondary-alpha-20: #45454533; 162 + --color-secondary-alpha-30: #4545454b; 163 + --color-secondary-alpha-40: #45454566; 164 + --color-secondary-alpha-50: #45454580; 165 + --color-secondary-alpha-60: #45454599; 166 + --color-secondary-alpha-70: #454545b3; 167 + --color-secondary-alpha-80: #454545cc; 168 + --color-secondary-alpha-90: #454545e1; 169 + /* colors */ 170 + --color-red: #db2828; 171 + --color-orange: #ff6600; 172 + --color-yellow: #ffff99; 173 + --color-olive: #abc11a; 174 + --color-green: #199717; 175 + --color-teal: #01fed4; 176 + --color-blue: #226ac9; 177 + --color-violet: #6435c9; 178 + --color-purple: #a333c8; 179 + --color-pink: #e03997; 180 + --color-brown: #a5673f; 181 + --color-grey: #767a85; 182 + --color-black: #1e222e; 183 + --color-gold: #a1882b; 184 + --color-white: #ffffff; 185 + --color-diff-removed-word-bg: #6f3333; 186 + --color-diff-added-word-bg: #3c653c; 187 + --color-diff-removed-row-bg: #3c2626; 188 + --color-diff-added-row-bg: #283e2d; 189 + --color-diff-removed-row-border: #634343; 190 + --color-diff-added-row-border: #314a37; 191 + --color-diff-inactive: #353846; 192 + /* target-based colors */ 193 + --color-body: #000; 194 + --color-box-header: #000; 195 + --color-box-body: #070707; 196 + --color-text-dark: #dee1e8; 197 + --color-text: #c7cad1; 198 + --color-text-light: #acb0b9; 199 + --color-text-light-2: #8a8e99; 200 + --color-text-light-3: #707687; 201 + --color-footer: #000; 202 + --color-timeline: #4c525e; 203 + --color-input-text: #d5dbe6; 204 + --color-input-background: #000; 205 + --color-input-border: #454545; 206 + --color-input-border-hover: #4e5465; 207 + --color-navbar: #060606; 208 + --color-light: #00000028; 209 + --color-light-border: #ffffff28; 210 + --color-hover: #ffffff10; 211 + --color-active: #25272d; 212 + --color-menu: #060606; 213 + --color-card: #060606; 214 + --color-markdown-table-row: #ffffff06; 215 + --color-markdown-code-block: #121314; 216 + --color-button: #070707; 217 + --color-code-bg: #060606; 218 + --color-shadow: #00000060; 219 + --color-secondary-bg: #060606; 220 + --color-text-focus: #fff; 221 + --color-expand-button: #3c404d; 222 + --color-placeholder-text: #6a737d; 223 + --color-editor-line-highlight: var(--color-primary-light-5); 224 + --color-project-board-bg: var(--color-secondary-light-2); 225 + --color-nav-bg: var(--color-body); 226 + --color-nav-hover-bg: var(--color-hover); 227 + } 228 + 229 + ::-webkit-calendar-picker-indicator { 230 + filter: invert(.8); 231 + } 232 + 233 + .ui.horizontal.segments > .segment { 234 + background-color: #2d2d2d; 235 + } 236 + 237 + .repository .segment.reactions .ui.label.basic.blue { 238 + background: var(--color-primary-alpha-20) !important; 239 + } 240 + 241 + [data-tooltip]::before, 242 + [data-tooltip]::after { 243 + background: #1b1c1d !important; /* .ui.inverted.popup */ 244 + border-color: #1b1c1d !important; /* .ui.inverted.popup */ 245 + color: #dbdbdb !important; 246 + } 247 + 248 + [data-tooltip]::before { 249 + box-shadow: 1px 1px 0 0 #1b1c1d !important; /* .ui.inverted.popup */ 250 + } 251 + 252 + .ui.green.progress .bar { 253 + background-color: #848b84; 254 + } 255 + 256 + .ui.progress.success .bar { 257 + background-color: #8fa37b !important; 258 + } 259 + 260 + .following.bar.light { 261 + background: var(--color-body); 262 + border-color: var(--color-secondary-alpha-40); 263 + } 264 + 265 + .following.bar .top.menu a.item:hover { 266 + color: #fff; 267 + } 268 + 269 + .feeds .list ul li.private { 270 + background: #25272d; 271 + } 272 + 273 + .ui.link.list .item, 274 + .ui.link.list a.item, 275 + .ui.link.list .item a:not(.ui) { 276 + color: #dbdbdb; 277 + } 278 + 279 + .ui.red.label, 280 + .ui.red.labels .label { 281 + background-color: #7d3434 !important; 282 + border-color: #8a2121 !important; 283 + } 284 + 285 + .ui.yellow.label, 286 + .ui.yellow.labels .label { 287 + border-color: #664d02 !important; 288 + background-color: #936e00 !important; 289 + } 290 + 291 + .ui.accordion .title:not(.ui) { 292 + color: #dbdbdb; 293 + } 294 + 295 + .ui.green.label, 296 + .ui.green.labels .label, 297 + .ui.basic.green.label { 298 + background-color: #53682c !important; 299 + border-color: #53682c !important; 300 + } 301 + 302 + .ui.green.labels a.label:hover, 303 + .ui.basic.green.labels a.label:hover, 304 + a.ui.ui.ui.green.label:hover, 305 + a.ui.basic.green.label:hover { 306 + background-color: #657a3e !important; 307 + border-color: #657a3e !important; 308 + color: #fff !important; 309 + } 310 + 311 + .ui.divider:not(.vertical):not(.horizontal) { 312 + border-bottom-color: var(--color-secondary); 313 + border-top-color: transparent; 314 + } 315 + 316 + .form .help { 317 + color: #7f8699; 318 + } 319 + 320 + .ui .text.light.grey { 321 + color: #7f8699 !important; 322 + } 323 + 324 + .ui.form .fields.error .field textarea, 325 + .ui.form .fields.error .field select, 326 + .ui.form .fields.error .field input:not([type]), 327 + .ui.form .fields.error .field input[type="date"], 328 + .ui.form .fields.error .field input[type="datetime-local"], 329 + .ui.form .fields.error .field input[type="email"], 330 + .ui.form .fields.error .field input[type="number"], 331 + .ui.form .fields.error .field input[type="password"], 332 + .ui.form .fields.error .field input[type="search"], 333 + .ui.form .fields.error .field input[type="tel"], 334 + .ui.form .fields.error .field input[type="time"], 335 + .ui.form .fields.error .field input[type="text"], 336 + .ui.form .fields.error .field input[type="file"], 337 + .ui.form .fields.error .field input[type="url"], 338 + .ui.form .field.error textarea, 339 + .ui.form .field.error select, 340 + .ui.form .field.error input:not([type]), 341 + .ui.form .field.error input[type="date"], 342 + .ui.form .field.error input[type="datetime-local"], 343 + .ui.form .field.error input[type="email"], 344 + .ui.form .field.error input[type="number"], 345 + .ui.form .field.error input[type="password"], 346 + .ui.form .field.error input[type="search"], 347 + .ui.form .field.error input[type="tel"], 348 + .ui.form .field.error input[type="time"], 349 + .ui.form .field.error input[type="text"], 350 + .ui.form .field.error input[type="file"], 351 + .ui.form .field.error input[type="url"] { 352 + background-color: #522; 353 + border: 1px solid #7d3434; 354 + color: #f9cbcb; 355 + } 356 + 357 + .ui.form .field.error select:focus, 358 + .ui.form .field.error input:not([type]):focus, 359 + .ui.form .field.error input[type="date"]:focus, 360 + .ui.form .field.error input[type="datetime-local"]:focus, 361 + .ui.form .field.error input[type="email"]:focus, 362 + .ui.form .field.error input[type="number"]:focus, 363 + .ui.form .field.error input[type="password"]:focus, 364 + .ui.form .field.error input[type="search"]:focus, 365 + .ui.form .field.error input[type="tel"]:focus, 366 + .ui.form .field.error input[type="time"]:focus, 367 + .ui.form .field.error input[type="text"]:focus, 368 + .ui.form .field.error input[type="file"]:focus, 369 + .ui.form .field.error input[type="url"]:focus { 370 + background-color: #522; 371 + border: 1px solid #a04141; 372 + color: #f9cbcb; 373 + } 374 + 375 + .ui.green.button, 376 + .ui.green.buttons .button { 377 + background-color: #070707; 378 + } 379 + 380 + .ui.green.button:hover, 381 + .ui.green.buttons .button:hover { 382 + background-color: #141414; 383 + } 384 + 385 + .ui.green.button:active, 386 + .ui.green.buttons .button:active { 387 + background-color: #070707; 388 + } 389 + 390 + .ui.search > .results { 391 + background: #2d2d2d; 392 + border-color: var(--color-secondary); 393 + } 394 + 395 + .ui.search > .results .result:hover, 396 + .ui.category.search > .results .category .result:hover { 397 + background: var(--color-secondary); 398 + } 399 + 400 + .ui.search > .results .result .title { 401 + color: #dbdbdb; 402 + } 403 + 404 + .ui.table > thead > tr > th { 405 + background: var(--color-secondary); 406 + color: #dbdbdb !important; 407 + } 408 + 409 + .repository.file.list #repo-files-table tr { 410 + background: #070707; 411 + } 412 + 413 + .repository.file.list #repo-files-table tr:hover { 414 + background-color: #2d2d2d !important; 415 + } 416 + 417 + .repository.file.editor.edit, 418 + .repository.wiki.new .CodeMirror { 419 + .editor-preview, 420 + .editor-preview-side, 421 + & + .editor-preview-side { 422 + background: #25272d; 423 + 424 + .markdown:not(code).ui.segment { 425 + border-width: 0; 426 + } 427 + } 428 + } 429 + 430 + .overflow.menu .items .item { 431 + color: #9d9d9d; 432 + } 433 + 434 + .overflow.menu .items .item:hover { 435 + color: #dbdbdb; 436 + } 437 + 438 + .ui.list > .item > .content { 439 + color: var(--color-secondary-dark-6) !important; 440 + } 441 + 442 + .ui.active.button:active, 443 + .ui.button:active, 444 + .ui.button:focus, 445 + .ui.active.button { 446 + background-color: #2e3e4e; 447 + color: #dbdbdb; 448 + } 449 + 450 + .ui.active.button:hover { 451 + background-color: #475e75; 452 + color: #dbdbdb; 453 + } 454 + 455 + .repository .navbar .active.item, 456 + .repository .navbar .active.item:hover { 457 + border-color: transparent !important; 458 + } 459 + 460 + .ui .info.segment.top { 461 + background-color: var(--color-secondary) !important; 462 + } 463 + 464 + .repository .diff-stats li { 465 + border-color: var(--color-secondary); 466 + } 467 + 468 + .tag-code, 469 + .tag-code td { 470 + background: #25272d !important; 471 + 472 + } 473 + .tag-code td.lines-num { 474 + background-color: #3a3e4c !important; 475 + } 476 + 477 + .tag-code td.lines-type-marker, 478 + td.blob-hunk { 479 + color: #dbdbdb !important; 480 + } 481 + 482 + .ui.attached.info.message, 483 + .ui.info.message { 484 + box-shadow: 0 0 0 1px #4b5e71 inset, 0 0 0 0 transparent; 485 + } 486 + 487 + .ui.bottom.attached.message { 488 + background-color: #2c662d; 489 + color: #ab6363; 490 + } 491 + 492 + .ui.bottom.attached.message .pull-right { 493 + color: #ab6363; 494 + } 495 + 496 + .ui.info.message { 497 + background-color: #2c3b4a; 498 + color: #9ebcc5; 499 + } 500 + 501 + .ui .warning.header, 502 + .ui.warning.message { 503 + background-color: #542 !important; 504 + border-color: #ec8; 505 + } 506 + 507 + .ui.warning.message { 508 + color: #ec8; 509 + box-shadow: 0 0 0 1px #ec8; 510 + } 511 + 512 + .ui.warning.segment { 513 + border-color: #ec8; 514 + } 515 + 516 + .ui.red.message, 517 + .ui.error.message { 518 + background-color: #522; 519 + color: #f9cbcb; 520 + box-shadow: 0 0 0 1px #a04141 inset; 521 + } 522 + 523 + .ui .error.header, 524 + .ui.error.message { 525 + background-color: #522 !important; 526 + border-color: #a04141; 527 + } 528 + 529 + .ui.error.segment { 530 + border-color: #a04141; 531 + } 532 + 533 + .ui.red.button, 534 + .ui.red.buttons .button { 535 + background-color: #7d3434; 536 + } 537 + 538 + .ui.red.button:hover, 539 + .ui.red.buttons .button:hover { 540 + background-color: #984646; 541 + } 542 + 543 + .ui.positive.message { 544 + background-color: #000; 545 + color: #fff; 546 + box-shadow: 0 0 0 1px #1c1c1c inset, 0 0 0 0 transparent; 547 + } 548 + 549 + .ui.negative.message { 550 + background-color: rgba(80, 23, 17, .6); 551 + color: #f9cbcb; 552 + box-shadow: 0 0 0 1px rgba(121, 71, 66, .5) inset, 0 0 0 0 transparent; 553 + } 554 + 555 + .ui.list .list > .item .header, 556 + .ui.list > .item .header { 557 + color: #dedede; 558 + } 559 + 560 + .ui.list .list > .item .description, 561 + .ui.list > .item .description { 562 + color: var(--color-secondary-dark-6); 563 + } 564 + 565 + .repository.file.list #repo-files-table tbody .svg.octicon-file-directory, 566 + .repository.file.list #repo-files-table tbody .svg.octicon-file-submodule { 567 + color: #52555b; 568 + } 569 + 570 + .repository.labels .ui.basic.black.label { 571 + background-color: #bbbbbb !important; 572 + } 573 + 574 + .lines-commit, 575 + .blame .lines-num { 576 + background: #060606 !important; 577 + } 578 + 579 + .lines-num { 580 + color: var(--color-secondary-dark-6) !important; 581 + border-color: var(--color-secondary) !important; 582 + } 583 + 584 + td.blob-excerpt { 585 + background-color: rgba(0, 0, 0, .15); 586 + } 587 + 588 + .lines-code.active, 589 + .lines-code .active { 590 + background: #534d1b !important; 591 + } 592 + 593 + .ui.ui.ui.ui.table tr.active, 594 + .ui.ui.table td.active { 595 + color: #dbdbdb; 596 + } 597 + 598 + .ui.active.label { 599 + background: #46484e; 600 + border-color: #46484e; 601 + color: #dbdbdb; 602 + } 603 + 604 + .repository .ui.attached.message.isSigned.isVerified { 605 + background-color: #394829; 606 + color: var(--color-secondary-dark-6); 607 + 608 + &.message { 609 + color: #ab6363; 610 + .ui.text { 611 + color: var(--color-secondary-dark-6); 612 + } 613 + .pull-right { 614 + color: #ab6363; 615 + } 616 + } 617 + } 618 + 619 + .repository .ui.attached.message.isSigned.isVerifiedUntrusted { 620 + background-color: #4a3903; 621 + color: var(--color-secondary-dark-6); 622 + &.message { 623 + color: #c2c193; 624 + .ui.text { 625 + color: var(--color-secondary-dark-6); 626 + } 627 + a { 628 + color: #c2c193; 629 + } 630 + } 631 + } 632 + 633 + .repository .ui.attached.message.isSigned.isVerifiedUnmatched { 634 + background-color: #4e3321; 635 + color: var(--color-secondary-dark-6); 636 + &.message { 637 + color: #c2a893; 638 + .ui.text { 639 + color: var(--color-secondary-dark-6); 640 + } 641 + a { 642 + color: #c2a893; 643 + } 644 + } 645 + } 646 + 647 + .repository .ui.attached.message.isSigned.isWarning { 648 + background-color: rgba(80, 23, 17, .6); 649 + &.message { 650 + color: #d07d7d; 651 + .ui.text { 652 + color: #d07d7d; 653 + } 654 + } 655 + } 656 + 657 + .ui.header .sub.header { 658 + color: var(--color-secondary-dark-6); 659 + } 660 + 661 + .ui.dividing.header { 662 + border-bottom: 1px solid var(--color-secondary); 663 + } 664 + 665 + .ui.modal > .header { 666 + background: var(--color-secondary); 667 + color: #dbdbdb; 668 + } 669 + 670 + .ui.modal > .actions { 671 + background: var(--color-secondary); 672 + border-color: var(--color-secondary); 673 + } 674 + 675 + .ui.modal > .content { 676 + background: #2d2d2d; 677 + } 678 + 679 + .minicolors-panel { 680 + background: var(--color-secondary) !important; 681 + border-color: #6a737d !important; 682 + } 683 + 684 + /* invert emojis that are hard to read otherwise */ 685 + .emoji[aria-label="check mark"], 686 + .emoji[aria-label="currency exchange"], 687 + .emoji[aria-label="TOP arrow"], 688 + .emoji[aria-label="END arrow"], 689 + .emoji[aria-label="ON! arrow"], 690 + .emoji[aria-label="SOON arrow"], 691 + .emoji[aria-label="heavy dollar sign"], 692 + .emoji[aria-label="copyright"], 693 + .emoji[aria-label="registered"], 694 + .emoji[aria-label="trade mark"], 695 + .emoji[aria-label="multiply"], 696 + .emoji[aria-label="plus"], 697 + .emoji[aria-label="minus"], 698 + .emoji[aria-label="divide"], 699 + .emoji[aria-label="curly loop"], 700 + .emoji[aria-label="double curly loop"], 701 + .emoji[aria-label="wavy dash"], 702 + .emoji[aria-label="paw prints"], 703 + .emoji[aria-label="musical note"], 704 + .emoji[aria-label="musical notes"] { 705 + filter: invert(100%); 706 + } 707 + 708 + .edit-diff > div > .ui.table { 709 + border-left-color: var(--color-secondary) !important; 710 + border-right-color: var(--color-secondary) !important; 711 + } 712 + 713 + /* code mirror dark theme */ 714 + 715 + .CodeMirror { 716 + &.cm-s-default, 717 + &.cm-s-paper { 718 + .cm-property { 719 + color: #a0cc75; 720 + } 721 + 722 + .cm-header { 723 + color: #9daccc; 724 + } 725 + 726 + .cm-quote { 727 + color: #009900; 728 + } 729 + 730 + .cm-keyword { 731 + color: #cc8a61; 732 + } 733 + 734 + .cm-atom { 735 + color: #ef5e77; 736 + } 737 + 738 + .cm-number { 739 + color: #ff5656; 740 + } 741 + 742 + .cm-def { 743 + color: #e4e4e4; 744 + } 745 + 746 + .cm-variable-2 { 747 + color: #00bdbf; 748 + } 749 + 750 + .cm-variable-3 { 751 + color: #008855; 752 + } 753 + 754 + .cm-comment { 755 + color: #8e9ab3; 756 + } 757 + 758 + .cm-string { 759 + color: #a77272; 760 + } 761 + 762 + .cm-string-2 { 763 + color: #ff5500; 764 + } 765 + 766 + .cm-meta, 767 + .cm-qualifier { 768 + color: #ffb176; 769 + } 770 + 771 + .cm-builtin { 772 + color: #b7c951; 773 + } 774 + 775 + .cm-bracket { 776 + color: #999977; 777 + } 778 + 779 + .cm-tag { 780 + color: #f1d273; 781 + } 782 + 783 + .cm-attribute { 784 + color: #bfcc70; 785 + } 786 + 787 + .cm-hr { 788 + color: #999999; 789 + } 790 + 791 + .cm-url { 792 + color: #c5cfd0; 793 + } 794 + 795 + .cm-link { 796 + color: #d8c792; 797 + } 798 + 799 + .cm-error { 800 + /* color: #ff6e00; */ 801 + color: #dbdbeb; 802 + } 803 + } 804 + } 805 + 806 + footer .container .links > * { 807 + border-left-color: #888; 808 + } 809 + 810 + .repository.file.list #repo-files-table tbody .svg { 811 + color: var(--color-secondary-dark-6); 812 + } 813 + 814 + .repository.release #release-list > li .detail .dot { 815 + background-color: #4e5465; 816 + border-color: #2d2d2d; 817 + } 818 + 819 + .tribute-container { 820 + box-shadow: 0 .25rem .5rem rgba(0, 0, 0, .6); 821 + } 822 + 823 + .repository .repo-header .ui.huge.breadcrumb.repo-title .repo-header-icon .avatar { 824 + color: #060606; 825 + } 826 + 827 + img[src$="/img/matrix.svg"] { 828 + filter: invert(80%); 829 + } 830 + 831 + #git-graph-container li .time { 832 + color: #6a737d; 833 + } 834 + 835 + #git-graph-container.monochrome #rel-container .flow-group { 836 + stroke: dimgrey; 837 + fill: dimgrey; 838 + } 839 + 840 + #git-graph-container.monochrome #rel-container .flow-group.highlight { 841 + stroke: darkgrey; 842 + fill: darkgrey; 843 + } 844 + 845 + #git-graph-container:not(.monochrome) #rel-container .flow-group { 846 + &.flow-color-16-5 { 847 + stroke: #5543b1; 848 + fill: #5543b1; 849 + } 850 + } 851 + 852 + #git-graph-container:not(.monochrome) #rel-container .flow-group.highlight { 853 + &.flow-color-16-5 { 854 + stroke: #7058e6; 855 + fill: #7058e6; 856 + } 857 + } 858 + 859 + #git-graph-container #rev-list li.highlight.hover { 860 + background-color: rgba(255, 255, 255, .1); 861 + } 862 + 863 + #git-graph-container .ui.buttons button#flow-color-monochrome.ui.button { 864 + border-left-color: rgb(76, 80, 92); 865 + border-left-style: solid; 866 + border-left-width: 1px; 867 + } 868 + 869 + .mermaid-chart { 870 + filter: invert(84%) hue-rotate(180deg); 871 + } 872 + 873 + .is-loading::after { 874 + border-color: #4a4c58 #4a4c58 #d7d7da #d7d7da; 875 + } 876 + 877 + .markdown-block-error { 878 + border: 1px solid rgba(121, 71, 66, .5) !important; 879 + border-bottom: none !important; 880 + } 881 + 882 + .home .hero .svg { 883 + color: var(--color-primary); 884 + } 885 + 886 + .home a { 887 + color: var(--color-primary-light-1); 888 + } 889 + 890 + .ui.menu, .ui.vertical.menu { 891 + background: #070707; 892 + border-color: var(--color-secondary-dark-4); 893 + } 894 + 895 + .ui.menu.new-menu { 896 + background: #060606; 897 + } 898 + 899 + .ui.menu.new-menu:after { 900 + background: none; 901 + } 902 + 903 + .ui.checkbox label:active:before, .ui.checkbox label:hover:before, .ui.form input:not([type]):hover, .ui.form input[type=date]:hover, .ui.form input[type=datetime-local]:hover, .ui.form input[type=email]:hover, .ui.form input[type=file]:hover, .ui.form input[type=number]:hover, .ui.form input[type=password]:hover, .ui.form input[type=search]:hover, .ui.form input[type=tel]:hover, .ui.form input[type=text]:hover, .ui.form input[type=time]:hover, .ui.form input[type=url]:hover, .ui.form select:hover, .ui.form textarea:hover, .ui.input input:hover, .ui.radio.checkbox input:checked~label:before, .ui.radio.checkbox input:focus~label:before, .ui.radio.checkbox label:after, .ui.selection.dropdown:hover, input:hover, textarea:hover { 904 + background: var(--color-secondary-dark-3); 905 + } 906 + 907 + .ui.checkbox input:checked~label:before, .ui.checkbox input:not([type=radio]):indeterminate~label:before, .ui.checkbox label:before, .ui.form input:not([type]), .ui.form input[type=date], .ui.form input[type=datetime-local], .ui.form input[type=email], .ui.form input[type=file], .ui.form input[type=number], .ui.form input[type=password], .ui.form input[type=search], .ui.form input[type=tel], .ui.form input[type=text], .ui.form input[type=time], .ui.form input[type=url], .ui.form select, .ui.form textarea, .ui.input>input, .ui.selection.dropdown, input, textarea { 908 + background: var(--color-secondary-dark-2); 909 + } 910 + 911 + .ui.checkbox input:checked:focus~label:before, .ui.checkbox input:focus~label:before, .ui.checkbox input:not([type=radio]):indeterminate:focus~label:before, .ui.form input:not([type]):focus, .ui.form input[type=date]:focus, .ui.form input[type=datetime-local]:focus, .ui.form input[type=email]:focus, .ui.form input[type=file]:focus, .ui.form input[type=number]:focus, .ui.form input[type=password]:focus, .ui.form input[type=search]:focus, .ui.form input[type=tel]:focus, .ui.form input[type=text]:focus, .ui.form input[type=time]:focus, .ui.form input[type=url]:focus, .ui.form select:focus, .ui.form textarea:focus, .ui.input input:focus, .ui.radio.checkbox input:focus:checked~label:before, .ui.selection.dropdown:focus, input:focus, textarea:focus { 912 + background: var(--color-secondary-dark-3); 913 + } 914 + 915 + .ui.list .list>.item .description, .ui.list>.item .description { 916 + color: var(--color-secondary-dark-11); 917 + } 918 + 919 + .explore .navbar { 920 + background-color: var(--color-box-body)!important; 921 + } 922 + 923 + .repository .header-wrapper { 924 + background-color: var(--color-box-body); 925 + } 926 + 927 + .monaco-editor, .monaco-editor-background, .monaco-editor .inputarea.ime-input { 928 + background-color: #181818; 929 + } 930 + 931 + .ui.blue.label, .ui.blue.labels .label, .ui.primary.label, .ui.primary.labels .label { 932 + background-color: var(--color-secondary)!important; 933 + border-color: var(--color-primary-dark-2)!important; 934 + } 935 + 936 + .ui.blue.button, .ui.blue.buttons .button, .ui.primary.button, .ui.primary.buttons .button { 937 + background-color: #070707!important; 938 + } 939 + 940 + .ui.blue.button:hover, .ui.blue.buttons .button:hover, .ui.primary.button:hover, .ui.primary.buttons .button:hover { 941 + background-color: #1c1c1c!important; 942 + } 943 + 944 + .ui.green.labels .label, .ui.ui.ui.green.label { 945 + background-color: #1c1c1c!important; 946 + border-color: #21ba45!important; 947 + color: #fff; 948 + } 949 + 950 + .ui.red.labels .label, .ui.ui.ui.red.label { 951 + background-color: #1c1c1c!important; 952 + border-color: #db2828!important; 953 + color: #fff; 954 + } 955 + 956 + ::selection, ::-moz-selection { 957 + background: var(--color-grey); 958 + color: var(--color-secondary)!important; 959 + } 960 + 961 + .CodeMirror, .CodeMirror-selected, ::selection { 962 + background: var(--color-primary)!important; 963 + color: var(--color-secondary)!important; 964 + } 965 + 966 + .markup a, .ui.breadcrumb a { 967 + color: var(--color-primary-light-7); 968 + cursor: pointer; 969 + text-decoration: none; 970 + border-bottom: 1px solid var(--color-primary); 971 + transition-property: all 972 + } 973 + 974 + .markup a:hover, .ui.breadcrumb a:hover { 975 + color: #000; 976 + cursor: pointer; 977 + text-decoration: none; 978 + background: #fff; 979 + background-color: #fff 980 + } 981 + 982 + .markup .anchor { 983 + border-bottom: none 984 + } 985 + 986 + .markup .anchor:hover { 987 + color: var(--color-primary-light-7); 988 + border-bottom: none; 989 + background: var(--color-body); 990 + background-color: var(--color-body) 991 + } 992 + 993 + .mtk1, .mtk10 { 994 + color: #6D7178!important 995 + }
hosts/wolumonde/modules/forgejo.disabled/public/assets/fonts/comic.woff2

This is a binary file and will not be displayed.

hosts/wolumonde/modules/forgejo.disabled/public/assets/fonts/comicbd.woff2

This is a binary file and will not be displayed.

hosts/wolumonde/modules/forgejo.disabled/public/assets/fonts/comici.woff2

This is a binary file and will not be displayed.

hosts/wolumonde/modules/forgejo.disabled/public/assets/img/favicon.png

This is a binary file and will not be displayed.

hosts/wolumonde/modules/forgejo.disabled/public/assets/img/grrr.webp

This is a binary file and will not be displayed.

hosts/wolumonde/modules/forgejo.disabled/public/assets/img/logo.png

This is a binary file and will not be displayed.

hosts/wolumonde/modules/forgejo.disabled/public/assets/img/wecode.gif

This is a binary file and will not be displayed.

+44
hosts/wolumonde/modules/forgejo.disabled/templates/base/head.tmpl
··· 1 + <!DOCTYPE html> 2 + <html lang="{{ctx.Locale.Lang}}" data-theme="{{ThemeName .SignedUser}}"> 3 + <head> 4 + <meta name="viewport" content="width=device-width, initial-scale=1"> 5 + {{/* Display `- .Repository.FullName` only if `.Title` does not already start with that. */}} 6 + <title>{{if .Title}}{{.Title}} - {{end}}{{if and (.Repository.Name) (not (StringUtils.HasPrefix .Title .Repository.FullName))}}{{.Repository.FullName}} - {{end}}{{AppDisplayName}}</title> 7 + {{if .ManifestData}}<link rel="manifest" href="data:{{.ManifestData}}">{{end}} 8 + <meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}"> 9 + <meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}"> 10 + <meta name="keywords" content="{{MetaKeywords}}"> 11 + <meta name="referrer" content="no-referrer"> 12 + {{if .GoGetImport}} 13 + <meta name="go-import" content="{{.GoGetImport}} git {{.RepoCloneLink.HTTPS}}"> 14 + <meta name="go-source" content="{{.GoGetImport}} _ {{.GoDocDirectory}} {{.GoDocFile}}"> 15 + {{end}} 16 + {{if and .EnableFeed .FeedURL}} 17 + <link rel="alternate" type="application/atom+xml" title="" href="{{.FeedURL}}.atom"> 18 + <link rel="alternate" type="application/rss+xml" title="" href="{{.FeedURL}}.rss"> 19 + {{end}} 20 + <link rel="alternate icon" href="{{AssetUrlPrefix}}/img/favicon.png" type="image/png"> 21 + {{template "base/head_script" .}} 22 + {{template "shared/user/mention_highlight" .}} 23 + {{template "base/head_opengraph" .}} 24 + {{template "base/head_style" .}} 25 + {{template "custom/header" .}} 26 + </head> 27 + <body hx-headers='{"x-csrf-token": "{{.CsrfToken}}"}' hx-swap="outerHTML" hx-ext="morph" hx-push-url="false"> 28 + {{template "custom/body_outer_pre" .}} 29 + 30 + <div class="full height"> 31 + <noscript>{{ctx.Locale.Tr "enable_javascript"}}</noscript> 32 + 33 + {{template "custom/body_inner_pre" .}} 34 + 35 + {{if not .PageIsInstall}} 36 + {{template "base/head_navbar" .}} 37 + {{end}} 38 + 39 + {{if false}} 40 + {{/* to make html structure "likely" complete to prevent IDE warnings */}} 41 + </div> 42 + </body> 43 + </html> 44 + {{end}}
+207
hosts/wolumonde/modules/forgejo.disabled/templates/base/head_navbar.tmpl
··· 1 + {{$notificationUnreadCount := 0}} 2 + {{if and .IsSigned .NotificationUnreadCount}} 3 + {{$notificationUnreadCount = call .NotificationUnreadCount}} 4 + {{end}} 5 + 6 + <nav id="navbar" aria-label="{{ctx.Locale.Tr "aria.navbar"}}"> 7 + <div class="navbar-left ui secondary menu"> 8 + <!-- the logo --> 9 + <a class="item" id="navbar-logo" href="{{AppSubUrl}}/" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home"}}{{end}}"> 10 + <img width="30" height="30" src="{{AssetUrlPrefix}}/img/logo.png" alt="{{ctx.Locale.Tr "logo"}}" aria-hidden="true"> 11 + </a> 12 + 13 + <!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column --> 14 + <div class="ui secondary menu item navbar-mobile-right only-mobile"> 15 + {{if .IsSigned}} 16 + <a id="mobile-notifications-icon" class="item tw-w-auto tw-p-2" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}" aria-label="{{ctx.Locale.Tr "notifications"}}"> 17 + <div class="tw-relative"> 18 + {{svg "octicon-bell"}} 19 + <span class="notification_count{{if not $notificationUnreadCount}} tw-hidden{{end}}">{{$notificationUnreadCount}}</span> 20 + </div> 21 + </a> 22 + {{end}} 23 + <button class="item tw-w-auto ui icon mini button tw-p-2 tw-m-0" id="navbar-expand-toggle" aria-label="{{ctx.Locale.Tr "toggle_menu"}}">{{svg "octicon-three-bars"}}</button> 24 + </div> 25 + 26 + <!-- navbar links non-mobile --> 27 + {{if and .IsSigned .MustChangePassword}} 28 + {{/* No links */}} 29 + {{else if .IsSigned}} 30 + {{if not .UnitIssuesGlobalDisabled}} 31 + <a class="item{{if .PageIsIssues}} active{{end}}" href="{{AppSubUrl}}/issues">{{ctx.Locale.Tr "issues"}}</a> 32 + {{end}} 33 + {{if not .UnitPullsGlobalDisabled}} 34 + <a class="item{{if .PageIsPulls}} active{{end}}" href="{{AppSubUrl}}/pulls">{{ctx.Locale.Tr "pull_requests"}}</a> 35 + {{end}} 36 + {{if not (and .UnitIssuesGlobalDisabled .UnitPullsGlobalDisabled)}} 37 + {{if .ShowMilestonesDashboardPage}} 38 + <a class="item{{if .PageIsMilestonesDashboard}} active{{end}}" href="{{AppSubUrl}}/milestones">{{ctx.Locale.Tr "milestones"}}</a> 39 + {{end}} 40 + {{end}} 41 + <a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/repos">{{ctx.Locale.Tr "explore"}}</a> 42 + {{else if .IsLandingPageOrganizations}} 43 + <a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/organizations">{{ctx.Locale.Tr "explore"}}</a> 44 + {{else}} 45 + <a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/repos">{{ctx.Locale.Tr "explore"}}</a> 46 + {{end}} 47 + 48 + {{template "custom/extra_links" .}} 49 + 50 + {{if not .IsSigned}} 51 + <a class="item" target="_blank" rel="noopener noreferrer" href="https://forgejo.org/docs/latest/">{{ctx.Locale.Tr "help"}}</a> 52 + {{end}} 53 + </div> 54 + 55 + <!-- the full dropdown menus --> 56 + <div class="navbar-right ui secondary menu"> 57 + {{if and .IsSigned .MustChangePassword}} 58 + <div class="ui dropdown jump item" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}"> 59 + <span class="text tw-flex tw-items-center"> 60 + {{ctx.AvatarUtils.Avatar .SignedUser 24 "tw-mr-1"}} 61 + <span class="only-mobile tw-ml-2">{{.SignedUser.Name}}</span> 62 + <span class="not-mobile">{{svg "octicon-triangle-down"}}</span> 63 + </span> 64 + <div class="menu user-menu"> 65 + <div class="ui header"> 66 + {{ctx.Locale.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong> 67 + </div> 68 + 69 + <div class="divider"></div> 70 + <a class="item link-action" href data-url="{{AppSubUrl}}/user/logout"> 71 + {{svg "octicon-sign-out"}} 72 + {{ctx.Locale.Tr "sign_out"}} 73 + </a> 74 + </div><!-- end content avatar menu --> 75 + </div><!-- end dropdown avatar menu --> 76 + {{else if .IsSigned}} 77 + {{if EnableTimetracking}} 78 + <a class="active-stopwatch-trigger item tw-mx-0{{if not .ActiveStopwatch}} tw-hidden{{end}}" href="{{.ActiveStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}"> 79 + <div class="tw-relative"> 80 + {{svg "octicon-stopwatch"}} 81 + <span class="header-stopwatch-dot"></span> 82 + </div> 83 + <span class="only-mobile tw-ml-2">{{ctx.Locale.Tr "active_stopwatch"}}</span> 84 + </a> 85 + <div class="active-stopwatch-popup item tippy-target tw-p-2"> 86 + <div class="tw-flex tw-items-center"> 87 + <a class="stopwatch-link tw-flex tw-items-center" href="{{.ActiveStopwatch.IssueLink}}"> 88 + {{svg "octicon-issue-opened" 16 "tw-mr-2"}} 89 + <span class="stopwatch-issue">{{.ActiveStopwatch.RepoSlug}}#{{.ActiveStopwatch.IssueIndex}}</span> 90 + <span class="ui primary label stopwatch-time tw-my-0 tw-mx-4" data-seconds="{{.ActiveStopwatch.Seconds}}"> 91 + {{if .ActiveStopwatch}}{{Sec2Time .ActiveStopwatch.Seconds}}{{end}} 92 + </span> 93 + </a> 94 + <form class="stopwatch-commit" method="post" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/toggle"> 95 + {{.CsrfTokenHtml}} 96 + <button 97 + type="submit" 98 + class="ui button mini compact basic icon" 99 + data-tooltip-content="{{ctx.Locale.Tr "repo.issues.stop_tracking"}}" 100 + >{{svg "octicon-square-fill"}}</button> 101 + </form> 102 + <form class="stopwatch-cancel" method="post" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/cancel"> 103 + {{.CsrfTokenHtml}} 104 + <button 105 + type="submit" 106 + class="ui button mini compact basic icon" 107 + data-tooltip-content="{{ctx.Locale.Tr "repo.issues.cancel_tracking"}}" 108 + >{{svg "octicon-trash"}}</button> 109 + </form> 110 + </div> 111 + </div> 112 + {{end}} 113 + 114 + <a class="item not-mobile tw-mx-0" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}" aria-label="{{ctx.Locale.Tr "notifications"}}"> 115 + <div class="tw-relative"> 116 + {{svg "octicon-bell"}} 117 + <span class="notification_count{{if not $notificationUnreadCount}} tw-hidden{{end}}">{{$notificationUnreadCount}}</span> 118 + </div> 119 + </a> 120 + 121 + <div class="ui dropdown jump item tw-mx-0 tw-pr-2" data-tooltip-content="{{ctx.Locale.Tr "create_new"}}"> 122 + <span class="text"> 123 + {{svg "octicon-plus"}} 124 + <span class="not-mobile">{{svg "octicon-triangle-down"}}</span> 125 + <span class="only-mobile">{{ctx.Locale.Tr "create_new"}}</span> 126 + </span> 127 + <div class="menu"> 128 + <a class="item" href="{{AppSubUrl}}/repo/create"> 129 + {{svg "octicon-plus"}} {{ctx.Locale.Tr "new_repo.link"}} 130 + </a> 131 + {{if not .DisableMigrations}} 132 + <a class="item" href="{{AppSubUrl}}/repo/migrate"> 133 + {{svg "octicon-repo-push"}} {{ctx.Locale.Tr "new_migrate.link"}} 134 + </a> 135 + {{end}} 136 + {{if .SignedUser.CanCreateOrganization}} 137 + <a class="item" href="{{AppSubUrl}}/org/create"> 138 + {{svg "octicon-organization"}} {{ctx.Locale.Tr "new_org.link"}} 139 + </a> 140 + {{end}} 141 + </div><!-- end content create new menu --> 142 + </div><!-- end dropdown menu create new --> 143 + 144 + <div class="ui dropdown jump item tw-mx-0 tw-pr-2" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}"> 145 + <span class="text tw-flex tw-items-center"> 146 + {{ctx.AvatarUtils.Avatar .SignedUser 24 "tw-mr-1"}} 147 + <span class="only-mobile tw-ml-2">{{.SignedUser.Name}}</span> 148 + <span class="not-mobile">{{svg "octicon-triangle-down"}}</span> 149 + </span> 150 + <div class="menu user-menu"> 151 + <div class="ui header"> 152 + {{ctx.Locale.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong> 153 + </div> 154 + 155 + <div class="divider"></div> 156 + <a class="item" href="{{.SignedUser.HomeLink}}"> 157 + {{svg "octicon-person"}} 158 + {{ctx.Locale.Tr "your_profile"}} 159 + </a> 160 + {{if not .DisableStars}} 161 + <a class="item" href="{{.SignedUser.HomeLink}}?tab=stars"> 162 + {{svg "octicon-star"}} 163 + {{ctx.Locale.Tr "your_starred"}} 164 + </a> 165 + {{end}} 166 + <a class="item" href="{{AppSubUrl}}/notifications/subscriptions"> 167 + {{svg "octicon-bell"}} 168 + {{ctx.Locale.Tr "notification.subscriptions"}} 169 + </a> 170 + <a class="{{if .PageIsUserSettings}}active {{end}}item" href="{{AppSubUrl}}/user/settings"> 171 + {{svg "octicon-tools"}} 172 + {{ctx.Locale.Tr "your_settings"}} 173 + </a> 174 + <a class="item" target="_blank" rel="noopener noreferrer" href="https://forgejo.org/docs/latest/"> 175 + {{svg "octicon-question"}} 176 + {{ctx.Locale.Tr "help"}} 177 + </a> 178 + {{if .IsAdmin}} 179 + <div class="divider"></div> 180 + 181 + <a class="{{if .PageIsAdmin}}active {{end}}item" href="{{AppSubUrl}}/admin"> 182 + {{svg "octicon-server"}} 183 + {{ctx.Locale.Tr "admin_panel"}} 184 + </a> 185 + {{end}} 186 + 187 + <div class="divider"></div> 188 + <a class="item link-action" href data-url="{{AppSubUrl}}/user/logout"> 189 + {{svg "octicon-sign-out"}} 190 + {{ctx.Locale.Tr "sign_out"}} 191 + </a> 192 + </div><!-- end content avatar menu --> 193 + </div><!-- end dropdown avatar menu --> 194 + {{else}} 195 + {{if .ShowRegistrationButton}} 196 + <a class="item{{if .PageIsSignUp}} active{{end}}" href="{{AppSubUrl}}/user/sign_up"> 197 + {{svg "octicon-person" 16 "tw-mr-1"}} 198 + <span>{{ctx.Locale.Tr "register"}}</span> 199 + </a> 200 + {{end}} 201 + <a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login{{if not .PageIsSignIn}}?redirect_to={{.CurrentURL}}{{end}}"> 202 + {{svg "octicon-sign-in" 16 "tw-mr-1"}} 203 + <span>{{ctx.Locale.Tr "sign_in"}}</span> 204 + </a> 205 + {{end}} 206 + </div><!-- end full right menu --> 207 + </nav>
+14
hosts/wolumonde/modules/forgejo.disabled/templates/home.tmpl
··· 1 + {{template "base/head" .}} 2 + <div role="main" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home"}}{{end}}" class="page-content home"> 3 + <div class="tw-mb-8 tw-px-8"> 4 + <div class="center"> 5 + <img class="logo" width="220" height="220" src="https://git.gaze.systems/assets/img/grrr.webp" alt="i hate software" title="i hate software"> 6 + <div class="hero"> 7 + <h2>software</h2> 8 + </div> 9 + <div style="height: 200vh;"></div> 10 + <img class="logo" width="220" height="220" src="https://git.gaze.systems/assets/img/wecode.gif" alt="forgejo. beyond coding. we forge. but lowtiergod" title="skies ur rina"> 11 + </div> 12 + </div> 13 + </div> 14 + {{template "base/footer" .}}
-98
hosts/wolumonde/modules/forgejo.nix/default.nix
··· 1 - { 2 - pkgs, 3 - lib, 4 - config, 5 - ... 6 - }: 7 - let 8 - forgejoCfg = config.services.forgejo.settings; 9 - anubisCfg = config.services.anubis.instances."forgejo".settings; 10 - in 11 - { 12 - services.forgejo = { 13 - enable = true; 14 - package = pkgs.forgejo; 15 - lfs.enable = true; 16 - settings = { 17 - DEFAULT.APP_NAME = "awruff ^^"; 18 - server = { 19 - DOMAIN = "git.gaze.systems"; 20 - ROOT_URL = "https://git.gaze.systems/"; 21 - HTTP_PORT = 9008; 22 - }; 23 - service = { 24 - DISABLE_REGISTRATION = true; 25 - }; 26 - security.REVERSE_PROXY_TRUSTED_PROXIES = "127.0.0.0/8,::1/128"; 27 - session.COOKIE_SECURE = true; 28 - ui = { 29 - DEFAULT_SHOW_FULL_NAME = true; 30 - DEFAULT_THEME = "edge-dark"; 31 - THEMES = "edge-dark,forgejo-dark"; 32 - THEME_COLOR_META_TAG = "#333644"; 33 - }; 34 - "ui.meta" = { 35 - DESCRIPTION = "nyan? arf!!!! :3"; 36 - }; 37 - metrics.ENABLED = true; 38 - }; 39 - }; 40 - 41 - # copy custom data stuff 42 - systemd.services.forgejo.preStart = 43 - let 44 - customDir = "${config.services.forgejo.stateDir}/custom"; 45 - getCustomDir = name: "${customDir}/${name}"; 46 - makeCopyCommand = dir: '' 47 - mkdir -p ${customDir} 48 - rm -rf ${getCustomDir dir} 49 - cp -r --no-preserve=mode,ownership ${./${dir}} ${getCustomDir dir} 50 - ''; 51 - in 52 - lib.concatMapStrings makeCopyCommand [ 53 - "templates" 54 - "public" 55 - ]; 56 - 57 - security.acme.certs."gaze.systems".extraDomainNames = [ forgejoCfg.server.DOMAIN ]; 58 - services.nginx.virtualHosts.${forgejoCfg.server.DOMAIN} = { 59 - useACMEHost = "gaze.systems"; 60 - forceSSL = true; 61 - quic = true; 62 - kTLS = true; 63 - # disallow metrics for public 64 - locations."/metrics".return = "403"; 65 - locations."/" = { 66 - extraConfig = '' 67 - client_max_body_size 1000m; 68 - ''; 69 - proxyPass = "http://localhost${anubisCfg.BIND}"; 70 - }; 71 - }; 72 - 73 - services.anubis.instances."forgejo".settings = { 74 - BIND = ":6293"; 75 - BIND_NETWORK = "tcp"; 76 - METRICS_BIND = ":9090"; 77 - METRICS_BIND_NETWORK = "tcp"; 78 - TARGET = "http://localhost:${toString forgejoCfg.server.HTTP_PORT}"; 79 - WEBMASTER_EMAIL = "90008@gaze.systems"; 80 - SERVE_ROBOTS_TXT = true; 81 - OG_PASSTHROUGH = true; 82 - DIFFICULTY = 4; 83 - }; 84 - 85 - # scrape forgejo metrics 86 - services.victoriametrics.prometheusConfig.scrape_configs = [ 87 - { 88 - job_name = "forgejo"; 89 - metrics_path = "/metrics"; 90 - static_configs = [ { targets = [ "localhost:${toString forgejoCfg.server.HTTP_PORT}" ]; } ]; 91 - } 92 - { 93 - job_name = "anubis_forgejo"; 94 - metrics_path = "/metrics"; 95 - static_configs = [ { targets = [ "localhost${anubisCfg.METRICS_BIND}" ]; } ]; 96 - } 97 - ]; 98 - }
-995
hosts/wolumonde/modules/forgejo.nix/public/assets/css/theme-edge-dark.css
··· 1 - @import "https://cdn.jsdelivr.net/npm/comic-mono@0.0.1/index.css"; 2 - @font-face { 3 - font-family: 'Comic Sans'; 4 - font-style: normal; 5 - font-display: swap; 6 - src: url('../fonts/comic.woff2') format('woff2'); 7 - } 8 - @font-face { 9 - font-family: 'Comic Sans'; 10 - font-style: normal; 11 - font-weight: bold; 12 - font-display: swap; 13 - src: url('../fonts/comicbd.woff2') format('woff2'); 14 - } 15 - @font-face { 16 - font-family: 'Comic Sans'; 17 - font-style: italic; 18 - font-display: swap; 19 - src: url('../fonts/comici.woff2') format('woff2'); 20 - } 21 - :root { 22 - --fonts-proportional: "Comic Sans", sans-serif !important; 23 - --fonts-monospace: "Comic Mono", monospace !important; 24 - } 25 - .chroma .hl{background-color:#3f424d}.chroma .ln,.chroma .lnt{color:#7f7f7f} 26 - 27 - .chroma .k{color:#f63} 28 - 29 - .chroma .kc{color:#fa1} 30 - 31 - .chroma .kd{color:#9daccc} 32 - 33 - .chroma .kn{color:#fa1} 34 - 35 - .chroma .kp{color:#5f8700} 36 - 37 - .chroma .kr{color:#f63} 38 - 39 - .chroma .kt{color:#9daccc} 40 - 41 - .chroma .na{color:#8a8a8a} 42 - 43 - .chroma .bp,.chroma .nb{color:#9daccc} 44 - 45 - .chroma .nc,.chroma .no{color:#fa1} 46 - 47 - .chroma .nd{color:#9daccc} 48 - 49 - .chroma .ni{color:#fa1} 50 - 51 - .chroma .ne{color:#af8700} 52 - 53 - .chroma .nf{color:#9daccc} 54 - 55 - .chroma .nl,.chroma .nn{color:#fa1} 56 - 57 - .chroma .nt,.chroma .nv,.chroma .nx{color:#9daccc} 58 - 59 - .chroma .vc{color:#f81} 60 - 61 - .chroma .vg,.chroma .vi{color:#fa1} 62 - 63 - .chroma .s,.chroma .sa{color:#1af} 64 - 65 - .chroma .sb{color:#a0cc75} 66 - 67 - .chroma .dl,.chroma .sc{color:#1af} 68 - 69 - .chroma .sd{color:#6a737d} 70 - 71 - .chroma .s2{color:#a0cc75} 72 - 73 - .chroma .se{color:#f63} 74 - 75 - .chroma .sh{color:#1af} 76 - 77 - .chroma .si,.chroma .sx{color:#fa1} 78 - 79 - .chroma .sr{color:#97c} 80 - 81 - .chroma .s1{color:#a0cc75} 82 - 83 - .chroma .ss{color:#fa1} 84 - 85 - .chroma .il,.chroma .m,.chroma .mb,.chroma .mf,.chroma .mh,.chroma .mi,.chroma .mo{color:#1af} 86 - 87 - .chroma .o{color:#f63} 88 - 89 - .chroma .ow{color:#5f8700} 90 - 91 - .chroma .c,.chroma .c1,.chroma .ch,.chroma .cm{color:#6a737d} 92 - 93 - .chroma .cs{color:#637d} 94 - 95 - .chroma .cp,.chroma .cpf{color:#fc6} 96 - 97 - .chroma .gd{color:#fff;background-color:#5f3737} 98 - 99 - .chroma .ge{color:#ef5} 100 - 101 - .chroma .gr{color:#f33} 102 - 103 - .chroma .gh{color:#fa1} 104 - 105 - .chroma .gi{color:#fff;background-color:#3a523a} 106 - 107 - .chroma .go{color:#888888} 108 - 109 - .chroma .gp{color:#555555} 110 - 111 - .chroma .gu{color:#9daccc} 112 - 113 - .chroma .gt{color:#f63} 114 - 115 - .chroma .w{color:#bbbbbb} 116 - 117 - :root { 118 - --color-primary: #ccc; 119 - --color-primary-dark-1: #c5c5c5; 120 - --color-primary-dark-2: #bebebe; 121 - --color-primary-dark-3: #b7b7b7; 122 - --color-primary-dark-4: #b0b0b0; 123 - --color-primary-dark-5: #a9a9a9; 124 - --color-primary-dark-6: #a2a2a2; 125 - --color-primary-dark-7: #9b9b9b; 126 - --color-primary-light-1: #d3d3d3; 127 - --color-primary-light-2: #d9d9d9; 128 - --color-primary-light-3: #e0e0e0; 129 - --color-primary-light-4: #e7e7e7; 130 - --color-primary-light-5: #eeeeee; 131 - --color-primary-light-6: #f5f5f5; 132 - --color-primary-light-7: #fff; 133 - --color-primary-alpha-10: #afb0b119; 134 - --color-primary-alpha-20: #afb0b133; 135 - --color-primary-alpha-30: #afb0b14b; 136 - --color-primary-alpha-40: #afb0b166; 137 - --color-primary-alpha-50: #afb0b180; 138 - --color-primary-alpha-60: #afb0b199; 139 - --color-primary-alpha-70: #afb0b1b3; 140 - --color-primary-alpha-80: #afb0b1cc; 141 - --color-primary-alpha-90: #afb0b1e1; 142 - --color-secondary: #000; 143 - --color-secondary-dark-1: #141414; 144 - --color-secondary-dark-2: #0b0c0e; 145 - --color-secondary-dark-3: #17181c; 146 - --color-secondary-dark-4: #22242a; 147 - --color-secondary-dark-5: #2d3139; 148 - --color-secondary-dark-6: #393d47; 149 - --color-secondary-dark-7: #444955; 150 - --color-secondary-dark-7: #4f5563; 151 - --color-secondary-dark-8: #5b6171; 152 - --color-secondary-dark-8: #666d7f; 153 - --color-secondary-dark-9: #71798e; 154 - --color-secondary-dark-10: #808799; 155 - --color-secondary-dark-11: #8e94a4; 156 - --color-secondary-light-1: #373b46; 157 - --color-secondary-light-2: #292c34; 158 - --color-secondary-light-3: #1c1e23; 159 - --color-secondary-light-4: #0e0f11; 160 - --color-secondary-alpha-10: #45454519; 161 - --color-secondary-alpha-20: #45454533; 162 - --color-secondary-alpha-30: #4545454b; 163 - --color-secondary-alpha-40: #45454566; 164 - --color-secondary-alpha-50: #45454580; 165 - --color-secondary-alpha-60: #45454599; 166 - --color-secondary-alpha-70: #454545b3; 167 - --color-secondary-alpha-80: #454545cc; 168 - --color-secondary-alpha-90: #454545e1; 169 - /* colors */ 170 - --color-red: #db2828; 171 - --color-orange: #ff6600; 172 - --color-yellow: #ffff99; 173 - --color-olive: #abc11a; 174 - --color-green: #199717; 175 - --color-teal: #01fed4; 176 - --color-blue: #226ac9; 177 - --color-violet: #6435c9; 178 - --color-purple: #a333c8; 179 - --color-pink: #e03997; 180 - --color-brown: #a5673f; 181 - --color-grey: #767a85; 182 - --color-black: #1e222e; 183 - --color-gold: #a1882b; 184 - --color-white: #ffffff; 185 - --color-diff-removed-word-bg: #6f3333; 186 - --color-diff-added-word-bg: #3c653c; 187 - --color-diff-removed-row-bg: #3c2626; 188 - --color-diff-added-row-bg: #283e2d; 189 - --color-diff-removed-row-border: #634343; 190 - --color-diff-added-row-border: #314a37; 191 - --color-diff-inactive: #353846; 192 - /* target-based colors */ 193 - --color-body: #000; 194 - --color-box-header: #000; 195 - --color-box-body: #070707; 196 - --color-text-dark: #dee1e8; 197 - --color-text: #c7cad1; 198 - --color-text-light: #acb0b9; 199 - --color-text-light-2: #8a8e99; 200 - --color-text-light-3: #707687; 201 - --color-footer: #000; 202 - --color-timeline: #4c525e; 203 - --color-input-text: #d5dbe6; 204 - --color-input-background: #000; 205 - --color-input-border: #454545; 206 - --color-input-border-hover: #4e5465; 207 - --color-navbar: #060606; 208 - --color-light: #00000028; 209 - --color-light-border: #ffffff28; 210 - --color-hover: #ffffff10; 211 - --color-active: #25272d; 212 - --color-menu: #060606; 213 - --color-card: #060606; 214 - --color-markdown-table-row: #ffffff06; 215 - --color-markdown-code-block: #121314; 216 - --color-button: #070707; 217 - --color-code-bg: #060606; 218 - --color-shadow: #00000060; 219 - --color-secondary-bg: #060606; 220 - --color-text-focus: #fff; 221 - --color-expand-button: #3c404d; 222 - --color-placeholder-text: #6a737d; 223 - --color-editor-line-highlight: var(--color-primary-light-5); 224 - --color-project-board-bg: var(--color-secondary-light-2); 225 - --color-nav-bg: var(--color-body); 226 - --color-nav-hover-bg: var(--color-hover); 227 - } 228 - 229 - ::-webkit-calendar-picker-indicator { 230 - filter: invert(.8); 231 - } 232 - 233 - .ui.horizontal.segments > .segment { 234 - background-color: #2d2d2d; 235 - } 236 - 237 - .repository .segment.reactions .ui.label.basic.blue { 238 - background: var(--color-primary-alpha-20) !important; 239 - } 240 - 241 - [data-tooltip]::before, 242 - [data-tooltip]::after { 243 - background: #1b1c1d !important; /* .ui.inverted.popup */ 244 - border-color: #1b1c1d !important; /* .ui.inverted.popup */ 245 - color: #dbdbdb !important; 246 - } 247 - 248 - [data-tooltip]::before { 249 - box-shadow: 1px 1px 0 0 #1b1c1d !important; /* .ui.inverted.popup */ 250 - } 251 - 252 - .ui.green.progress .bar { 253 - background-color: #848b84; 254 - } 255 - 256 - .ui.progress.success .bar { 257 - background-color: #8fa37b !important; 258 - } 259 - 260 - .following.bar.light { 261 - background: var(--color-body); 262 - border-color: var(--color-secondary-alpha-40); 263 - } 264 - 265 - .following.bar .top.menu a.item:hover { 266 - color: #fff; 267 - } 268 - 269 - .feeds .list ul li.private { 270 - background: #25272d; 271 - } 272 - 273 - .ui.link.list .item, 274 - .ui.link.list a.item, 275 - .ui.link.list .item a:not(.ui) { 276 - color: #dbdbdb; 277 - } 278 - 279 - .ui.red.label, 280 - .ui.red.labels .label { 281 - background-color: #7d3434 !important; 282 - border-color: #8a2121 !important; 283 - } 284 - 285 - .ui.yellow.label, 286 - .ui.yellow.labels .label { 287 - border-color: #664d02 !important; 288 - background-color: #936e00 !important; 289 - } 290 - 291 - .ui.accordion .title:not(.ui) { 292 - color: #dbdbdb; 293 - } 294 - 295 - .ui.green.label, 296 - .ui.green.labels .label, 297 - .ui.basic.green.label { 298 - background-color: #53682c !important; 299 - border-color: #53682c !important; 300 - } 301 - 302 - .ui.green.labels a.label:hover, 303 - .ui.basic.green.labels a.label:hover, 304 - a.ui.ui.ui.green.label:hover, 305 - a.ui.basic.green.label:hover { 306 - background-color: #657a3e !important; 307 - border-color: #657a3e !important; 308 - color: #fff !important; 309 - } 310 - 311 - .ui.divider:not(.vertical):not(.horizontal) { 312 - border-bottom-color: var(--color-secondary); 313 - border-top-color: transparent; 314 - } 315 - 316 - .form .help { 317 - color: #7f8699; 318 - } 319 - 320 - .ui .text.light.grey { 321 - color: #7f8699 !important; 322 - } 323 - 324 - .ui.form .fields.error .field textarea, 325 - .ui.form .fields.error .field select, 326 - .ui.form .fields.error .field input:not([type]), 327 - .ui.form .fields.error .field input[type="date"], 328 - .ui.form .fields.error .field input[type="datetime-local"], 329 - .ui.form .fields.error .field input[type="email"], 330 - .ui.form .fields.error .field input[type="number"], 331 - .ui.form .fields.error .field input[type="password"], 332 - .ui.form .fields.error .field input[type="search"], 333 - .ui.form .fields.error .field input[type="tel"], 334 - .ui.form .fields.error .field input[type="time"], 335 - .ui.form .fields.error .field input[type="text"], 336 - .ui.form .fields.error .field input[type="file"], 337 - .ui.form .fields.error .field input[type="url"], 338 - .ui.form .field.error textarea, 339 - .ui.form .field.error select, 340 - .ui.form .field.error input:not([type]), 341 - .ui.form .field.error input[type="date"], 342 - .ui.form .field.error input[type="datetime-local"], 343 - .ui.form .field.error input[type="email"], 344 - .ui.form .field.error input[type="number"], 345 - .ui.form .field.error input[type="password"], 346 - .ui.form .field.error input[type="search"], 347 - .ui.form .field.error input[type="tel"], 348 - .ui.form .field.error input[type="time"], 349 - .ui.form .field.error input[type="text"], 350 - .ui.form .field.error input[type="file"], 351 - .ui.form .field.error input[type="url"] { 352 - background-color: #522; 353 - border: 1px solid #7d3434; 354 - color: #f9cbcb; 355 - } 356 - 357 - .ui.form .field.error select:focus, 358 - .ui.form .field.error input:not([type]):focus, 359 - .ui.form .field.error input[type="date"]:focus, 360 - .ui.form .field.error input[type="datetime-local"]:focus, 361 - .ui.form .field.error input[type="email"]:focus, 362 - .ui.form .field.error input[type="number"]:focus, 363 - .ui.form .field.error input[type="password"]:focus, 364 - .ui.form .field.error input[type="search"]:focus, 365 - .ui.form .field.error input[type="tel"]:focus, 366 - .ui.form .field.error input[type="time"]:focus, 367 - .ui.form .field.error input[type="text"]:focus, 368 - .ui.form .field.error input[type="file"]:focus, 369 - .ui.form .field.error input[type="url"]:focus { 370 - background-color: #522; 371 - border: 1px solid #a04141; 372 - color: #f9cbcb; 373 - } 374 - 375 - .ui.green.button, 376 - .ui.green.buttons .button { 377 - background-color: #070707; 378 - } 379 - 380 - .ui.green.button:hover, 381 - .ui.green.buttons .button:hover { 382 - background-color: #141414; 383 - } 384 - 385 - .ui.green.button:active, 386 - .ui.green.buttons .button:active { 387 - background-color: #070707; 388 - } 389 - 390 - .ui.search > .results { 391 - background: #2d2d2d; 392 - border-color: var(--color-secondary); 393 - } 394 - 395 - .ui.search > .results .result:hover, 396 - .ui.category.search > .results .category .result:hover { 397 - background: var(--color-secondary); 398 - } 399 - 400 - .ui.search > .results .result .title { 401 - color: #dbdbdb; 402 - } 403 - 404 - .ui.table > thead > tr > th { 405 - background: var(--color-secondary); 406 - color: #dbdbdb !important; 407 - } 408 - 409 - .repository.file.list #repo-files-table tr { 410 - background: #070707; 411 - } 412 - 413 - .repository.file.list #repo-files-table tr:hover { 414 - background-color: #2d2d2d !important; 415 - } 416 - 417 - .repository.file.editor.edit, 418 - .repository.wiki.new .CodeMirror { 419 - .editor-preview, 420 - .editor-preview-side, 421 - & + .editor-preview-side { 422 - background: #25272d; 423 - 424 - .markdown:not(code).ui.segment { 425 - border-width: 0; 426 - } 427 - } 428 - } 429 - 430 - .overflow.menu .items .item { 431 - color: #9d9d9d; 432 - } 433 - 434 - .overflow.menu .items .item:hover { 435 - color: #dbdbdb; 436 - } 437 - 438 - .ui.list > .item > .content { 439 - color: var(--color-secondary-dark-6) !important; 440 - } 441 - 442 - .ui.active.button:active, 443 - .ui.button:active, 444 - .ui.button:focus, 445 - .ui.active.button { 446 - background-color: #2e3e4e; 447 - color: #dbdbdb; 448 - } 449 - 450 - .ui.active.button:hover { 451 - background-color: #475e75; 452 - color: #dbdbdb; 453 - } 454 - 455 - .repository .navbar .active.item, 456 - .repository .navbar .active.item:hover { 457 - border-color: transparent !important; 458 - } 459 - 460 - .ui .info.segment.top { 461 - background-color: var(--color-secondary) !important; 462 - } 463 - 464 - .repository .diff-stats li { 465 - border-color: var(--color-secondary); 466 - } 467 - 468 - .tag-code, 469 - .tag-code td { 470 - background: #25272d !important; 471 - 472 - } 473 - .tag-code td.lines-num { 474 - background-color: #3a3e4c !important; 475 - } 476 - 477 - .tag-code td.lines-type-marker, 478 - td.blob-hunk { 479 - color: #dbdbdb !important; 480 - } 481 - 482 - .ui.attached.info.message, 483 - .ui.info.message { 484 - box-shadow: 0 0 0 1px #4b5e71 inset, 0 0 0 0 transparent; 485 - } 486 - 487 - .ui.bottom.attached.message { 488 - background-color: #2c662d; 489 - color: #ab6363; 490 - } 491 - 492 - .ui.bottom.attached.message .pull-right { 493 - color: #ab6363; 494 - } 495 - 496 - .ui.info.message { 497 - background-color: #2c3b4a; 498 - color: #9ebcc5; 499 - } 500 - 501 - .ui .warning.header, 502 - .ui.warning.message { 503 - background-color: #542 !important; 504 - border-color: #ec8; 505 - } 506 - 507 - .ui.warning.message { 508 - color: #ec8; 509 - box-shadow: 0 0 0 1px #ec8; 510 - } 511 - 512 - .ui.warning.segment { 513 - border-color: #ec8; 514 - } 515 - 516 - .ui.red.message, 517 - .ui.error.message { 518 - background-color: #522; 519 - color: #f9cbcb; 520 - box-shadow: 0 0 0 1px #a04141 inset; 521 - } 522 - 523 - .ui .error.header, 524 - .ui.error.message { 525 - background-color: #522 !important; 526 - border-color: #a04141; 527 - } 528 - 529 - .ui.error.segment { 530 - border-color: #a04141; 531 - } 532 - 533 - .ui.red.button, 534 - .ui.red.buttons .button { 535 - background-color: #7d3434; 536 - } 537 - 538 - .ui.red.button:hover, 539 - .ui.red.buttons .button:hover { 540 - background-color: #984646; 541 - } 542 - 543 - .ui.positive.message { 544 - background-color: #000; 545 - color: #fff; 546 - box-shadow: 0 0 0 1px #1c1c1c inset, 0 0 0 0 transparent; 547 - } 548 - 549 - .ui.negative.message { 550 - background-color: rgba(80, 23, 17, .6); 551 - color: #f9cbcb; 552 - box-shadow: 0 0 0 1px rgba(121, 71, 66, .5) inset, 0 0 0 0 transparent; 553 - } 554 - 555 - .ui.list .list > .item .header, 556 - .ui.list > .item .header { 557 - color: #dedede; 558 - } 559 - 560 - .ui.list .list > .item .description, 561 - .ui.list > .item .description { 562 - color: var(--color-secondary-dark-6); 563 - } 564 - 565 - .repository.file.list #repo-files-table tbody .svg.octicon-file-directory, 566 - .repository.file.list #repo-files-table tbody .svg.octicon-file-submodule { 567 - color: #52555b; 568 - } 569 - 570 - .repository.labels .ui.basic.black.label { 571 - background-color: #bbbbbb !important; 572 - } 573 - 574 - .lines-commit, 575 - .blame .lines-num { 576 - background: #060606 !important; 577 - } 578 - 579 - .lines-num { 580 - color: var(--color-secondary-dark-6) !important; 581 - border-color: var(--color-secondary) !important; 582 - } 583 - 584 - td.blob-excerpt { 585 - background-color: rgba(0, 0, 0, .15); 586 - } 587 - 588 - .lines-code.active, 589 - .lines-code .active { 590 - background: #534d1b !important; 591 - } 592 - 593 - .ui.ui.ui.ui.table tr.active, 594 - .ui.ui.table td.active { 595 - color: #dbdbdb; 596 - } 597 - 598 - .ui.active.label { 599 - background: #46484e; 600 - border-color: #46484e; 601 - color: #dbdbdb; 602 - } 603 - 604 - .repository .ui.attached.message.isSigned.isVerified { 605 - background-color: #394829; 606 - color: var(--color-secondary-dark-6); 607 - 608 - &.message { 609 - color: #ab6363; 610 - .ui.text { 611 - color: var(--color-secondary-dark-6); 612 - } 613 - .pull-right { 614 - color: #ab6363; 615 - } 616 - } 617 - } 618 - 619 - .repository .ui.attached.message.isSigned.isVerifiedUntrusted { 620 - background-color: #4a3903; 621 - color: var(--color-secondary-dark-6); 622 - &.message { 623 - color: #c2c193; 624 - .ui.text { 625 - color: var(--color-secondary-dark-6); 626 - } 627 - a { 628 - color: #c2c193; 629 - } 630 - } 631 - } 632 - 633 - .repository .ui.attached.message.isSigned.isVerifiedUnmatched { 634 - background-color: #4e3321; 635 - color: var(--color-secondary-dark-6); 636 - &.message { 637 - color: #c2a893; 638 - .ui.text { 639 - color: var(--color-secondary-dark-6); 640 - } 641 - a { 642 - color: #c2a893; 643 - } 644 - } 645 - } 646 - 647 - .repository .ui.attached.message.isSigned.isWarning { 648 - background-color: rgba(80, 23, 17, .6); 649 - &.message { 650 - color: #d07d7d; 651 - .ui.text { 652 - color: #d07d7d; 653 - } 654 - } 655 - } 656 - 657 - .ui.header .sub.header { 658 - color: var(--color-secondary-dark-6); 659 - } 660 - 661 - .ui.dividing.header { 662 - border-bottom: 1px solid var(--color-secondary); 663 - } 664 - 665 - .ui.modal > .header { 666 - background: var(--color-secondary); 667 - color: #dbdbdb; 668 - } 669 - 670 - .ui.modal > .actions { 671 - background: var(--color-secondary); 672 - border-color: var(--color-secondary); 673 - } 674 - 675 - .ui.modal > .content { 676 - background: #2d2d2d; 677 - } 678 - 679 - .minicolors-panel { 680 - background: var(--color-secondary) !important; 681 - border-color: #6a737d !important; 682 - } 683 - 684 - /* invert emojis that are hard to read otherwise */ 685 - .emoji[aria-label="check mark"], 686 - .emoji[aria-label="currency exchange"], 687 - .emoji[aria-label="TOP arrow"], 688 - .emoji[aria-label="END arrow"], 689 - .emoji[aria-label="ON! arrow"], 690 - .emoji[aria-label="SOON arrow"], 691 - .emoji[aria-label="heavy dollar sign"], 692 - .emoji[aria-label="copyright"], 693 - .emoji[aria-label="registered"], 694 - .emoji[aria-label="trade mark"], 695 - .emoji[aria-label="multiply"], 696 - .emoji[aria-label="plus"], 697 - .emoji[aria-label="minus"], 698 - .emoji[aria-label="divide"], 699 - .emoji[aria-label="curly loop"], 700 - .emoji[aria-label="double curly loop"], 701 - .emoji[aria-label="wavy dash"], 702 - .emoji[aria-label="paw prints"], 703 - .emoji[aria-label="musical note"], 704 - .emoji[aria-label="musical notes"] { 705 - filter: invert(100%); 706 - } 707 - 708 - .edit-diff > div > .ui.table { 709 - border-left-color: var(--color-secondary) !important; 710 - border-right-color: var(--color-secondary) !important; 711 - } 712 - 713 - /* code mirror dark theme */ 714 - 715 - .CodeMirror { 716 - &.cm-s-default, 717 - &.cm-s-paper { 718 - .cm-property { 719 - color: #a0cc75; 720 - } 721 - 722 - .cm-header { 723 - color: #9daccc; 724 - } 725 - 726 - .cm-quote { 727 - color: #009900; 728 - } 729 - 730 - .cm-keyword { 731 - color: #cc8a61; 732 - } 733 - 734 - .cm-atom { 735 - color: #ef5e77; 736 - } 737 - 738 - .cm-number { 739 - color: #ff5656; 740 - } 741 - 742 - .cm-def { 743 - color: #e4e4e4; 744 - } 745 - 746 - .cm-variable-2 { 747 - color: #00bdbf; 748 - } 749 - 750 - .cm-variable-3 { 751 - color: #008855; 752 - } 753 - 754 - .cm-comment { 755 - color: #8e9ab3; 756 - } 757 - 758 - .cm-string { 759 - color: #a77272; 760 - } 761 - 762 - .cm-string-2 { 763 - color: #ff5500; 764 - } 765 - 766 - .cm-meta, 767 - .cm-qualifier { 768 - color: #ffb176; 769 - } 770 - 771 - .cm-builtin { 772 - color: #b7c951; 773 - } 774 - 775 - .cm-bracket { 776 - color: #999977; 777 - } 778 - 779 - .cm-tag { 780 - color: #f1d273; 781 - } 782 - 783 - .cm-attribute { 784 - color: #bfcc70; 785 - } 786 - 787 - .cm-hr { 788 - color: #999999; 789 - } 790 - 791 - .cm-url { 792 - color: #c5cfd0; 793 - } 794 - 795 - .cm-link { 796 - color: #d8c792; 797 - } 798 - 799 - .cm-error { 800 - /* color: #ff6e00; */ 801 - color: #dbdbeb; 802 - } 803 - } 804 - } 805 - 806 - footer .container .links > * { 807 - border-left-color: #888; 808 - } 809 - 810 - .repository.file.list #repo-files-table tbody .svg { 811 - color: var(--color-secondary-dark-6); 812 - } 813 - 814 - .repository.release #release-list > li .detail .dot { 815 - background-color: #4e5465; 816 - border-color: #2d2d2d; 817 - } 818 - 819 - .tribute-container { 820 - box-shadow: 0 .25rem .5rem rgba(0, 0, 0, .6); 821 - } 822 - 823 - .repository .repo-header .ui.huge.breadcrumb.repo-title .repo-header-icon .avatar { 824 - color: #060606; 825 - } 826 - 827 - img[src$="/img/matrix.svg"] { 828 - filter: invert(80%); 829 - } 830 - 831 - #git-graph-container li .time { 832 - color: #6a737d; 833 - } 834 - 835 - #git-graph-container.monochrome #rel-container .flow-group { 836 - stroke: dimgrey; 837 - fill: dimgrey; 838 - } 839 - 840 - #git-graph-container.monochrome #rel-container .flow-group.highlight { 841 - stroke: darkgrey; 842 - fill: darkgrey; 843 - } 844 - 845 - #git-graph-container:not(.monochrome) #rel-container .flow-group { 846 - &.flow-color-16-5 { 847 - stroke: #5543b1; 848 - fill: #5543b1; 849 - } 850 - } 851 - 852 - #git-graph-container:not(.monochrome) #rel-container .flow-group.highlight { 853 - &.flow-color-16-5 { 854 - stroke: #7058e6; 855 - fill: #7058e6; 856 - } 857 - } 858 - 859 - #git-graph-container #rev-list li.highlight.hover { 860 - background-color: rgba(255, 255, 255, .1); 861 - } 862 - 863 - #git-graph-container .ui.buttons button#flow-color-monochrome.ui.button { 864 - border-left-color: rgb(76, 80, 92); 865 - border-left-style: solid; 866 - border-left-width: 1px; 867 - } 868 - 869 - .mermaid-chart { 870 - filter: invert(84%) hue-rotate(180deg); 871 - } 872 - 873 - .is-loading::after { 874 - border-color: #4a4c58 #4a4c58 #d7d7da #d7d7da; 875 - } 876 - 877 - .markdown-block-error { 878 - border: 1px solid rgba(121, 71, 66, .5) !important; 879 - border-bottom: none !important; 880 - } 881 - 882 - .home .hero .svg { 883 - color: var(--color-primary); 884 - } 885 - 886 - .home a { 887 - color: var(--color-primary-light-1); 888 - } 889 - 890 - .ui.menu, .ui.vertical.menu { 891 - background: #070707; 892 - border-color: var(--color-secondary-dark-4); 893 - } 894 - 895 - .ui.menu.new-menu { 896 - background: #060606; 897 - } 898 - 899 - .ui.menu.new-menu:after { 900 - background: none; 901 - } 902 - 903 - .ui.checkbox label:active:before, .ui.checkbox label:hover:before, .ui.form input:not([type]):hover, .ui.form input[type=date]:hover, .ui.form input[type=datetime-local]:hover, .ui.form input[type=email]:hover, .ui.form input[type=file]:hover, .ui.form input[type=number]:hover, .ui.form input[type=password]:hover, .ui.form input[type=search]:hover, .ui.form input[type=tel]:hover, .ui.form input[type=text]:hover, .ui.form input[type=time]:hover, .ui.form input[type=url]:hover, .ui.form select:hover, .ui.form textarea:hover, .ui.input input:hover, .ui.radio.checkbox input:checked~label:before, .ui.radio.checkbox input:focus~label:before, .ui.radio.checkbox label:after, .ui.selection.dropdown:hover, input:hover, textarea:hover { 904 - background: var(--color-secondary-dark-3); 905 - } 906 - 907 - .ui.checkbox input:checked~label:before, .ui.checkbox input:not([type=radio]):indeterminate~label:before, .ui.checkbox label:before, .ui.form input:not([type]), .ui.form input[type=date], .ui.form input[type=datetime-local], .ui.form input[type=email], .ui.form input[type=file], .ui.form input[type=number], .ui.form input[type=password], .ui.form input[type=search], .ui.form input[type=tel], .ui.form input[type=text], .ui.form input[type=time], .ui.form input[type=url], .ui.form select, .ui.form textarea, .ui.input>input, .ui.selection.dropdown, input, textarea { 908 - background: var(--color-secondary-dark-2); 909 - } 910 - 911 - .ui.checkbox input:checked:focus~label:before, .ui.checkbox input:focus~label:before, .ui.checkbox input:not([type=radio]):indeterminate:focus~label:before, .ui.form input:not([type]):focus, .ui.form input[type=date]:focus, .ui.form input[type=datetime-local]:focus, .ui.form input[type=email]:focus, .ui.form input[type=file]:focus, .ui.form input[type=number]:focus, .ui.form input[type=password]:focus, .ui.form input[type=search]:focus, .ui.form input[type=tel]:focus, .ui.form input[type=text]:focus, .ui.form input[type=time]:focus, .ui.form input[type=url]:focus, .ui.form select:focus, .ui.form textarea:focus, .ui.input input:focus, .ui.radio.checkbox input:focus:checked~label:before, .ui.selection.dropdown:focus, input:focus, textarea:focus { 912 - background: var(--color-secondary-dark-3); 913 - } 914 - 915 - .ui.list .list>.item .description, .ui.list>.item .description { 916 - color: var(--color-secondary-dark-11); 917 - } 918 - 919 - .explore .navbar { 920 - background-color: var(--color-box-body)!important; 921 - } 922 - 923 - .repository .header-wrapper { 924 - background-color: var(--color-box-body); 925 - } 926 - 927 - .monaco-editor, .monaco-editor-background, .monaco-editor .inputarea.ime-input { 928 - background-color: #181818; 929 - } 930 - 931 - .ui.blue.label, .ui.blue.labels .label, .ui.primary.label, .ui.primary.labels .label { 932 - background-color: var(--color-secondary)!important; 933 - border-color: var(--color-primary-dark-2)!important; 934 - } 935 - 936 - .ui.blue.button, .ui.blue.buttons .button, .ui.primary.button, .ui.primary.buttons .button { 937 - background-color: #070707!important; 938 - } 939 - 940 - .ui.blue.button:hover, .ui.blue.buttons .button:hover, .ui.primary.button:hover, .ui.primary.buttons .button:hover { 941 - background-color: #1c1c1c!important; 942 - } 943 - 944 - .ui.green.labels .label, .ui.ui.ui.green.label { 945 - background-color: #1c1c1c!important; 946 - border-color: #21ba45!important; 947 - color: #fff; 948 - } 949 - 950 - .ui.red.labels .label, .ui.ui.ui.red.label { 951 - background-color: #1c1c1c!important; 952 - border-color: #db2828!important; 953 - color: #fff; 954 - } 955 - 956 - ::selection, ::-moz-selection { 957 - background: var(--color-grey); 958 - color: var(--color-secondary)!important; 959 - } 960 - 961 - .CodeMirror, .CodeMirror-selected, ::selection { 962 - background: var(--color-primary)!important; 963 - color: var(--color-secondary)!important; 964 - } 965 - 966 - .markup a, .ui.breadcrumb a { 967 - color: var(--color-primary-light-7); 968 - cursor: pointer; 969 - text-decoration: none; 970 - border-bottom: 1px solid var(--color-primary); 971 - transition-property: all 972 - } 973 - 974 - .markup a:hover, .ui.breadcrumb a:hover { 975 - color: #000; 976 - cursor: pointer; 977 - text-decoration: none; 978 - background: #fff; 979 - background-color: #fff 980 - } 981 - 982 - .markup .anchor { 983 - border-bottom: none 984 - } 985 - 986 - .markup .anchor:hover { 987 - color: var(--color-primary-light-7); 988 - border-bottom: none; 989 - background: var(--color-body); 990 - background-color: var(--color-body) 991 - } 992 - 993 - .mtk1, .mtk10 { 994 - color: #6D7178!important 995 - }
hosts/wolumonde/modules/forgejo.nix/public/assets/fonts/comic.woff2

This is a binary file and will not be displayed.

hosts/wolumonde/modules/forgejo.nix/public/assets/fonts/comicbd.woff2

This is a binary file and will not be displayed.

hosts/wolumonde/modules/forgejo.nix/public/assets/fonts/comici.woff2

This is a binary file and will not be displayed.

hosts/wolumonde/modules/forgejo.nix/public/assets/img/favicon.png

This is a binary file and will not be displayed.

hosts/wolumonde/modules/forgejo.nix/public/assets/img/grrr.webp

This is a binary file and will not be displayed.

hosts/wolumonde/modules/forgejo.nix/public/assets/img/logo.png

This is a binary file and will not be displayed.

hosts/wolumonde/modules/forgejo.nix/public/assets/img/wecode.gif

This is a binary file and will not be displayed.

-44
hosts/wolumonde/modules/forgejo.nix/templates/base/head.tmpl
··· 1 - <!DOCTYPE html> 2 - <html lang="{{ctx.Locale.Lang}}" data-theme="{{ThemeName .SignedUser}}"> 3 - <head> 4 - <meta name="viewport" content="width=device-width, initial-scale=1"> 5 - {{/* Display `- .Repository.FullName` only if `.Title` does not already start with that. */}} 6 - <title>{{if .Title}}{{.Title}} - {{end}}{{if and (.Repository.Name) (not (StringUtils.HasPrefix .Title .Repository.FullName))}}{{.Repository.FullName}} - {{end}}{{AppDisplayName}}</title> 7 - {{if .ManifestData}}<link rel="manifest" href="data:{{.ManifestData}}">{{end}} 8 - <meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}"> 9 - <meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}"> 10 - <meta name="keywords" content="{{MetaKeywords}}"> 11 - <meta name="referrer" content="no-referrer"> 12 - {{if .GoGetImport}} 13 - <meta name="go-import" content="{{.GoGetImport}} git {{.RepoCloneLink.HTTPS}}"> 14 - <meta name="go-source" content="{{.GoGetImport}} _ {{.GoDocDirectory}} {{.GoDocFile}}"> 15 - {{end}} 16 - {{if and .EnableFeed .FeedURL}} 17 - <link rel="alternate" type="application/atom+xml" title="" href="{{.FeedURL}}.atom"> 18 - <link rel="alternate" type="application/rss+xml" title="" href="{{.FeedURL}}.rss"> 19 - {{end}} 20 - <link rel="alternate icon" href="{{AssetUrlPrefix}}/img/favicon.png" type="image/png"> 21 - {{template "base/head_script" .}} 22 - {{template "shared/user/mention_highlight" .}} 23 - {{template "base/head_opengraph" .}} 24 - {{template "base/head_style" .}} 25 - {{template "custom/header" .}} 26 - </head> 27 - <body hx-headers='{"x-csrf-token": "{{.CsrfToken}}"}' hx-swap="outerHTML" hx-ext="morph" hx-push-url="false"> 28 - {{template "custom/body_outer_pre" .}} 29 - 30 - <div class="full height"> 31 - <noscript>{{ctx.Locale.Tr "enable_javascript"}}</noscript> 32 - 33 - {{template "custom/body_inner_pre" .}} 34 - 35 - {{if not .PageIsInstall}} 36 - {{template "base/head_navbar" .}} 37 - {{end}} 38 - 39 - {{if false}} 40 - {{/* to make html structure "likely" complete to prevent IDE warnings */}} 41 - </div> 42 - </body> 43 - </html> 44 - {{end}}
-207
hosts/wolumonde/modules/forgejo.nix/templates/base/head_navbar.tmpl
··· 1 - {{$notificationUnreadCount := 0}} 2 - {{if and .IsSigned .NotificationUnreadCount}} 3 - {{$notificationUnreadCount = call .NotificationUnreadCount}} 4 - {{end}} 5 - 6 - <nav id="navbar" aria-label="{{ctx.Locale.Tr "aria.navbar"}}"> 7 - <div class="navbar-left ui secondary menu"> 8 - <!-- the logo --> 9 - <a class="item" id="navbar-logo" href="{{AppSubUrl}}/" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home"}}{{end}}"> 10 - <img width="30" height="30" src="{{AssetUrlPrefix}}/img/logo.png" alt="{{ctx.Locale.Tr "logo"}}" aria-hidden="true"> 11 - </a> 12 - 13 - <!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column --> 14 - <div class="ui secondary menu item navbar-mobile-right only-mobile"> 15 - {{if .IsSigned}} 16 - <a id="mobile-notifications-icon" class="item tw-w-auto tw-p-2" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}" aria-label="{{ctx.Locale.Tr "notifications"}}"> 17 - <div class="tw-relative"> 18 - {{svg "octicon-bell"}} 19 - <span class="notification_count{{if not $notificationUnreadCount}} tw-hidden{{end}}">{{$notificationUnreadCount}}</span> 20 - </div> 21 - </a> 22 - {{end}} 23 - <button class="item tw-w-auto ui icon mini button tw-p-2 tw-m-0" id="navbar-expand-toggle" aria-label="{{ctx.Locale.Tr "toggle_menu"}}">{{svg "octicon-three-bars"}}</button> 24 - </div> 25 - 26 - <!-- navbar links non-mobile --> 27 - {{if and .IsSigned .MustChangePassword}} 28 - {{/* No links */}} 29 - {{else if .IsSigned}} 30 - {{if not .UnitIssuesGlobalDisabled}} 31 - <a class="item{{if .PageIsIssues}} active{{end}}" href="{{AppSubUrl}}/issues">{{ctx.Locale.Tr "issues"}}</a> 32 - {{end}} 33 - {{if not .UnitPullsGlobalDisabled}} 34 - <a class="item{{if .PageIsPulls}} active{{end}}" href="{{AppSubUrl}}/pulls">{{ctx.Locale.Tr "pull_requests"}}</a> 35 - {{end}} 36 - {{if not (and .UnitIssuesGlobalDisabled .UnitPullsGlobalDisabled)}} 37 - {{if .ShowMilestonesDashboardPage}} 38 - <a class="item{{if .PageIsMilestonesDashboard}} active{{end}}" href="{{AppSubUrl}}/milestones">{{ctx.Locale.Tr "milestones"}}</a> 39 - {{end}} 40 - {{end}} 41 - <a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/repos">{{ctx.Locale.Tr "explore"}}</a> 42 - {{else if .IsLandingPageOrganizations}} 43 - <a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/organizations">{{ctx.Locale.Tr "explore"}}</a> 44 - {{else}} 45 - <a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/repos">{{ctx.Locale.Tr "explore"}}</a> 46 - {{end}} 47 - 48 - {{template "custom/extra_links" .}} 49 - 50 - {{if not .IsSigned}} 51 - <a class="item" target="_blank" rel="noopener noreferrer" href="https://forgejo.org/docs/latest/">{{ctx.Locale.Tr "help"}}</a> 52 - {{end}} 53 - </div> 54 - 55 - <!-- the full dropdown menus --> 56 - <div class="navbar-right ui secondary menu"> 57 - {{if and .IsSigned .MustChangePassword}} 58 - <div class="ui dropdown jump item" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}"> 59 - <span class="text tw-flex tw-items-center"> 60 - {{ctx.AvatarUtils.Avatar .SignedUser 24 "tw-mr-1"}} 61 - <span class="only-mobile tw-ml-2">{{.SignedUser.Name}}</span> 62 - <span class="not-mobile">{{svg "octicon-triangle-down"}}</span> 63 - </span> 64 - <div class="menu user-menu"> 65 - <div class="ui header"> 66 - {{ctx.Locale.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong> 67 - </div> 68 - 69 - <div class="divider"></div> 70 - <a class="item link-action" href data-url="{{AppSubUrl}}/user/logout"> 71 - {{svg "octicon-sign-out"}} 72 - {{ctx.Locale.Tr "sign_out"}} 73 - </a> 74 - </div><!-- end content avatar menu --> 75 - </div><!-- end dropdown avatar menu --> 76 - {{else if .IsSigned}} 77 - {{if EnableTimetracking}} 78 - <a class="active-stopwatch-trigger item tw-mx-0{{if not .ActiveStopwatch}} tw-hidden{{end}}" href="{{.ActiveStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}"> 79 - <div class="tw-relative"> 80 - {{svg "octicon-stopwatch"}} 81 - <span class="header-stopwatch-dot"></span> 82 - </div> 83 - <span class="only-mobile tw-ml-2">{{ctx.Locale.Tr "active_stopwatch"}}</span> 84 - </a> 85 - <div class="active-stopwatch-popup item tippy-target tw-p-2"> 86 - <div class="tw-flex tw-items-center"> 87 - <a class="stopwatch-link tw-flex tw-items-center" href="{{.ActiveStopwatch.IssueLink}}"> 88 - {{svg "octicon-issue-opened" 16 "tw-mr-2"}} 89 - <span class="stopwatch-issue">{{.ActiveStopwatch.RepoSlug}}#{{.ActiveStopwatch.IssueIndex}}</span> 90 - <span class="ui primary label stopwatch-time tw-my-0 tw-mx-4" data-seconds="{{.ActiveStopwatch.Seconds}}"> 91 - {{if .ActiveStopwatch}}{{Sec2Time .ActiveStopwatch.Seconds}}{{end}} 92 - </span> 93 - </a> 94 - <form class="stopwatch-commit" method="post" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/toggle"> 95 - {{.CsrfTokenHtml}} 96 - <button 97 - type="submit" 98 - class="ui button mini compact basic icon" 99 - data-tooltip-content="{{ctx.Locale.Tr "repo.issues.stop_tracking"}}" 100 - >{{svg "octicon-square-fill"}}</button> 101 - </form> 102 - <form class="stopwatch-cancel" method="post" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/cancel"> 103 - {{.CsrfTokenHtml}} 104 - <button 105 - type="submit" 106 - class="ui button mini compact basic icon" 107 - data-tooltip-content="{{ctx.Locale.Tr "repo.issues.cancel_tracking"}}" 108 - >{{svg "octicon-trash"}}</button> 109 - </form> 110 - </div> 111 - </div> 112 - {{end}} 113 - 114 - <a class="item not-mobile tw-mx-0" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}" aria-label="{{ctx.Locale.Tr "notifications"}}"> 115 - <div class="tw-relative"> 116 - {{svg "octicon-bell"}} 117 - <span class="notification_count{{if not $notificationUnreadCount}} tw-hidden{{end}}">{{$notificationUnreadCount}}</span> 118 - </div> 119 - </a> 120 - 121 - <div class="ui dropdown jump item tw-mx-0 tw-pr-2" data-tooltip-content="{{ctx.Locale.Tr "create_new"}}"> 122 - <span class="text"> 123 - {{svg "octicon-plus"}} 124 - <span class="not-mobile">{{svg "octicon-triangle-down"}}</span> 125 - <span class="only-mobile">{{ctx.Locale.Tr "create_new"}}</span> 126 - </span> 127 - <div class="menu"> 128 - <a class="item" href="{{AppSubUrl}}/repo/create"> 129 - {{svg "octicon-plus"}} {{ctx.Locale.Tr "new_repo.link"}} 130 - </a> 131 - {{if not .DisableMigrations}} 132 - <a class="item" href="{{AppSubUrl}}/repo/migrate"> 133 - {{svg "octicon-repo-push"}} {{ctx.Locale.Tr "new_migrate.link"}} 134 - </a> 135 - {{end}} 136 - {{if .SignedUser.CanCreateOrganization}} 137 - <a class="item" href="{{AppSubUrl}}/org/create"> 138 - {{svg "octicon-organization"}} {{ctx.Locale.Tr "new_org.link"}} 139 - </a> 140 - {{end}} 141 - </div><!-- end content create new menu --> 142 - </div><!-- end dropdown menu create new --> 143 - 144 - <div class="ui dropdown jump item tw-mx-0 tw-pr-2" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}"> 145 - <span class="text tw-flex tw-items-center"> 146 - {{ctx.AvatarUtils.Avatar .SignedUser 24 "tw-mr-1"}} 147 - <span class="only-mobile tw-ml-2">{{.SignedUser.Name}}</span> 148 - <span class="not-mobile">{{svg "octicon-triangle-down"}}</span> 149 - </span> 150 - <div class="menu user-menu"> 151 - <div class="ui header"> 152 - {{ctx.Locale.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong> 153 - </div> 154 - 155 - <div class="divider"></div> 156 - <a class="item" href="{{.SignedUser.HomeLink}}"> 157 - {{svg "octicon-person"}} 158 - {{ctx.Locale.Tr "your_profile"}} 159 - </a> 160 - {{if not .DisableStars}} 161 - <a class="item" href="{{.SignedUser.HomeLink}}?tab=stars"> 162 - {{svg "octicon-star"}} 163 - {{ctx.Locale.Tr "your_starred"}} 164 - </a> 165 - {{end}} 166 - <a class="item" href="{{AppSubUrl}}/notifications/subscriptions"> 167 - {{svg "octicon-bell"}} 168 - {{ctx.Locale.Tr "notification.subscriptions"}} 169 - </a> 170 - <a class="{{if .PageIsUserSettings}}active {{end}}item" href="{{AppSubUrl}}/user/settings"> 171 - {{svg "octicon-tools"}} 172 - {{ctx.Locale.Tr "your_settings"}} 173 - </a> 174 - <a class="item" target="_blank" rel="noopener noreferrer" href="https://forgejo.org/docs/latest/"> 175 - {{svg "octicon-question"}} 176 - {{ctx.Locale.Tr "help"}} 177 - </a> 178 - {{if .IsAdmin}} 179 - <div class="divider"></div> 180 - 181 - <a class="{{if .PageIsAdmin}}active {{end}}item" href="{{AppSubUrl}}/admin"> 182 - {{svg "octicon-server"}} 183 - {{ctx.Locale.Tr "admin_panel"}} 184 - </a> 185 - {{end}} 186 - 187 - <div class="divider"></div> 188 - <a class="item link-action" href data-url="{{AppSubUrl}}/user/logout"> 189 - {{svg "octicon-sign-out"}} 190 - {{ctx.Locale.Tr "sign_out"}} 191 - </a> 192 - </div><!-- end content avatar menu --> 193 - </div><!-- end dropdown avatar menu --> 194 - {{else}} 195 - {{if .ShowRegistrationButton}} 196 - <a class="item{{if .PageIsSignUp}} active{{end}}" href="{{AppSubUrl}}/user/sign_up"> 197 - {{svg "octicon-person" 16 "tw-mr-1"}} 198 - <span>{{ctx.Locale.Tr "register"}}</span> 199 - </a> 200 - {{end}} 201 - <a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login{{if not .PageIsSignIn}}?redirect_to={{.CurrentURL}}{{end}}"> 202 - {{svg "octicon-sign-in" 16 "tw-mr-1"}} 203 - <span>{{ctx.Locale.Tr "sign_in"}}</span> 204 - </a> 205 - {{end}} 206 - </div><!-- end full right menu --> 207 - </nav>
-14
hosts/wolumonde/modules/forgejo.nix/templates/home.tmpl
··· 1 - {{template "base/head" .}} 2 - <div role="main" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home"}}{{end}}" class="page-content home"> 3 - <div class="tw-mb-8 tw-px-8"> 4 - <div class="center"> 5 - <img class="logo" width="220" height="220" src="https://git.gaze.systems/assets/img/grrr.webp" alt="i hate software" title="i hate software"> 6 - <div class="hero"> 7 - <h2>software</h2> 8 - </div> 9 - <div style="height: 200vh;"></div> 10 - <img class="logo" width="220" height="220" src="https://git.gaze.systems/assets/img/wecode.gif" alt="forgejo. beyond coding. we forge. but lowtiergod" title="skies ur rina"> 11 - </div> 12 - </div> 13 - </div> 14 - {{template "base/footer" .}}
+28
hosts/wolumonde/modules/hedgedoc.disabled
··· 1 + { config, ... }: 2 + let 3 + cfg = config.services.hedgedoc.settings; 4 + in 5 + { 6 + services.hedgedoc = { 7 + enable = true; 8 + settings = { 9 + port = 3333; 10 + domain = "doc.gaze.systems"; 11 + protocolUseSSL = true; 12 + allowEmailRegister = false; 13 + allowAnonymous = false; 14 + allowAnonymousEdits = true; 15 + allowFreeURL = true; 16 + requireFreeURLAuthentication = true; 17 + }; 18 + }; 19 + 20 + security.acme.certs."gaze.systems".extraDomainNames = [ cfg.domain ]; 21 + services.nginx.virtualHosts.${cfg.domain} = { 22 + useACMEHost = "gaze.systems"; 23 + forceSSL = true; 24 + quic = true; 25 + kTLS = true; 26 + locations."/".proxyPass = "http://${cfg.host}:${toString cfg.port}"; 27 + }; 28 + }
-28
hosts/wolumonde/modules/hedgedoc.nix
··· 1 - { config, ... }: 2 - let 3 - cfg = config.services.hedgedoc.settings; 4 - in 5 - { 6 - services.hedgedoc = { 7 - enable = true; 8 - settings = { 9 - port = 3333; 10 - domain = "doc.gaze.systems"; 11 - protocolUseSSL = true; 12 - allowEmailRegister = false; 13 - allowAnonymous = false; 14 - allowAnonymousEdits = true; 15 - allowFreeURL = true; 16 - requireFreeURLAuthentication = true; 17 - }; 18 - }; 19 - 20 - security.acme.certs."gaze.systems".extraDomainNames = [ cfg.domain ]; 21 - services.nginx.virtualHosts.${cfg.domain} = { 22 - useACMEHost = "gaze.systems"; 23 - forceSSL = true; 24 - quic = true; 25 - kTLS = true; 26 - locations."/".proxyPass = "http://${cfg.host}:${toString cfg.port}"; 27 - }; 28 - }
+59
hosts/wolumonde/modules/limbusart.disabled
··· 1 + { 2 + inputs, 3 + pkgs, 4 + lib, 5 + ... 6 + }: 7 + let 8 + pkg = pkgs.callPackage "${inputs.limbusart}/package.nix" { }; 9 + domain = "pmart.gaze.systems"; 10 + oldDomain = "limbus.gaze.systems"; 11 + in 12 + { 13 + systemd.services.limbusart = { 14 + description = "limbusart"; 15 + wantedBy = [ "multi-user.target" ]; 16 + after = [ "network.target" ]; 17 + serviceConfig = lib.mkMerge [ 18 + { 19 + User = "limbusart"; 20 + ExecStart = "${pkg}/bin/limbusart"; 21 + Restart = "on-failure"; 22 + RestartSec = 5; 23 + WorkingDirectory = "/var/lib/limbusart"; 24 + EnvironmentFile = pkgs.writeText "limbusart.conf" '' 25 + ARTS_PATH="arts.txt" 26 + SITE_TITLE="random pm art" 27 + EMBED_TITLE="random pm art here!!" 28 + EMBED_DESC="click NOW to see random pm art" 29 + EMBED_COLOR="#bd0000" 30 + ''; 31 + } 32 + ]; 33 + }; 34 + users.users.limbusart = { 35 + isSystemUser = true; 36 + group = "limbusart"; 37 + }; 38 + users.groups.limbusart = { }; 39 + 40 + security.acme.certs."gaze.systems".extraDomainNames = [ 41 + domain 42 + oldDomain 43 + ]; 44 + services.nginx.virtualHosts.${domain} = { 45 + useACMEHost = "gaze.systems"; 46 + forceSSL = true; 47 + quic = true; 48 + kTLS = true; 49 + locations."/".proxyPass = "http://localhost:3000"; 50 + }; 51 + # redirects 52 + services.nginx.virtualHosts.${oldDomain} = { 53 + useACMEHost = "gaze.systems"; 54 + forceSSL = true; 55 + quic = true; 56 + kTLS = true; 57 + globalRedirect = domain; 58 + }; 59 + }
-59
hosts/wolumonde/modules/limbusart.nix
··· 1 - { 2 - inputs, 3 - pkgs, 4 - lib, 5 - ... 6 - }: 7 - let 8 - pkg = pkgs.callPackage "${inputs.limbusart}/package.nix" { }; 9 - domain = "pmart.gaze.systems"; 10 - oldDomain = "limbus.gaze.systems"; 11 - in 12 - { 13 - systemd.services.limbusart = { 14 - description = "limbusart"; 15 - wantedBy = [ "multi-user.target" ]; 16 - after = [ "network.target" ]; 17 - serviceConfig = lib.mkMerge [ 18 - { 19 - User = "limbusart"; 20 - ExecStart = "${pkg}/bin/limbusart"; 21 - Restart = "on-failure"; 22 - RestartSec = 5; 23 - WorkingDirectory = "/var/lib/limbusart"; 24 - EnvironmentFile = pkgs.writeText "limbusart.conf" '' 25 - ARTS_PATH="arts.txt" 26 - SITE_TITLE="random pm art" 27 - EMBED_TITLE="random pm art here!!" 28 - EMBED_DESC="click NOW to see random pm art" 29 - EMBED_COLOR="#bd0000" 30 - ''; 31 - } 32 - ]; 33 - }; 34 - users.users.limbusart = { 35 - isSystemUser = true; 36 - group = "limbusart"; 37 - }; 38 - users.groups.limbusart = { }; 39 - 40 - security.acme.certs."gaze.systems".extraDomainNames = [ 41 - domain 42 - oldDomain 43 - ]; 44 - services.nginx.virtualHosts.${domain} = { 45 - useACMEHost = "gaze.systems"; 46 - forceSSL = true; 47 - quic = true; 48 - kTLS = true; 49 - locations."/".proxyPass = "http://localhost:3000"; 50 - }; 51 - # redirects 52 - services.nginx.virtualHosts.${oldDomain} = { 53 - useACMEHost = "gaze.systems"; 54 - forceSSL = true; 55 - quic = true; 56 - kTLS = true; 57 - globalRedirect = domain; 58 - }; 59 - }
+67 -61
hosts/wolumonde/modules/nginx.nix
··· 1 1 { 2 + config, 2 3 lib, 3 4 inputs, 4 - pkgs, 5 5 ... 6 6 }: 7 7 { 8 8 services.nginx = { 9 9 enable = true; 10 - package = pkgs.nginxQuic; 11 10 recommendedTlsSettings = true; 12 11 recommendedOptimisation = true; 13 12 recommendedGzipSettings = true; ··· 40 39 41 40 users.users.nginx.extraGroups = [ "acme" ]; 42 41 42 + age.secrets.cfDnsEditToken.file = ../../../secrets/cloudflareDnsEdit.age; 43 43 security.acme = { 44 44 acceptTerms = true; 45 - defaults.email = (import "${inputs.self}/personal.nix").emails.primary; 46 - defaults.webroot = "/var/lib/acme/acme-challenge"; 45 + defaults = { 46 + group = "nginx"; 47 + email = (import "${inputs.self}/personal.nix").emails.primary; 48 + dnsProvider = "cloudflare"; 49 + credentialFiles = { 50 + CF_DNS_API_TOKEN_FILE = config.age.secrets.cfDnsEditToken.path; 51 + }; 52 + }; 47 53 certs."poor.dog" = { }; 48 54 certs."ptr.pet" = { }; 49 55 certs."gaze.systems" = { }; ··· 67 73 forceSSL = true; 68 74 }; 69 75 70 - services.fluent-bit.settings = { 71 - parsers = [ 72 - { 73 - name = "nginx_json"; 74 - format = "json"; 75 - time_key = "time"; 76 - time_format = "%d/%b/%Y:%H:%M:%S %z"; 77 - } 78 - ]; 79 - pipeline = { 80 - inputs = [ 81 - { 82 - name = "nginx_metrics"; 83 - tag = "metrics.nginx"; 84 - status_url = "/nginx_status"; 85 - nginx_plus = false; 86 - } 87 - { 88 - name = "tail"; 89 - tag = "logs.nginx"; 90 - path = "/var/log/nginx/*.log"; 91 - db = "/var/lib/fluent-bit/nginx-access.db"; 92 - "db.locking" = true; 93 - buffer_chunk_size = "4m"; 94 - buffer_max_size = "32m"; 95 - parser = "nginx_json"; 96 - } 97 - ]; 98 - filters = [ 99 - { 100 - name = "modify"; 101 - match = "logs.nginx"; 102 - Add = [ "name nginx" ]; 103 - } 104 - ]; 105 - }; 106 - }; 76 + # services.fluent-bit.settings = { 77 + # parsers = [ 78 + # { 79 + # name = "nginx_json"; 80 + # format = "json"; 81 + # time_key = "time"; 82 + # time_format = "%d/%b/%Y:%H:%M:%S %z"; 83 + # } 84 + # ]; 85 + # pipeline = { 86 + # inputs = [ 87 + # { 88 + # name = "nginx_metrics"; 89 + # tag = "metrics.nginx"; 90 + # status_url = "/nginx_status"; 91 + # nginx_plus = false; 92 + # } 93 + # { 94 + # name = "tail"; 95 + # tag = "logs.nginx"; 96 + # path = "/var/log/nginx/*.log"; 97 + # db = "/var/lib/fluent-bit/nginx-access.db"; 98 + # "db.locking" = true; 99 + # buffer_chunk_size = "4m"; 100 + # buffer_max_size = "32m"; 101 + # parser = "nginx_json"; 102 + # } 103 + # ]; 104 + # filters = [ 105 + # { 106 + # name = "modify"; 107 + # match = "logs.nginx"; 108 + # Add = [ "name nginx" ]; 109 + # } 110 + # ]; 111 + # }; 112 + # }; 107 113 108 - # need so fluent-bit can access nginx 109 - systemd.services.fluent-bit.serviceConfig.SupplementaryGroups = lib.mkForce "systemd-journal nginx"; 114 + # # need so fluent-bit can access nginx 115 + # systemd.services.fluent-bit.serviceConfig.SupplementaryGroups = lib.mkForce "systemd-journal nginx"; 110 116 111 - services.vmalert.instances."".rules.groups = [ 112 - { 113 - name = "nginx-logs"; 114 - type = "vlogs"; 115 - interval = "1m"; 116 - rules = [ 117 - { 118 - record = "nginx_request_count"; 119 - expr = "name:nginx | stats (res.statusCode) count() as total_requests"; 120 - } 121 - { 122 - record = "nginx_request_latency"; 123 - # filter out subscribeRepos requests because they are long polling http L 124 - expr = "name:nginx | filter req.url:!/xrpc/com.atproto.sync.subscribeRepos | stats avg(requestTime) avg, quantile(0.5, requestTime) p50, quantile(0.9, requestTime) p90, quantile(0.99, requestTime) p99"; 125 - } 126 - ]; 127 - } 128 - ]; 117 + # services.vmalert.instances."".rules.groups = [ 118 + # { 119 + # name = "nginx-logs"; 120 + # type = "vlogs"; 121 + # interval = "1m"; 122 + # rules = [ 123 + # { 124 + # record = "nginx_request_count"; 125 + # expr = "name:nginx | stats (res.statusCode) count() as total_requests"; 126 + # } 127 + # { 128 + # record = "nginx_request_latency"; 129 + # # filter out subscribeRepos requests because they are long polling http L 130 + # expr = "name:nginx | filter req.url:!/xrpc/com.atproto.sync.subscribeRepos | stats avg(requestTime) avg, quantile(0.5, requestTime) p50, quantile(0.9, requestTime) p90, quantile(0.99, requestTime) p99"; 131 + # } 132 + # ]; 133 + # } 134 + # ]; 129 135 }
+66
hosts/wolumonde/modules/nsid-tracker.disabled
··· 1 + { 2 + pkgs, 3 + terra, 4 + inputs, 5 + ... 6 + }: 7 + let 8 + client-modules = pkgs.callPackage "${inputs.nsid-tracker}/nix/client-modules.nix" { }; 9 + client = pkgs.callPackage "${inputs.nsid-tracker}/nix/client.nix" { 10 + PUBLIC_API_URL = "gaze.systems/nsid-tracker/api"; 11 + inherit client-modules; 12 + }; 13 + # server = terra.nsid-tracker-server; 14 + port = 3713; 15 + in 16 + { 17 + systemd.services.nsid-tracker-client = { 18 + description = "nsid-tracker-client"; 19 + wantedBy = [ "multi-user.target" ]; 20 + after = [ "network.target" ]; 21 + environment = { 22 + # ORIGIN = "https://gaze.systems"; 23 + PORT = toString port; 24 + }; 25 + serviceConfig = { 26 + DynamicUser = true; 27 + ExecStart = "${client}/bin/website"; 28 + Restart = "on-failure"; 29 + RestartSec = 5; 30 + WorkingDirectory = "/var/lib/nsid-tracker"; 31 + }; 32 + }; 33 + # 34 + 35 + systemd.services.nsid-tracker-keep-alive = { 36 + description = "keeps nsid-tracker peer connection alive"; 37 + wantedBy = [ "multi-user.target" ]; 38 + after = [ "network.target" ]; 39 + serviceConfig = { 40 + Type = "oneshot"; 41 + ExecStart = "${pkgs.curl}/bin/curl http://dusk-devel-mobi:${toString port}/events"; 42 + }; 43 + }; 44 + systemd.timers.nsid-tracker-keep-alive.timerConfig = { 45 + OnBootSec = "5 min"; 46 + OnUnitActiveSec = "5 min"; 47 + Unit = "nsid-tracker-keep-alive.service"; 48 + }; 49 + 50 + services.nginx.virtualHosts."gaze.systems" = { 51 + locations."/nsid-tracker/api" = { 52 + proxyPass = "http://100.64.0.6:${toString port}/"; 53 + proxyWebsockets = true; 54 + extraConfig = '' 55 + rewrite ^/nsid-tracker/api/(.*) /$1 break; 56 + ''; 57 + }; 58 + locations."/nsid-tracker".return = "301 /nsid-tracker/"; 59 + locations."/nsid-tracker/" = { 60 + proxyPass = "http://localhost:${toString port}/"; 61 + extraConfig = '' 62 + rewrite ^/nsid-tracker/(.*)$ /$1 break; 63 + ''; 64 + }; 65 + }; 66 + }
-66
hosts/wolumonde/modules/nsid-tracker.nix
··· 1 - { 2 - pkgs, 3 - terra, 4 - inputs, 5 - ... 6 - }: 7 - let 8 - client-modules = pkgs.callPackage "${inputs.nsid-tracker}/nix/client-modules.nix" { }; 9 - client = pkgs.callPackage "${inputs.nsid-tracker}/nix/client.nix" { 10 - PUBLIC_API_URL = "gaze.systems/nsid-tracker/api"; 11 - inherit client-modules; 12 - }; 13 - # server = terra.nsid-tracker-server; 14 - port = 3713; 15 - in 16 - { 17 - systemd.services.nsid-tracker-client = { 18 - description = "nsid-tracker-client"; 19 - wantedBy = [ "multi-user.target" ]; 20 - after = [ "network.target" ]; 21 - environment = { 22 - # ORIGIN = "https://gaze.systems"; 23 - PORT = toString port; 24 - }; 25 - serviceConfig = { 26 - DynamicUser = true; 27 - ExecStart = "${client}/bin/website"; 28 - Restart = "on-failure"; 29 - RestartSec = 5; 30 - WorkingDirectory = "/var/lib/nsid-tracker"; 31 - }; 32 - }; 33 - # 34 - 35 - systemd.services.nsid-tracker-keep-alive = { 36 - description = "keeps nsid-tracker peer connection alive"; 37 - wantedBy = [ "multi-user.target" ]; 38 - after = [ "network.target" ]; 39 - serviceConfig = { 40 - Type = "oneshot"; 41 - ExecStart = "${pkgs.curl}/bin/curl http://dusk-devel-mobi:${toString port}/events"; 42 - }; 43 - }; 44 - systemd.timers.nsid-tracker-keep-alive.timerConfig = { 45 - OnBootSec = "5 min"; 46 - OnUnitActiveSec = "5 min"; 47 - Unit = "nsid-tracker-keep-alive.service"; 48 - }; 49 - 50 - services.nginx.virtualHosts."gaze.systems" = { 51 - locations."/nsid-tracker/api" = { 52 - proxyPass = "http://100.64.0.6:${toString port}/"; 53 - proxyWebsockets = true; 54 - extraConfig = '' 55 - rewrite ^/nsid-tracker/api/(.*) /$1 break; 56 - ''; 57 - }; 58 - locations."/nsid-tracker".return = "301 /nsid-tracker/"; 59 - locations."/nsid-tracker/" = { 60 - proxyPass = "http://localhost:${toString port}/"; 61 - extraConfig = '' 62 - rewrite ^/nsid-tracker/(.*)$ /$1 break; 63 - ''; 64 - }; 65 - }; 66 - }
+152
hosts/wolumonde/modules/pds.disabled
··· 1 + { lib, config, ... }: 2 + let 3 + pdsLocalhost = "http://localhost:${toString config.services.bluesky-pds.settings.PDS_PORT}"; 4 + in 5 + { 6 + services.nginx.virtualHosts.${config.services.bluesky-pds.settings.PDS_HOSTNAME} = { 7 + useACMEHost = "gaze.systems"; 8 + forceSSL = true; 9 + locations = { 10 + # we need to proxy /xrpc for pds to work 11 + # silly but i want root domain >:3 12 + "/xrpc" = { 13 + proxyPass = pdsLocalhost; 14 + proxyWebsockets = true; 15 + # pass ws headers so we can actually proxy the ws 16 + extraConfig = '' 17 + proxy_set_header id $request_id; 18 + client_max_body_size 100M; 19 + ''; 20 + # higher prio just to make sure 21 + priority = 100; 22 + }; 23 + "/xrpc/app.bsky.unspecced.getAgeAssuranceState".extraConfig = '' 24 + default_type application/json; 25 + add_header access-control-allow-headers "authorization,dpop,atproto-accept-labelers,atproto-proxy" always; 26 + add_header access-control-allow-origin "*" always; 27 + return 200 '{"lastInitiatedAt":"2025-07-14T14:22:43.912Z","status":"assured"}'; 28 + ''; 29 + } 30 + # others 31 + // (lib.genAttrs 32 + [ 33 + "/account" 34 + "/@atproto" 35 + "/oauth" 36 + "=/.well-known/oauth-protected-resource" 37 + "=/.well-known/oauth-authorization-server" 38 + ] 39 + (_: { 40 + proxyPass = pdsLocalhost; 41 + # higher prio just to make sure 42 + priority = 100; 43 + }) 44 + ); 45 + }; 46 + # setup pds stuff 47 + services.bluesky-pds = { 48 + enable = true; 49 + settings = { 50 + PDS_HOSTNAME = "gaze.systems"; 51 + PDS_PORT = 1334; 52 + 53 + PDS_SERVICE_NAME = ''"gazing at the sky"''; 54 + PDS_LOGO_URL = "https://gaze.systems/icons/gaze_site.webp"; 55 + 56 + PDS_RATE_LIMITS_ENABLED = "true"; 57 + PDS_INVITE_REQUIRED = "true"; 58 + 59 + PDS_DID_PLC_URL = "https://plc.directory"; 60 + PDS_BSKY_APP_VIEW_URL = "https://api.bsky.app"; 61 + PDS_BSKY_APP_VIEW_DID = "did:web:api.bsky.app"; 62 + PDS_REPORT_SERVICE_URL = "https://mod.bsky.app"; 63 + PDS_REPORT_SERVICE_DID = "did:plc:ar7c4by46qjdydhdevvrndac"; 64 + PDS_CRAWLERS = "https://bsky.network"; 65 + }; 66 + environmentFiles = [ config.age.secrets.pdsConfig.path ]; 67 + }; 68 + 69 + # services.fluent-bit.settings = { 70 + # parsers = [ 71 + # { 72 + # name = "pds_json"; 73 + # format = "json"; 74 + # time_key = "time"; 75 + # time_strict = false; 76 + # } 77 + # ]; 78 + # pipeline = { 79 + # inputs = [ 80 + # { 81 + # name = "systemd"; 82 + # tag = "logs.pds"; 83 + # systemd_filter = "_SYSTEMD_UNIT=bluesky-pds.service"; 84 + # } 85 + # ]; 86 + # filters = [ 87 + # { 88 + # name = "parser"; 89 + # match = "logs.pds"; 90 + # key_name = "MESSAGE"; 91 + # parser = "pds_json"; 92 + # } 93 + # { 94 + # name = "modify"; 95 + # match = "logs.pds"; 96 + # Rename = [ "msg _msg" ]; 97 + # } 98 + # ]; 99 + # }; 100 + # }; 101 + 102 + # services.vmalert.instances."".rules.groups = [ 103 + # { 104 + # name = "pds-logs"; 105 + # type = "vlogs"; 106 + # interval = "1m"; 107 + # rules = [ 108 + # { 109 + # record = "pds_request_count"; 110 + # expr = "name:pds | stats (res.statusCode) count() as total_requests"; 111 + # } 112 + # { 113 + # record = "pds_response_latency"; 114 + # expr = "name:pds | stats avg(responseTime) avg, quantile(0.5, responseTime) p50, quantile(0.9, responseTime) p90, quantile(0.99, responseTime) p99"; 115 + # } 116 + # ]; 117 + # } 118 + # ]; 119 + 120 + # virtualisation = { 121 + # podman = { 122 + # enable = true; 123 + # dockerCompat = true; 124 + # defaultNetwork.settings.dns_enabled = true; 125 + # }; 126 + # oci-containers.containers = { 127 + # pds = { 128 + # image = "ghcr.io/bluesky-social/pds:0.4"; 129 + # autoStart = true; 130 + # environmentFiles = [ ./pds.env config.age.secrets.pdsConfig.path ]; 131 + # ports = [ "1334:1334" ]; 132 + # volumes = [ 133 + # "/var/lib/pds:/pds" 134 + # ]; 135 + # extraOptions = [ 136 + # #"--network=host" 137 + # "--label=io.containers.autoupdate=registry" 138 + # ]; 139 + # }; 140 + # }; 141 + # }; 142 + # # This is the podman auto-update systemd timer. 143 + # # If I start to rely on podman auto-update more, I should move this out of the PDS definition. 144 + # systemd.timers."podman-auto-update" = { 145 + # enable = true; 146 + # timerConfig = { 147 + # OnCalendar = "*-*-* 4:00:00"; 148 + # Persistent = true; 149 + # }; 150 + # wantedBy = [ "timers.target" ]; 151 + # }; 152 + }
-152
hosts/wolumonde/modules/pds.nix
··· 1 - { lib, config, ... }: 2 - let 3 - pdsLocalhost = "http://localhost:${toString config.services.bluesky-pds.settings.PDS_PORT}"; 4 - in 5 - { 6 - services.nginx.virtualHosts.${config.services.bluesky-pds.settings.PDS_HOSTNAME} = { 7 - useACMEHost = "gaze.systems"; 8 - forceSSL = true; 9 - locations = { 10 - # we need to proxy /xrpc for pds to work 11 - # silly but i want root domain >:3 12 - "/xrpc" = { 13 - proxyPass = pdsLocalhost; 14 - proxyWebsockets = true; 15 - # pass ws headers so we can actually proxy the ws 16 - extraConfig = '' 17 - proxy_set_header id $request_id; 18 - client_max_body_size 100M; 19 - ''; 20 - # higher prio just to make sure 21 - priority = 100; 22 - }; 23 - "/xrpc/app.bsky.unspecced.getAgeAssuranceState".extraConfig = '' 24 - default_type application/json; 25 - add_header access-control-allow-headers "authorization,dpop,atproto-accept-labelers,atproto-proxy" always; 26 - add_header access-control-allow-origin "*" always; 27 - return 200 '{"lastInitiatedAt":"2025-07-14T14:22:43.912Z","status":"assured"}'; 28 - ''; 29 - } 30 - # others 31 - // (lib.genAttrs 32 - [ 33 - "/account" 34 - "/@atproto" 35 - "/oauth" 36 - "=/.well-known/oauth-protected-resource" 37 - "=/.well-known/oauth-authorization-server" 38 - ] 39 - (_: { 40 - proxyPass = pdsLocalhost; 41 - # higher prio just to make sure 42 - priority = 100; 43 - }) 44 - ); 45 - }; 46 - # setup pds stuff 47 - services.bluesky-pds = { 48 - enable = true; 49 - settings = { 50 - PDS_HOSTNAME = "gaze.systems"; 51 - PDS_PORT = 1334; 52 - 53 - PDS_SERVICE_NAME = ''"gazing at the sky"''; 54 - PDS_LOGO_URL = "https://gaze.systems/icons/gaze_site.webp"; 55 - 56 - PDS_RATE_LIMITS_ENABLED = "true"; 57 - PDS_INVITE_REQUIRED = "true"; 58 - 59 - PDS_DID_PLC_URL = "https://plc.directory"; 60 - PDS_BSKY_APP_VIEW_URL = "https://api.bsky.app"; 61 - PDS_BSKY_APP_VIEW_DID = "did:web:api.bsky.app"; 62 - PDS_REPORT_SERVICE_URL = "https://mod.bsky.app"; 63 - PDS_REPORT_SERVICE_DID = "did:plc:ar7c4by46qjdydhdevvrndac"; 64 - PDS_CRAWLERS = "https://bsky.network"; 65 - }; 66 - environmentFiles = [ config.age.secrets.pdsConfig.path ]; 67 - }; 68 - 69 - services.fluent-bit.settings = { 70 - parsers = [ 71 - { 72 - name = "pds_json"; 73 - format = "json"; 74 - time_key = "time"; 75 - time_strict = false; 76 - } 77 - ]; 78 - pipeline = { 79 - inputs = [ 80 - { 81 - name = "systemd"; 82 - tag = "logs.pds"; 83 - systemd_filter = "_SYSTEMD_UNIT=bluesky-pds.service"; 84 - } 85 - ]; 86 - filters = [ 87 - { 88 - name = "parser"; 89 - match = "logs.pds"; 90 - key_name = "MESSAGE"; 91 - parser = "pds_json"; 92 - } 93 - { 94 - name = "modify"; 95 - match = "logs.pds"; 96 - Rename = [ "msg _msg" ]; 97 - } 98 - ]; 99 - }; 100 - }; 101 - 102 - services.vmalert.instances."".rules.groups = [ 103 - { 104 - name = "pds-logs"; 105 - type = "vlogs"; 106 - interval = "1m"; 107 - rules = [ 108 - { 109 - record = "pds_request_count"; 110 - expr = "name:pds | stats (res.statusCode) count() as total_requests"; 111 - } 112 - { 113 - record = "pds_response_latency"; 114 - expr = "name:pds | stats avg(responseTime) avg, quantile(0.5, responseTime) p50, quantile(0.9, responseTime) p90, quantile(0.99, responseTime) p99"; 115 - } 116 - ]; 117 - } 118 - ]; 119 - 120 - # virtualisation = { 121 - # podman = { 122 - # enable = true; 123 - # dockerCompat = true; 124 - # defaultNetwork.settings.dns_enabled = true; 125 - # }; 126 - # oci-containers.containers = { 127 - # pds = { 128 - # image = "ghcr.io/bluesky-social/pds:0.4"; 129 - # autoStart = true; 130 - # environmentFiles = [ ./pds.env config.age.secrets.pdsConfig.path ]; 131 - # ports = [ "1334:1334" ]; 132 - # volumes = [ 133 - # "/var/lib/pds:/pds" 134 - # ]; 135 - # extraOptions = [ 136 - # #"--network=host" 137 - # "--label=io.containers.autoupdate=registry" 138 - # ]; 139 - # }; 140 - # }; 141 - # }; 142 - # # This is the podman auto-update systemd timer. 143 - # # If I start to rely on podman auto-update more, I should move this out of the PDS definition. 144 - # systemd.timers."podman-auto-update" = { 145 - # enable = true; 146 - # timerConfig = { 147 - # OnCalendar = "*-*-* 4:00:00"; 148 - # Persistent = true; 149 - # }; 150 - # wantedBy = [ "timers.target" ]; 151 - # }; 152 - }
+2
hosts/wolumonde/modules/perses.disabled/dashboards/.gitignore
··· 1 + # folder used to store the results of the `percli dac build` command 2 + built
+28
hosts/wolumonde/modules/perses.disabled/dashboards/go.mod
··· 1 + module dash 2 + 3 + go 1.24.2 4 + 5 + require ( 6 + github.com/beorn7/perks v1.0.1 // indirect 7 + github.com/cespare/xxhash/v2 v2.3.0 // indirect 8 + github.com/go-jose/go-jose/v4 v4.0.5 // indirect 9 + github.com/jpillora/backoff v1.0.0 // indirect 10 + github.com/muhlemmer/gu v0.3.1 // indirect 11 + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 12 + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect 13 + github.com/perses/perses v0.50.3 // indirect 14 + github.com/prometheus/client_golang v1.20.5 // indirect 15 + github.com/prometheus/client_model v0.6.1 // indirect 16 + github.com/prometheus/common v0.63.0 // indirect 17 + github.com/prometheus/procfs v0.15.1 // indirect 18 + github.com/zitadel/oidc/v3 v3.36.1 // indirect 19 + github.com/zitadel/schema v1.3.0 // indirect 20 + golang.org/x/crypto v0.36.0 // indirect 21 + golang.org/x/net v0.35.0 // indirect 22 + golang.org/x/oauth2 v0.28.0 // indirect 23 + golang.org/x/sys v0.31.0 // indirect 24 + golang.org/x/text v0.23.0 // indirect 25 + google.golang.org/protobuf v1.36.5 // indirect 26 + gopkg.in/yaml.v2 v2.4.0 // indirect 27 + gopkg.in/yaml.v3 v3.0.1 // indirect 28 + )
+45
hosts/wolumonde/modules/perses.disabled/dashboards/go.sum
··· 1 + github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 2 + github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 3 + github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 4 + github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 5 + github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= 6 + github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= 7 + github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= 8 + github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= 9 + github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM= 10 + github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM= 11 + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 12 + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 13 + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= 14 + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 15 + github.com/perses/perses v0.50.3 h1:BHlU9qkCFCUSP4HP5p9GwophWcxm5Vnu6Fsrx8Fb/+w= 16 + github.com/perses/perses v0.50.3/go.mod h1:oqfHLOrXERvEqECShqXPjHXqVukQxcoaaTM6ySRF7hU= 17 + github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= 18 + github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= 19 + github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= 20 + github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= 21 + github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= 22 + github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= 23 + github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= 24 + github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= 25 + github.com/zitadel/oidc/v3 v3.36.1 h1:1AT1NqKKEqAwx4GmKJZ9fYkWH2WIn/VKMfQ46nBtRf0= 26 + github.com/zitadel/oidc/v3 v3.36.1/go.mod h1:dApGZLvWZTHRuxmcbQlW5d2XVjVYR3vGOdq536igmTs= 27 + github.com/zitadel/schema v1.3.0 h1:kQ9W9tvIwZICCKWcMvCEweXET1OcOyGEuFbHs4o5kg0= 28 + github.com/zitadel/schema v1.3.0/go.mod h1:NptN6mkBDFvERUCvZHlvWmmME+gmZ44xzwRXwhzsbtc= 29 + golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= 30 + golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= 31 + golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= 32 + golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= 33 + golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= 34 + golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= 35 + golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= 36 + golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 37 + golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= 38 + golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= 39 + google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= 40 + google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 41 + gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 42 + gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 43 + gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 44 + gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 45 + gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+334
hosts/wolumonde/modules/perses.disabled/dashboards/wolumonde.go
··· 1 + package main 2 + 3 + import ( 4 + "flag" 5 + "time" 6 + 7 + "github.com/perses/perses/go-sdk" 8 + "github.com/perses/perses/go-sdk/common" 9 + dash "github.com/perses/perses/go-sdk/dashboard" 10 + "github.com/perses/perses/go-sdk/panel" 11 + panels "github.com/perses/perses/go-sdk/panel-group" 12 + "github.com/perses/perses/go-sdk/panel/bar" 13 + "github.com/perses/perses/go-sdk/panel/gauge" 14 + "github.com/perses/perses/go-sdk/panel/stat" 15 + "github.com/perses/perses/go-sdk/prometheus/query" 16 + 17 + timeSeries "github.com/perses/perses/go-sdk/panel/time-series" 18 + // promDs "github.com/perses/perses/go-sdk/prometheus/datasource" 19 + ) 20 + 21 + func main() { 22 + flag.Parse() 23 + exec := sdk.NewExec() 24 + 25 + var loadPanel = panels.AddPanel("load over 5 min", 26 + timeSeries.Chart( 27 + timeSeries.WithYAxis( 28 + timeSeries.YAxis{ 29 + Max: 2.0, 30 + }, 31 + ), 32 + ), 33 + panel.AddQuery( 34 + query.PromQL( 35 + "node_load5", 36 + query.SeriesNameFormat("load"), 37 + ), 38 + ), 39 + ) 40 + var cpuPanel = panels.AddPanel("cpu usage", 41 + timeSeries.Chart( 42 + timeSeries.WithYAxis( 43 + timeSeries.YAxis{ 44 + Format: &common.Format{ 45 + Unit: "percent", 46 + }, 47 + Max: 100.0, 48 + }, 49 + ), 50 + ), 51 + panel.AddQuery( 52 + query.PromQL( 53 + `sum by (cpu) (rate(node_cpu_seconds_total{mode=~"user|system"}[1m])) * 100`, 54 + query.SeriesNameFormat("cpu {{cpu}}"), 55 + ), 56 + ), 57 + ) 58 + var memoryPanel = panels.AddPanel("memory usage", 59 + timeSeries.Chart( 60 + timeSeries.WithYAxis( 61 + timeSeries.YAxis{ 62 + Format: &common.Format{ 63 + Unit: "bytes", 64 + }, 65 + Max: 4000000000, 66 + }, 67 + ), 68 + ), 69 + panel.AddQuery( 70 + query.PromQL( 71 + "node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes", 72 + query.SeriesNameFormat("current memory usage"), 73 + ), 74 + ), 75 + ) 76 + 77 + var diskPanel = panels.AddPanel("disk usage /", 78 + timeSeries.Chart( 79 + timeSeries.WithYAxis( 80 + timeSeries.YAxis{ 81 + Format: &common.Format{ 82 + Unit: "bytes", 83 + }, 84 + Max: 38000000000, 85 + }, 86 + ), 87 + ), 88 + panel.AddQuery( 89 + query.PromQL( 90 + `node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}`, 91 + query.SeriesNameFormat("disk usage"), 92 + ), 93 + ), 94 + ) 95 + 96 + // Gauge versions (percent unit) 97 + var loadGaugePanel = panels.AddPanel("load over 5 min", 98 + gauge.Chart( 99 + gauge.Format(common.Format{Unit: "percent"}), 100 + gauge.Max(100), 101 + gauge.Calculation(common.MeanCalculation), 102 + ), 103 + panel.AddQuery( 104 + query.PromQL( 105 + "node_load5 * 100 / count(count(node_cpu_seconds_total) by (cpu))", 106 + query.SeriesNameFormat("load %"), 107 + ), 108 + ), 109 + ) 110 + var cpuGaugePanel = panels.AddPanel("cpu usage", 111 + gauge.Chart( 112 + gauge.Format(common.Format{Unit: "percent"}), 113 + gauge.Max(100), 114 + gauge.Calculation(common.MeanCalculation), 115 + ), 116 + panel.AddQuery( 117 + query.PromQL( 118 + `sum by (cpu) (rate(node_cpu_seconds_total{mode=~"user|system"}[1m])) * 100`, 119 + query.SeriesNameFormat("cpu {{cpu}}"), 120 + ), 121 + ), 122 + ) 123 + var memoryGaugePanel = panels.AddPanel("memory usage", 124 + gauge.Chart( 125 + gauge.Format(common.Format{Unit: "percent"}), 126 + gauge.Max(100), 127 + gauge.Calculation(common.MeanCalculation), 128 + ), 129 + panel.AddQuery( 130 + query.PromQL( 131 + "(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) * 100 / node_memory_MemTotal_bytes", 132 + query.SeriesNameFormat("memory usage %"), 133 + ), 134 + ), 135 + ) 136 + var diskGaugePanel = panels.AddPanel("disk usage /", 137 + gauge.Chart( 138 + gauge.Format(common.Format{Unit: "percent"}), 139 + gauge.Max(100), 140 + ), 141 + panel.AddQuery( 142 + query.PromQL( 143 + `(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}) * 100 / node_filesystem_size_bytes{mountpoint="/"}`, 144 + query.SeriesNameFormat("disk usage %"), 145 + ), 146 + ), 147 + ) 148 + 149 + var resPanels = dash.AddPanelGroup("resource usage", 150 + panels.PanelsPerLine(4), 151 + loadGaugePanel, cpuGaugePanel, memoryGaugePanel, diskGaugePanel, 152 + loadPanel, cpuPanel, memoryPanel, diskPanel, 153 + ) 154 + 155 + var nginxPanel = panels.AddPanel("nginx requests / min", 156 + timeSeries.Chart( 157 + timeSeries.WithYAxis( 158 + timeSeries.YAxis{ 159 + Format: &common.Format{ 160 + Unit: "decimal", 161 + }, 162 + }, 163 + ), 164 + timeSeries.WithVisual(timeSeries.Visual{ 165 + Display: timeSeries.BarDisplay, 166 + Palette: timeSeries.Palette{ 167 + Mode: timeSeries.CategoricalMode, 168 + }, 169 + Stack: timeSeries.AllStack, 170 + }), 171 + timeSeries.WithLegend(timeSeries.Legend{ 172 + Position: timeSeries.BottomPosition, 173 + Size: timeSeries.SmallSize, 174 + }), 175 + ), 176 + panel.AddQuery( 177 + query.PromQL( 178 + "nginx_request_count", 179 + query.SeriesNameFormat("{{res.statusCode}}"), 180 + ), 181 + ), 182 + ) 183 + 184 + var nginxLatencyPanel = panels.AddPanel("nginx latency / min", 185 + timeSeries.Chart( 186 + timeSeries.WithYAxis( 187 + timeSeries.YAxis{ 188 + Format: &common.Format{ 189 + Unit: "seconds", 190 + }, 191 + Max: 0.5, 192 + }, 193 + ), 194 + ), 195 + panel.AddQuery( 196 + query.PromQL( 197 + "nginx_request_latency", 198 + query.SeriesNameFormat("{{stats_result}}"), 199 + ), 200 + ), 201 + ) 202 + 203 + var nginxPanels = dash.AddPanelGroup("nginx metrics", 204 + panels.PanelsPerLine(3), 205 + nginxPanel, 206 + nginxLatencyPanel, 207 + ) 208 + 209 + var pdsPanel = panels.AddPanel("pds requests / min", 210 + timeSeries.Chart( 211 + timeSeries.WithYAxis( 212 + timeSeries.YAxis{ 213 + Format: &common.Format{ 214 + Unit: "decimal", 215 + }, 216 + }, 217 + ), 218 + timeSeries.WithVisual(timeSeries.Visual{ 219 + Display: timeSeries.BarDisplay, 220 + Palette: timeSeries.Palette{ 221 + Mode: timeSeries.CategoricalMode, 222 + }, 223 + Stack: timeSeries.AllStack, 224 + }), 225 + timeSeries.WithLegend(timeSeries.Legend{ 226 + Position: timeSeries.BottomPosition, 227 + Size: timeSeries.SmallSize, 228 + }), 229 + ), 230 + panel.AddQuery( 231 + query.PromQL( 232 + "pds_request_count", 233 + query.SeriesNameFormat("{{res.statusCode}}"), 234 + ), 235 + ), 236 + ) 237 + 238 + var pdsLatencyPanel = panels.AddPanel("pds latency / min", 239 + timeSeries.Chart( 240 + timeSeries.WithYAxis( 241 + timeSeries.YAxis{ 242 + Format: &common.Format{ 243 + Unit: "milliseconds", 244 + }, 245 + Max: 500, 246 + }, 247 + ), 248 + ), 249 + panel.AddQuery( 250 + query.PromQL( 251 + "pds_response_latency", 252 + query.SeriesNameFormat("{{stats_result}}"), 253 + ), 254 + ), 255 + ) 256 + 257 + var pdsPanels = dash.AddPanelGroup("pds metrics", 258 + panels.PanelsPerLine(3), 259 + pdsPanel, 260 + pdsLatencyPanel, 261 + ) 262 + 263 + var anubisForgejoPanel = panels.AddPanel("anubis policy actions", 264 + bar.Chart(), 265 + panel.AddQuery( 266 + query.PromQL( 267 + "anubis_policy_results", 268 + query.SeriesNameFormat("{{action}}: {{rule}}"), 269 + ), 270 + ), 271 + ) 272 + 273 + var forgejoPanels = dash.AddPanelGroup("forgejo", 274 + panels.PanelsPerLine(3), 275 + anubisForgejoPanel, 276 + ) 277 + 278 + var gazesys_visit_panel = panels.AddPanel("gazesys visits", 279 + bar.Chart(), 280 + panel.AddQuery( 281 + query.PromQL( 282 + "gazesys_visit_real_total + gazesys_visit_fake_total", 283 + query.SeriesNameFormat("total visits"), 284 + ), 285 + ), 286 + panel.AddQuery( 287 + query.PromQL( 288 + "gazesys_visit_fake_total", 289 + query.SeriesNameFormat("(ai) bot visits"), 290 + ), 291 + ), 292 + panel.AddQuery( 293 + query.PromQL( 294 + "gazesys_visit_real_total", 295 + query.SeriesNameFormat("real visits"), 296 + ), 297 + ), 298 + ) 299 + 300 + var gazesys_pet_panel = panels.AddPanel("gazesys pet", 301 + stat.Chart( 302 + stat.Format(common.Format{ 303 + Unit: "decimal", 304 + ShortValues: true, 305 + DecimalPlaces: 0, 306 + }), 307 + ), 308 + panel.AddQuery( 309 + query.PromQL( 310 + "gazesys_pet_bounce_total", 311 + query.SeriesNameFormat("bounce count"), 312 + ), 313 + ), 314 + panel.AddQuery( 315 + query.PromQL( 316 + "gazesys_pet_distance_total", 317 + query.SeriesNameFormat("distance travelled"), 318 + ), 319 + ), 320 + ) 321 + 322 + var gazesys_panels = dash.AddPanelGroup("gazesys", 323 + panels.PanelsPerLine(3), 324 + gazesys_visit_panel, gazesys_pet_panel, 325 + ) 326 + 327 + builder, buildErr := dash.New("wolumonde", 328 + dash.ProjectName("private-infra"), 329 + dash.Duration(30*time.Minute), 330 + dash.RefreshInterval(time.Minute), 331 + resPanels, nginxPanels, pdsPanels, gazesys_panels, forgejoPanels, 332 + ) 333 + exec.BuildDashboard(builder, buildErr) 334 + }
+104
hosts/wolumonde/modules/perses.disabled/default.nix
··· 1 + { 2 + pkgs, 3 + config, 4 + ... 5 + }: 6 + let 7 + domain = "dash.gaze.systems"; 8 + port = 7412; 9 + user = "perses"; 10 + 11 + provisionFolder = "provisioning"; 12 + provisioningFolder = "${config.users.users.${user}.home}/${provisionFolder}"; 13 + 14 + persesConfig = { 15 + database.file = { 16 + folder = config.users.users.${user}.home; 17 + extension = "json"; 18 + }; 19 + provisioning.folders = [ provisioningFolder ]; 20 + security = { 21 + enable_auth = true; 22 + authentication = { 23 + providers = { 24 + enable_native = false; 25 + oidc = [ 26 + { 27 + slug_id = "pocketid"; 28 + name = "Pocket ID"; 29 + client_id = "aa583db6-e03c-4490-853a-7f2b3e089fbe"; 30 + issuer = config.services.pocket-id.settings.APP_URL; 31 + scopes = [ "openid profile email" ]; 32 + } 33 + ]; 34 + }; 35 + disable_sign_up = false; 36 + }; 37 + cookie = { 38 + same_site = "strict"; 39 + secure = true; 40 + }; 41 + }; 42 + }; 43 + persesConfigYaml = pkgs.writers.writeYAML "config.yaml" persesConfig; 44 + 45 + secrets = config.age.secrets; 46 + in 47 + { 48 + environment.systemPackages = [ pkgs.perses ]; 49 + 50 + users.users.${user} = { 51 + isNormalUser = true; 52 + group = user; 53 + home = "/var/lib/${user}"; 54 + createHome = true; 55 + uid = 1001; 56 + }; 57 + users.groups.${user} = { 58 + gid = 976; 59 + }; 60 + 61 + age.secrets.persesSecret = { 62 + file = ../../../../secrets/persesSecret.age; 63 + owner = user; 64 + group = user; 65 + }; 66 + 67 + systemd.services.perses = { 68 + description = "perses"; 69 + after = [ 70 + "network.target" 71 + "pocket-id.service" 72 + ]; 73 + requires = [ "pocket-id.service" ]; 74 + serviceConfig = { 75 + ExecStart = "${pkgs.perses}/bin/perses --config=${persesConfigYaml} --web.listen-address=:${toString port} --log.level=info"; 76 + EnvironmentFile = secrets.persesSecret.path; 77 + WorkingDirectory = config.users.users.${user}.home; 78 + }; 79 + }; 80 + systemd.services.perses.preStart = '' 81 + rm -rf ${provisioningFolder} && mkdir -p ${provisioningFolder} 82 + cp -f ${./provision}/* ${provisioningFolder} 83 + ''; 84 + 85 + security.acme.certs."gaze.systems".extraDomainNames = [ domain ]; 86 + services.nginx.virtualHosts.${domain} = { 87 + useACMEHost = "gaze.systems"; # TODO: write a module to define vhosts for subdomains 88 + quic = true; 89 + kTLS = true; 90 + forceSSL = true; 91 + locations."/" = { 92 + proxyPass = "http://localhost:${toString port}"; 93 + }; 94 + }; 95 + 96 + # scrape perses metrics 97 + services.victoriametrics.prometheusConfig.scrape_configs = [ 98 + { 99 + job_name = "perses"; 100 + metrics_path = "/metrics"; 101 + static_configs = [ { targets = [ "localhost:${toString port}" ]; } ]; 102 + } 103 + ]; 104 + }
+3
hosts/wolumonde/modules/perses.disabled/provision/1-private-infra.yaml
··· 1 + kind: Project 2 + metadata: 3 + name: private-infra
+9
hosts/wolumonde/modules/perses.disabled/provision/2-admin-role.yaml
··· 1 + - kind: GlobalRole 2 + metadata: 3 + name: admin 4 + spec: 5 + permissions: 6 + - actions: 7 + - '*' 8 + scopes: 9 + - '*'
+8
hosts/wolumonde/modules/perses.disabled/provision/3-admin-bind-role.yaml
··· 1 + - kind: GlobalRoleBinding 2 + metadata: 3 + name: admin 4 + spec: 5 + role: admin 6 + subjects: 7 + - kind: User 8 + name: 90008
+12
hosts/wolumonde/modules/perses.disabled/provision/4-victoria.yaml
··· 1 + - kind: GlobalDatasource 2 + metadata: 3 + name: victoria 4 + spec: 5 + default: true 6 + plugin: 7 + kind: PrometheusDatasource 8 + spec: 9 + proxy: 10 + kind: HTTPProxy 11 + spec: 12 + url: http://localhost:8428
+12
hosts/wolumonde/modules/perses.disabled/provision/6-guest-role.yaml
··· 1 + - kind: GlobalRole 2 + metadata: 3 + name: guest 4 + spec: 5 + permissions: 6 + - actions: 7 + - 'read' 8 + scopes: 9 + - 'Dashboard' 10 + - 'Project' 11 + - 'Datasource' 12 + - 'GlobalDatasource'
+8
hosts/wolumonde/modules/perses.disabled/provision/7-guest-role-bind.yaml
··· 1 + - kind: GlobalRoleBinding 2 + metadata: 3 + name: guest 4 + spec: 5 + role: guest 6 + subjects: 7 + - kind: User 8 + name: sorryu02
+454
hosts/wolumonde/modules/perses.disabled/provision/90-wolumonde.yaml
··· 1 + kind: Dashboard 2 + metadata: 3 + name: wolumonde 4 + createdAt: 0001-01-01T00:00:00Z 5 + updatedAt: 0001-01-01T00:00:00Z 6 + version: 0 7 + project: private-infra 8 + spec: 9 + panels: 10 + "0_0": 11 + kind: Panel 12 + spec: 13 + display: 14 + name: load over 5 min 15 + plugin: 16 + kind: GaugeChart 17 + spec: 18 + calculation: mean 19 + format: 20 + unit: percent 21 + max: 100 22 + queries: 23 + - kind: TimeSeriesQuery 24 + spec: 25 + plugin: 26 + kind: PrometheusTimeSeriesQuery 27 + spec: 28 + query: node_load5 * 100 / count(count(node_cpu_seconds_total) by (cpu)) 29 + seriesNameFormat: load % 30 + "0_1": 31 + kind: Panel 32 + spec: 33 + display: 34 + name: cpu usage 35 + plugin: 36 + kind: GaugeChart 37 + spec: 38 + calculation: mean 39 + format: 40 + unit: percent 41 + max: 100 42 + queries: 43 + - kind: TimeSeriesQuery 44 + spec: 45 + plugin: 46 + kind: PrometheusTimeSeriesQuery 47 + spec: 48 + query: sum by (cpu) (rate(node_cpu_seconds_total{mode=~"user|system"}[1m])) * 100 49 + seriesNameFormat: cpu {{cpu}} 50 + "0_2": 51 + kind: Panel 52 + spec: 53 + display: 54 + name: memory usage 55 + plugin: 56 + kind: GaugeChart 57 + spec: 58 + calculation: mean 59 + format: 60 + unit: percent 61 + max: 100 62 + queries: 63 + - kind: TimeSeriesQuery 64 + spec: 65 + plugin: 66 + kind: PrometheusTimeSeriesQuery 67 + spec: 68 + query: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) * 100 / node_memory_MemTotal_bytes 69 + seriesNameFormat: memory usage % 70 + "0_3": 71 + kind: Panel 72 + spec: 73 + display: 74 + name: disk usage / 75 + plugin: 76 + kind: GaugeChart 77 + spec: 78 + calculation: last 79 + format: 80 + unit: percent 81 + max: 100 82 + queries: 83 + - kind: TimeSeriesQuery 84 + spec: 85 + plugin: 86 + kind: PrometheusTimeSeriesQuery 87 + spec: 88 + query: (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}) * 100 / node_filesystem_size_bytes{mountpoint="/"} 89 + seriesNameFormat: disk usage % 90 + "0_4": 91 + kind: Panel 92 + spec: 93 + display: 94 + name: load over 5 min 95 + plugin: 96 + kind: TimeSeriesChart 97 + spec: 98 + yAxis: 99 + max: 2 100 + queries: 101 + - kind: TimeSeriesQuery 102 + spec: 103 + plugin: 104 + kind: PrometheusTimeSeriesQuery 105 + spec: 106 + query: node_load5 107 + seriesNameFormat: load 108 + "0_5": 109 + kind: Panel 110 + spec: 111 + display: 112 + name: cpu usage 113 + plugin: 114 + kind: TimeSeriesChart 115 + spec: 116 + yAxis: 117 + format: 118 + unit: percent 119 + max: 100 120 + queries: 121 + - kind: TimeSeriesQuery 122 + spec: 123 + plugin: 124 + kind: PrometheusTimeSeriesQuery 125 + spec: 126 + query: sum by (cpu) (rate(node_cpu_seconds_total{mode=~"user|system"}[1m])) * 100 127 + seriesNameFormat: cpu {{cpu}} 128 + "0_6": 129 + kind: Panel 130 + spec: 131 + display: 132 + name: memory usage 133 + plugin: 134 + kind: TimeSeriesChart 135 + spec: 136 + yAxis: 137 + format: 138 + unit: bytes 139 + max: 4e+09 140 + queries: 141 + - kind: TimeSeriesQuery 142 + spec: 143 + plugin: 144 + kind: PrometheusTimeSeriesQuery 145 + spec: 146 + query: node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes 147 + seriesNameFormat: current memory usage 148 + "0_7": 149 + kind: Panel 150 + spec: 151 + display: 152 + name: disk usage / 153 + plugin: 154 + kind: TimeSeriesChart 155 + spec: 156 + yAxis: 157 + format: 158 + unit: bytes 159 + max: 3.8e+10 160 + queries: 161 + - kind: TimeSeriesQuery 162 + spec: 163 + plugin: 164 + kind: PrometheusTimeSeriesQuery 165 + spec: 166 + query: node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"} 167 + seriesNameFormat: disk usage 168 + "1_0": 169 + kind: Panel 170 + spec: 171 + display: 172 + name: nginx requests / min 173 + plugin: 174 + kind: TimeSeriesChart 175 + spec: 176 + legend: 177 + position: bottom 178 + size: small 179 + yAxis: 180 + format: 181 + unit: decimal 182 + visual: 183 + display: bar 184 + palette: 185 + mode: categorical 186 + stack: all 187 + queries: 188 + - kind: TimeSeriesQuery 189 + spec: 190 + plugin: 191 + kind: PrometheusTimeSeriesQuery 192 + spec: 193 + query: nginx_request_count 194 + seriesNameFormat: '{{res.statusCode}}' 195 + "1_1": 196 + kind: Panel 197 + spec: 198 + display: 199 + name: nginx latency / min 200 + plugin: 201 + kind: TimeSeriesChart 202 + spec: 203 + yAxis: 204 + format: 205 + unit: seconds 206 + max: 0.5 207 + queries: 208 + - kind: TimeSeriesQuery 209 + spec: 210 + plugin: 211 + kind: PrometheusTimeSeriesQuery 212 + spec: 213 + query: nginx_request_latency 214 + seriesNameFormat: '{{stats_result}}' 215 + "2_0": 216 + kind: Panel 217 + spec: 218 + display: 219 + name: pds requests / min 220 + plugin: 221 + kind: TimeSeriesChart 222 + spec: 223 + legend: 224 + position: bottom 225 + size: small 226 + yAxis: 227 + format: 228 + unit: decimal 229 + visual: 230 + display: bar 231 + palette: 232 + mode: categorical 233 + stack: all 234 + queries: 235 + - kind: TimeSeriesQuery 236 + spec: 237 + plugin: 238 + kind: PrometheusTimeSeriesQuery 239 + spec: 240 + query: pds_request_count 241 + seriesNameFormat: '{{res.statusCode}}' 242 + "2_1": 243 + kind: Panel 244 + spec: 245 + display: 246 + name: pds latency / min 247 + plugin: 248 + kind: TimeSeriesChart 249 + spec: 250 + yAxis: 251 + format: 252 + unit: milliseconds 253 + max: 500 254 + queries: 255 + - kind: TimeSeriesQuery 256 + spec: 257 + plugin: 258 + kind: PrometheusTimeSeriesQuery 259 + spec: 260 + query: pds_response_latency 261 + seriesNameFormat: '{{stats_result}}' 262 + "3_0": 263 + kind: Panel 264 + spec: 265 + display: 266 + name: gazesys visits 267 + plugin: 268 + kind: BarChart 269 + spec: 270 + calculation: last 271 + queries: 272 + - kind: TimeSeriesQuery 273 + spec: 274 + plugin: 275 + kind: PrometheusTimeSeriesQuery 276 + spec: 277 + query: gazesys_visit_real_total + gazesys_visit_fake_total 278 + seriesNameFormat: total visits 279 + - kind: TimeSeriesQuery 280 + spec: 281 + plugin: 282 + kind: PrometheusTimeSeriesQuery 283 + spec: 284 + query: gazesys_visit_fake_total 285 + seriesNameFormat: (ai) bot visits 286 + - kind: TimeSeriesQuery 287 + spec: 288 + plugin: 289 + kind: PrometheusTimeSeriesQuery 290 + spec: 291 + query: gazesys_visit_real_total 292 + seriesNameFormat: real visits 293 + "3_1": 294 + kind: Panel 295 + spec: 296 + display: 297 + name: gazesys pet 298 + plugin: 299 + kind: StatChart 300 + spec: 301 + calculation: last 302 + format: 303 + unit: decimal 304 + shortValues: true 305 + queries: 306 + - kind: TimeSeriesQuery 307 + spec: 308 + plugin: 309 + kind: PrometheusTimeSeriesQuery 310 + spec: 311 + query: gazesys_pet_bounce_total 312 + seriesNameFormat: bounce count 313 + - kind: TimeSeriesQuery 314 + spec: 315 + plugin: 316 + kind: PrometheusTimeSeriesQuery 317 + spec: 318 + query: gazesys_pet_distance_total 319 + seriesNameFormat: distance travelled 320 + "4_0": 321 + kind: Panel 322 + spec: 323 + display: 324 + name: anubis policy actions 325 + plugin: 326 + kind: BarChart 327 + spec: 328 + calculation: last 329 + queries: 330 + - kind: TimeSeriesQuery 331 + spec: 332 + plugin: 333 + kind: PrometheusTimeSeriesQuery 334 + spec: 335 + query: anubis_policy_results 336 + seriesNameFormat: '{{action}}: {{rule}}' 337 + layouts: 338 + - kind: Grid 339 + spec: 340 + display: 341 + title: resource usage 342 + items: 343 + - x: 0 344 + "y": 0 345 + width: 6 346 + height: 6 347 + content: 348 + $ref: '#/spec/panels/0_0' 349 + - x: 6 350 + "y": 0 351 + width: 6 352 + height: 6 353 + content: 354 + $ref: '#/spec/panels/0_1' 355 + - x: 12 356 + "y": 0 357 + width: 6 358 + height: 6 359 + content: 360 + $ref: '#/spec/panels/0_2' 361 + - x: 18 362 + "y": 0 363 + width: 6 364 + height: 6 365 + content: 366 + $ref: '#/spec/panels/0_3' 367 + - x: 0 368 + "y": 6 369 + width: 6 370 + height: 6 371 + content: 372 + $ref: '#/spec/panels/0_4' 373 + - x: 6 374 + "y": 6 375 + width: 6 376 + height: 6 377 + content: 378 + $ref: '#/spec/panels/0_5' 379 + - x: 12 380 + "y": 6 381 + width: 6 382 + height: 6 383 + content: 384 + $ref: '#/spec/panels/0_6' 385 + - x: 18 386 + "y": 6 387 + width: 6 388 + height: 6 389 + content: 390 + $ref: '#/spec/panels/0_7' 391 + - kind: Grid 392 + spec: 393 + display: 394 + title: nginx metrics 395 + items: 396 + - x: 0 397 + "y": 0 398 + width: 8 399 + height: 6 400 + content: 401 + $ref: '#/spec/panels/1_0' 402 + - x: 8 403 + "y": 0 404 + width: 8 405 + height: 6 406 + content: 407 + $ref: '#/spec/panels/1_1' 408 + - kind: Grid 409 + spec: 410 + display: 411 + title: pds metrics 412 + items: 413 + - x: 0 414 + "y": 0 415 + width: 8 416 + height: 6 417 + content: 418 + $ref: '#/spec/panels/2_0' 419 + - x: 8 420 + "y": 0 421 + width: 8 422 + height: 6 423 + content: 424 + $ref: '#/spec/panels/2_1' 425 + - kind: Grid 426 + spec: 427 + display: 428 + title: gazesys 429 + items: 430 + - x: 0 431 + "y": 0 432 + width: 8 433 + height: 6 434 + content: 435 + $ref: '#/spec/panels/3_0' 436 + - x: 8 437 + "y": 0 438 + width: 8 439 + height: 6 440 + content: 441 + $ref: '#/spec/panels/3_1' 442 + - kind: Grid 443 + spec: 444 + display: 445 + title: forgejo 446 + items: 447 + - x: 0 448 + "y": 0 449 + width: 8 450 + height: 6 451 + content: 452 + $ref: '#/spec/panels/4_0' 453 + duration: 30m 454 + refreshInterval: 1m
-2
hosts/wolumonde/modules/perses.nix/dashboards/.gitignore
··· 1 - # folder used to store the results of the `percli dac build` command 2 - built
-28
hosts/wolumonde/modules/perses.nix/dashboards/go.mod
··· 1 - module dash 2 - 3 - go 1.24.2 4 - 5 - require ( 6 - github.com/beorn7/perks v1.0.1 // indirect 7 - github.com/cespare/xxhash/v2 v2.3.0 // indirect 8 - github.com/go-jose/go-jose/v4 v4.0.5 // indirect 9 - github.com/jpillora/backoff v1.0.0 // indirect 10 - github.com/muhlemmer/gu v0.3.1 // indirect 11 - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 12 - github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect 13 - github.com/perses/perses v0.50.3 // indirect 14 - github.com/prometheus/client_golang v1.20.5 // indirect 15 - github.com/prometheus/client_model v0.6.1 // indirect 16 - github.com/prometheus/common v0.63.0 // indirect 17 - github.com/prometheus/procfs v0.15.1 // indirect 18 - github.com/zitadel/oidc/v3 v3.36.1 // indirect 19 - github.com/zitadel/schema v1.3.0 // indirect 20 - golang.org/x/crypto v0.36.0 // indirect 21 - golang.org/x/net v0.35.0 // indirect 22 - golang.org/x/oauth2 v0.28.0 // indirect 23 - golang.org/x/sys v0.31.0 // indirect 24 - golang.org/x/text v0.23.0 // indirect 25 - google.golang.org/protobuf v1.36.5 // indirect 26 - gopkg.in/yaml.v2 v2.4.0 // indirect 27 - gopkg.in/yaml.v3 v3.0.1 // indirect 28 - )
-45
hosts/wolumonde/modules/perses.nix/dashboards/go.sum
··· 1 - github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 2 - github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 3 - github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 4 - github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 5 - github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= 6 - github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= 7 - github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= 8 - github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= 9 - github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM= 10 - github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM= 11 - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 12 - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 13 - github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= 14 - github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 15 - github.com/perses/perses v0.50.3 h1:BHlU9qkCFCUSP4HP5p9GwophWcxm5Vnu6Fsrx8Fb/+w= 16 - github.com/perses/perses v0.50.3/go.mod h1:oqfHLOrXERvEqECShqXPjHXqVukQxcoaaTM6ySRF7hU= 17 - github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= 18 - github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= 19 - github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= 20 - github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= 21 - github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= 22 - github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= 23 - github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= 24 - github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= 25 - github.com/zitadel/oidc/v3 v3.36.1 h1:1AT1NqKKEqAwx4GmKJZ9fYkWH2WIn/VKMfQ46nBtRf0= 26 - github.com/zitadel/oidc/v3 v3.36.1/go.mod h1:dApGZLvWZTHRuxmcbQlW5d2XVjVYR3vGOdq536igmTs= 27 - github.com/zitadel/schema v1.3.0 h1:kQ9W9tvIwZICCKWcMvCEweXET1OcOyGEuFbHs4o5kg0= 28 - github.com/zitadel/schema v1.3.0/go.mod h1:NptN6mkBDFvERUCvZHlvWmmME+gmZ44xzwRXwhzsbtc= 29 - golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= 30 - golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= 31 - golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= 32 - golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= 33 - golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= 34 - golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= 35 - golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= 36 - golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 37 - golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= 38 - golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= 39 - google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= 40 - google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 41 - gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 42 - gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 43 - gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 44 - gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 45 - gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-334
hosts/wolumonde/modules/perses.nix/dashboards/wolumonde.go
··· 1 - package main 2 - 3 - import ( 4 - "flag" 5 - "time" 6 - 7 - "github.com/perses/perses/go-sdk" 8 - "github.com/perses/perses/go-sdk/common" 9 - dash "github.com/perses/perses/go-sdk/dashboard" 10 - "github.com/perses/perses/go-sdk/panel" 11 - panels "github.com/perses/perses/go-sdk/panel-group" 12 - "github.com/perses/perses/go-sdk/panel/bar" 13 - "github.com/perses/perses/go-sdk/panel/gauge" 14 - "github.com/perses/perses/go-sdk/panel/stat" 15 - "github.com/perses/perses/go-sdk/prometheus/query" 16 - 17 - timeSeries "github.com/perses/perses/go-sdk/panel/time-series" 18 - // promDs "github.com/perses/perses/go-sdk/prometheus/datasource" 19 - ) 20 - 21 - func main() { 22 - flag.Parse() 23 - exec := sdk.NewExec() 24 - 25 - var loadPanel = panels.AddPanel("load over 5 min", 26 - timeSeries.Chart( 27 - timeSeries.WithYAxis( 28 - timeSeries.YAxis{ 29 - Max: 2.0, 30 - }, 31 - ), 32 - ), 33 - panel.AddQuery( 34 - query.PromQL( 35 - "node_load5", 36 - query.SeriesNameFormat("load"), 37 - ), 38 - ), 39 - ) 40 - var cpuPanel = panels.AddPanel("cpu usage", 41 - timeSeries.Chart( 42 - timeSeries.WithYAxis( 43 - timeSeries.YAxis{ 44 - Format: &common.Format{ 45 - Unit: "percent", 46 - }, 47 - Max: 100.0, 48 - }, 49 - ), 50 - ), 51 - panel.AddQuery( 52 - query.PromQL( 53 - `sum by (cpu) (rate(node_cpu_seconds_total{mode=~"user|system"}[1m])) * 100`, 54 - query.SeriesNameFormat("cpu {{cpu}}"), 55 - ), 56 - ), 57 - ) 58 - var memoryPanel = panels.AddPanel("memory usage", 59 - timeSeries.Chart( 60 - timeSeries.WithYAxis( 61 - timeSeries.YAxis{ 62 - Format: &common.Format{ 63 - Unit: "bytes", 64 - }, 65 - Max: 4000000000, 66 - }, 67 - ), 68 - ), 69 - panel.AddQuery( 70 - query.PromQL( 71 - "node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes", 72 - query.SeriesNameFormat("current memory usage"), 73 - ), 74 - ), 75 - ) 76 - 77 - var diskPanel = panels.AddPanel("disk usage /", 78 - timeSeries.Chart( 79 - timeSeries.WithYAxis( 80 - timeSeries.YAxis{ 81 - Format: &common.Format{ 82 - Unit: "bytes", 83 - }, 84 - Max: 38000000000, 85 - }, 86 - ), 87 - ), 88 - panel.AddQuery( 89 - query.PromQL( 90 - `node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}`, 91 - query.SeriesNameFormat("disk usage"), 92 - ), 93 - ), 94 - ) 95 - 96 - // Gauge versions (percent unit) 97 - var loadGaugePanel = panels.AddPanel("load over 5 min", 98 - gauge.Chart( 99 - gauge.Format(common.Format{Unit: "percent"}), 100 - gauge.Max(100), 101 - gauge.Calculation(common.MeanCalculation), 102 - ), 103 - panel.AddQuery( 104 - query.PromQL( 105 - "node_load5 * 100 / count(count(node_cpu_seconds_total) by (cpu))", 106 - query.SeriesNameFormat("load %"), 107 - ), 108 - ), 109 - ) 110 - var cpuGaugePanel = panels.AddPanel("cpu usage", 111 - gauge.Chart( 112 - gauge.Format(common.Format{Unit: "percent"}), 113 - gauge.Max(100), 114 - gauge.Calculation(common.MeanCalculation), 115 - ), 116 - panel.AddQuery( 117 - query.PromQL( 118 - `sum by (cpu) (rate(node_cpu_seconds_total{mode=~"user|system"}[1m])) * 100`, 119 - query.SeriesNameFormat("cpu {{cpu}}"), 120 - ), 121 - ), 122 - ) 123 - var memoryGaugePanel = panels.AddPanel("memory usage", 124 - gauge.Chart( 125 - gauge.Format(common.Format{Unit: "percent"}), 126 - gauge.Max(100), 127 - gauge.Calculation(common.MeanCalculation), 128 - ), 129 - panel.AddQuery( 130 - query.PromQL( 131 - "(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) * 100 / node_memory_MemTotal_bytes", 132 - query.SeriesNameFormat("memory usage %"), 133 - ), 134 - ), 135 - ) 136 - var diskGaugePanel = panels.AddPanel("disk usage /", 137 - gauge.Chart( 138 - gauge.Format(common.Format{Unit: "percent"}), 139 - gauge.Max(100), 140 - ), 141 - panel.AddQuery( 142 - query.PromQL( 143 - `(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}) * 100 / node_filesystem_size_bytes{mountpoint="/"}`, 144 - query.SeriesNameFormat("disk usage %"), 145 - ), 146 - ), 147 - ) 148 - 149 - var resPanels = dash.AddPanelGroup("resource usage", 150 - panels.PanelsPerLine(4), 151 - loadGaugePanel, cpuGaugePanel, memoryGaugePanel, diskGaugePanel, 152 - loadPanel, cpuPanel, memoryPanel, diskPanel, 153 - ) 154 - 155 - var nginxPanel = panels.AddPanel("nginx requests / min", 156 - timeSeries.Chart( 157 - timeSeries.WithYAxis( 158 - timeSeries.YAxis{ 159 - Format: &common.Format{ 160 - Unit: "decimal", 161 - }, 162 - }, 163 - ), 164 - timeSeries.WithVisual(timeSeries.Visual{ 165 - Display: timeSeries.BarDisplay, 166 - Palette: timeSeries.Palette{ 167 - Mode: timeSeries.CategoricalMode, 168 - }, 169 - Stack: timeSeries.AllStack, 170 - }), 171 - timeSeries.WithLegend(timeSeries.Legend{ 172 - Position: timeSeries.BottomPosition, 173 - Size: timeSeries.SmallSize, 174 - }), 175 - ), 176 - panel.AddQuery( 177 - query.PromQL( 178 - "nginx_request_count", 179 - query.SeriesNameFormat("{{res.statusCode}}"), 180 - ), 181 - ), 182 - ) 183 - 184 - var nginxLatencyPanel = panels.AddPanel("nginx latency / min", 185 - timeSeries.Chart( 186 - timeSeries.WithYAxis( 187 - timeSeries.YAxis{ 188 - Format: &common.Format{ 189 - Unit: "seconds", 190 - }, 191 - Max: 0.5, 192 - }, 193 - ), 194 - ), 195 - panel.AddQuery( 196 - query.PromQL( 197 - "nginx_request_latency", 198 - query.SeriesNameFormat("{{stats_result}}"), 199 - ), 200 - ), 201 - ) 202 - 203 - var nginxPanels = dash.AddPanelGroup("nginx metrics", 204 - panels.PanelsPerLine(3), 205 - nginxPanel, 206 - nginxLatencyPanel, 207 - ) 208 - 209 - var pdsPanel = panels.AddPanel("pds requests / min", 210 - timeSeries.Chart( 211 - timeSeries.WithYAxis( 212 - timeSeries.YAxis{ 213 - Format: &common.Format{ 214 - Unit: "decimal", 215 - }, 216 - }, 217 - ), 218 - timeSeries.WithVisual(timeSeries.Visual{ 219 - Display: timeSeries.BarDisplay, 220 - Palette: timeSeries.Palette{ 221 - Mode: timeSeries.CategoricalMode, 222 - }, 223 - Stack: timeSeries.AllStack, 224 - }), 225 - timeSeries.WithLegend(timeSeries.Legend{ 226 - Position: timeSeries.BottomPosition, 227 - Size: timeSeries.SmallSize, 228 - }), 229 - ), 230 - panel.AddQuery( 231 - query.PromQL( 232 - "pds_request_count", 233 - query.SeriesNameFormat("{{res.statusCode}}"), 234 - ), 235 - ), 236 - ) 237 - 238 - var pdsLatencyPanel = panels.AddPanel("pds latency / min", 239 - timeSeries.Chart( 240 - timeSeries.WithYAxis( 241 - timeSeries.YAxis{ 242 - Format: &common.Format{ 243 - Unit: "milliseconds", 244 - }, 245 - Max: 500, 246 - }, 247 - ), 248 - ), 249 - panel.AddQuery( 250 - query.PromQL( 251 - "pds_response_latency", 252 - query.SeriesNameFormat("{{stats_result}}"), 253 - ), 254 - ), 255 - ) 256 - 257 - var pdsPanels = dash.AddPanelGroup("pds metrics", 258 - panels.PanelsPerLine(3), 259 - pdsPanel, 260 - pdsLatencyPanel, 261 - ) 262 - 263 - var anubisForgejoPanel = panels.AddPanel("anubis policy actions", 264 - bar.Chart(), 265 - panel.AddQuery( 266 - query.PromQL( 267 - "anubis_policy_results", 268 - query.SeriesNameFormat("{{action}}: {{rule}}"), 269 - ), 270 - ), 271 - ) 272 - 273 - var forgejoPanels = dash.AddPanelGroup("forgejo", 274 - panels.PanelsPerLine(3), 275 - anubisForgejoPanel, 276 - ) 277 - 278 - var gazesys_visit_panel = panels.AddPanel("gazesys visits", 279 - bar.Chart(), 280 - panel.AddQuery( 281 - query.PromQL( 282 - "gazesys_visit_real_total + gazesys_visit_fake_total", 283 - query.SeriesNameFormat("total visits"), 284 - ), 285 - ), 286 - panel.AddQuery( 287 - query.PromQL( 288 - "gazesys_visit_fake_total", 289 - query.SeriesNameFormat("(ai) bot visits"), 290 - ), 291 - ), 292 - panel.AddQuery( 293 - query.PromQL( 294 - "gazesys_visit_real_total", 295 - query.SeriesNameFormat("real visits"), 296 - ), 297 - ), 298 - ) 299 - 300 - var gazesys_pet_panel = panels.AddPanel("gazesys pet", 301 - stat.Chart( 302 - stat.Format(common.Format{ 303 - Unit: "decimal", 304 - ShortValues: true, 305 - DecimalPlaces: 0, 306 - }), 307 - ), 308 - panel.AddQuery( 309 - query.PromQL( 310 - "gazesys_pet_bounce_total", 311 - query.SeriesNameFormat("bounce count"), 312 - ), 313 - ), 314 - panel.AddQuery( 315 - query.PromQL( 316 - "gazesys_pet_distance_total", 317 - query.SeriesNameFormat("distance travelled"), 318 - ), 319 - ), 320 - ) 321 - 322 - var gazesys_panels = dash.AddPanelGroup("gazesys", 323 - panels.PanelsPerLine(3), 324 - gazesys_visit_panel, gazesys_pet_panel, 325 - ) 326 - 327 - builder, buildErr := dash.New("wolumonde", 328 - dash.ProjectName("private-infra"), 329 - dash.Duration(30*time.Minute), 330 - dash.RefreshInterval(time.Minute), 331 - resPanels, nginxPanels, pdsPanels, gazesys_panels, forgejoPanels, 332 - ) 333 - exec.BuildDashboard(builder, buildErr) 334 - }
-104
hosts/wolumonde/modules/perses.nix/default.nix
··· 1 - { 2 - pkgs, 3 - config, 4 - ... 5 - }: 6 - let 7 - domain = "dash.gaze.systems"; 8 - port = 7412; 9 - user = "perses"; 10 - 11 - provisionFolder = "provisioning"; 12 - provisioningFolder = "${config.users.users.${user}.home}/${provisionFolder}"; 13 - 14 - persesConfig = { 15 - database.file = { 16 - folder = config.users.users.${user}.home; 17 - extension = "json"; 18 - }; 19 - provisioning.folders = [ provisioningFolder ]; 20 - security = { 21 - enable_auth = true; 22 - authentication = { 23 - providers = { 24 - enable_native = false; 25 - oidc = [ 26 - { 27 - slug_id = "pocketid"; 28 - name = "Pocket ID"; 29 - client_id = "aa583db6-e03c-4490-853a-7f2b3e089fbe"; 30 - issuer = config.services.pocket-id.settings.APP_URL; 31 - scopes = [ "openid profile email" ]; 32 - } 33 - ]; 34 - }; 35 - disable_sign_up = false; 36 - }; 37 - cookie = { 38 - same_site = "strict"; 39 - secure = true; 40 - }; 41 - }; 42 - }; 43 - persesConfigYaml = pkgs.writers.writeYAML "config.yaml" persesConfig; 44 - 45 - secrets = config.age.secrets; 46 - in 47 - { 48 - environment.systemPackages = [ pkgs.perses ]; 49 - 50 - users.users.${user} = { 51 - isNormalUser = true; 52 - group = user; 53 - home = "/var/lib/${user}"; 54 - createHome = true; 55 - uid = 1001; 56 - }; 57 - users.groups.${user} = { 58 - gid = 976; 59 - }; 60 - 61 - age.secrets.persesSecret = { 62 - file = ../../../../secrets/persesSecret.age; 63 - owner = user; 64 - group = user; 65 - }; 66 - 67 - systemd.services.perses = { 68 - description = "perses"; 69 - after = [ 70 - "network.target" 71 - "pocket-id.service" 72 - ]; 73 - requires = [ "pocket-id.service" ]; 74 - serviceConfig = { 75 - ExecStart = "${pkgs.perses}/bin/perses --config=${persesConfigYaml} --web.listen-address=:${toString port} --log.level=info"; 76 - EnvironmentFile = secrets.persesSecret.path; 77 - WorkingDirectory = config.users.users.${user}.home; 78 - }; 79 - }; 80 - systemd.services.perses.preStart = '' 81 - rm -rf ${provisioningFolder} && mkdir -p ${provisioningFolder} 82 - cp -f ${./provision}/* ${provisioningFolder} 83 - ''; 84 - 85 - security.acme.certs."gaze.systems".extraDomainNames = [ domain ]; 86 - services.nginx.virtualHosts.${domain} = { 87 - useACMEHost = "gaze.systems"; # TODO: write a module to define vhosts for subdomains 88 - quic = true; 89 - kTLS = true; 90 - forceSSL = true; 91 - locations."/" = { 92 - proxyPass = "http://localhost:${toString port}"; 93 - }; 94 - }; 95 - 96 - # scrape perses metrics 97 - services.victoriametrics.prometheusConfig.scrape_configs = [ 98 - { 99 - job_name = "perses"; 100 - metrics_path = "/metrics"; 101 - static_configs = [ { targets = [ "localhost:${toString port}" ]; } ]; 102 - } 103 - ]; 104 - }
-3
hosts/wolumonde/modules/perses.nix/provision/1-private-infra.yaml
··· 1 - kind: Project 2 - metadata: 3 - name: private-infra
-9
hosts/wolumonde/modules/perses.nix/provision/2-admin-role.yaml
··· 1 - - kind: GlobalRole 2 - metadata: 3 - name: admin 4 - spec: 5 - permissions: 6 - - actions: 7 - - '*' 8 - scopes: 9 - - '*'
-8
hosts/wolumonde/modules/perses.nix/provision/3-admin-bind-role.yaml
··· 1 - - kind: GlobalRoleBinding 2 - metadata: 3 - name: admin 4 - spec: 5 - role: admin 6 - subjects: 7 - - kind: User 8 - name: 90008
-12
hosts/wolumonde/modules/perses.nix/provision/4-victoria.yaml
··· 1 - - kind: GlobalDatasource 2 - metadata: 3 - name: victoria 4 - spec: 5 - default: true 6 - plugin: 7 - kind: PrometheusDatasource 8 - spec: 9 - proxy: 10 - kind: HTTPProxy 11 - spec: 12 - url: http://localhost:8428
-12
hosts/wolumonde/modules/perses.nix/provision/6-guest-role.yaml
··· 1 - - kind: GlobalRole 2 - metadata: 3 - name: guest 4 - spec: 5 - permissions: 6 - - actions: 7 - - 'read' 8 - scopes: 9 - - 'Dashboard' 10 - - 'Project' 11 - - 'Datasource' 12 - - 'GlobalDatasource'
-8
hosts/wolumonde/modules/perses.nix/provision/7-guest-role-bind.yaml
··· 1 - - kind: GlobalRoleBinding 2 - metadata: 3 - name: guest 4 - spec: 5 - role: guest 6 - subjects: 7 - - kind: User 8 - name: sorryu02
-454
hosts/wolumonde/modules/perses.nix/provision/90-wolumonde.yaml
··· 1 - kind: Dashboard 2 - metadata: 3 - name: wolumonde 4 - createdAt: 0001-01-01T00:00:00Z 5 - updatedAt: 0001-01-01T00:00:00Z 6 - version: 0 7 - project: private-infra 8 - spec: 9 - panels: 10 - "0_0": 11 - kind: Panel 12 - spec: 13 - display: 14 - name: load over 5 min 15 - plugin: 16 - kind: GaugeChart 17 - spec: 18 - calculation: mean 19 - format: 20 - unit: percent 21 - max: 100 22 - queries: 23 - - kind: TimeSeriesQuery 24 - spec: 25 - plugin: 26 - kind: PrometheusTimeSeriesQuery 27 - spec: 28 - query: node_load5 * 100 / count(count(node_cpu_seconds_total) by (cpu)) 29 - seriesNameFormat: load % 30 - "0_1": 31 - kind: Panel 32 - spec: 33 - display: 34 - name: cpu usage 35 - plugin: 36 - kind: GaugeChart 37 - spec: 38 - calculation: mean 39 - format: 40 - unit: percent 41 - max: 100 42 - queries: 43 - - kind: TimeSeriesQuery 44 - spec: 45 - plugin: 46 - kind: PrometheusTimeSeriesQuery 47 - spec: 48 - query: sum by (cpu) (rate(node_cpu_seconds_total{mode=~"user|system"}[1m])) * 100 49 - seriesNameFormat: cpu {{cpu}} 50 - "0_2": 51 - kind: Panel 52 - spec: 53 - display: 54 - name: memory usage 55 - plugin: 56 - kind: GaugeChart 57 - spec: 58 - calculation: mean 59 - format: 60 - unit: percent 61 - max: 100 62 - queries: 63 - - kind: TimeSeriesQuery 64 - spec: 65 - plugin: 66 - kind: PrometheusTimeSeriesQuery 67 - spec: 68 - query: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) * 100 / node_memory_MemTotal_bytes 69 - seriesNameFormat: memory usage % 70 - "0_3": 71 - kind: Panel 72 - spec: 73 - display: 74 - name: disk usage / 75 - plugin: 76 - kind: GaugeChart 77 - spec: 78 - calculation: last 79 - format: 80 - unit: percent 81 - max: 100 82 - queries: 83 - - kind: TimeSeriesQuery 84 - spec: 85 - plugin: 86 - kind: PrometheusTimeSeriesQuery 87 - spec: 88 - query: (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}) * 100 / node_filesystem_size_bytes{mountpoint="/"} 89 - seriesNameFormat: disk usage % 90 - "0_4": 91 - kind: Panel 92 - spec: 93 - display: 94 - name: load over 5 min 95 - plugin: 96 - kind: TimeSeriesChart 97 - spec: 98 - yAxis: 99 - max: 2 100 - queries: 101 - - kind: TimeSeriesQuery 102 - spec: 103 - plugin: 104 - kind: PrometheusTimeSeriesQuery 105 - spec: 106 - query: node_load5 107 - seriesNameFormat: load 108 - "0_5": 109 - kind: Panel 110 - spec: 111 - display: 112 - name: cpu usage 113 - plugin: 114 - kind: TimeSeriesChart 115 - spec: 116 - yAxis: 117 - format: 118 - unit: percent 119 - max: 100 120 - queries: 121 - - kind: TimeSeriesQuery 122 - spec: 123 - plugin: 124 - kind: PrometheusTimeSeriesQuery 125 - spec: 126 - query: sum by (cpu) (rate(node_cpu_seconds_total{mode=~"user|system"}[1m])) * 100 127 - seriesNameFormat: cpu {{cpu}} 128 - "0_6": 129 - kind: Panel 130 - spec: 131 - display: 132 - name: memory usage 133 - plugin: 134 - kind: TimeSeriesChart 135 - spec: 136 - yAxis: 137 - format: 138 - unit: bytes 139 - max: 4e+09 140 - queries: 141 - - kind: TimeSeriesQuery 142 - spec: 143 - plugin: 144 - kind: PrometheusTimeSeriesQuery 145 - spec: 146 - query: node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes 147 - seriesNameFormat: current memory usage 148 - "0_7": 149 - kind: Panel 150 - spec: 151 - display: 152 - name: disk usage / 153 - plugin: 154 - kind: TimeSeriesChart 155 - spec: 156 - yAxis: 157 - format: 158 - unit: bytes 159 - max: 3.8e+10 160 - queries: 161 - - kind: TimeSeriesQuery 162 - spec: 163 - plugin: 164 - kind: PrometheusTimeSeriesQuery 165 - spec: 166 - query: node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"} 167 - seriesNameFormat: disk usage 168 - "1_0": 169 - kind: Panel 170 - spec: 171 - display: 172 - name: nginx requests / min 173 - plugin: 174 - kind: TimeSeriesChart 175 - spec: 176 - legend: 177 - position: bottom 178 - size: small 179 - yAxis: 180 - format: 181 - unit: decimal 182 - visual: 183 - display: bar 184 - palette: 185 - mode: categorical 186 - stack: all 187 - queries: 188 - - kind: TimeSeriesQuery 189 - spec: 190 - plugin: 191 - kind: PrometheusTimeSeriesQuery 192 - spec: 193 - query: nginx_request_count 194 - seriesNameFormat: '{{res.statusCode}}' 195 - "1_1": 196 - kind: Panel 197 - spec: 198 - display: 199 - name: nginx latency / min 200 - plugin: 201 - kind: TimeSeriesChart 202 - spec: 203 - yAxis: 204 - format: 205 - unit: seconds 206 - max: 0.5 207 - queries: 208 - - kind: TimeSeriesQuery 209 - spec: 210 - plugin: 211 - kind: PrometheusTimeSeriesQuery 212 - spec: 213 - query: nginx_request_latency 214 - seriesNameFormat: '{{stats_result}}' 215 - "2_0": 216 - kind: Panel 217 - spec: 218 - display: 219 - name: pds requests / min 220 - plugin: 221 - kind: TimeSeriesChart 222 - spec: 223 - legend: 224 - position: bottom 225 - size: small 226 - yAxis: 227 - format: 228 - unit: decimal 229 - visual: 230 - display: bar 231 - palette: 232 - mode: categorical 233 - stack: all 234 - queries: 235 - - kind: TimeSeriesQuery 236 - spec: 237 - plugin: 238 - kind: PrometheusTimeSeriesQuery 239 - spec: 240 - query: pds_request_count 241 - seriesNameFormat: '{{res.statusCode}}' 242 - "2_1": 243 - kind: Panel 244 - spec: 245 - display: 246 - name: pds latency / min 247 - plugin: 248 - kind: TimeSeriesChart 249 - spec: 250 - yAxis: 251 - format: 252 - unit: milliseconds 253 - max: 500 254 - queries: 255 - - kind: TimeSeriesQuery 256 - spec: 257 - plugin: 258 - kind: PrometheusTimeSeriesQuery 259 - spec: 260 - query: pds_response_latency 261 - seriesNameFormat: '{{stats_result}}' 262 - "3_0": 263 - kind: Panel 264 - spec: 265 - display: 266 - name: gazesys visits 267 - plugin: 268 - kind: BarChart 269 - spec: 270 - calculation: last 271 - queries: 272 - - kind: TimeSeriesQuery 273 - spec: 274 - plugin: 275 - kind: PrometheusTimeSeriesQuery 276 - spec: 277 - query: gazesys_visit_real_total + gazesys_visit_fake_total 278 - seriesNameFormat: total visits 279 - - kind: TimeSeriesQuery 280 - spec: 281 - plugin: 282 - kind: PrometheusTimeSeriesQuery 283 - spec: 284 - query: gazesys_visit_fake_total 285 - seriesNameFormat: (ai) bot visits 286 - - kind: TimeSeriesQuery 287 - spec: 288 - plugin: 289 - kind: PrometheusTimeSeriesQuery 290 - spec: 291 - query: gazesys_visit_real_total 292 - seriesNameFormat: real visits 293 - "3_1": 294 - kind: Panel 295 - spec: 296 - display: 297 - name: gazesys pet 298 - plugin: 299 - kind: StatChart 300 - spec: 301 - calculation: last 302 - format: 303 - unit: decimal 304 - shortValues: true 305 - queries: 306 - - kind: TimeSeriesQuery 307 - spec: 308 - plugin: 309 - kind: PrometheusTimeSeriesQuery 310 - spec: 311 - query: gazesys_pet_bounce_total 312 - seriesNameFormat: bounce count 313 - - kind: TimeSeriesQuery 314 - spec: 315 - plugin: 316 - kind: PrometheusTimeSeriesQuery 317 - spec: 318 - query: gazesys_pet_distance_total 319 - seriesNameFormat: distance travelled 320 - "4_0": 321 - kind: Panel 322 - spec: 323 - display: 324 - name: anubis policy actions 325 - plugin: 326 - kind: BarChart 327 - spec: 328 - calculation: last 329 - queries: 330 - - kind: TimeSeriesQuery 331 - spec: 332 - plugin: 333 - kind: PrometheusTimeSeriesQuery 334 - spec: 335 - query: anubis_policy_results 336 - seriesNameFormat: '{{action}}: {{rule}}' 337 - layouts: 338 - - kind: Grid 339 - spec: 340 - display: 341 - title: resource usage 342 - items: 343 - - x: 0 344 - "y": 0 345 - width: 6 346 - height: 6 347 - content: 348 - $ref: '#/spec/panels/0_0' 349 - - x: 6 350 - "y": 0 351 - width: 6 352 - height: 6 353 - content: 354 - $ref: '#/spec/panels/0_1' 355 - - x: 12 356 - "y": 0 357 - width: 6 358 - height: 6 359 - content: 360 - $ref: '#/spec/panels/0_2' 361 - - x: 18 362 - "y": 0 363 - width: 6 364 - height: 6 365 - content: 366 - $ref: '#/spec/panels/0_3' 367 - - x: 0 368 - "y": 6 369 - width: 6 370 - height: 6 371 - content: 372 - $ref: '#/spec/panels/0_4' 373 - - x: 6 374 - "y": 6 375 - width: 6 376 - height: 6 377 - content: 378 - $ref: '#/spec/panels/0_5' 379 - - x: 12 380 - "y": 6 381 - width: 6 382 - height: 6 383 - content: 384 - $ref: '#/spec/panels/0_6' 385 - - x: 18 386 - "y": 6 387 - width: 6 388 - height: 6 389 - content: 390 - $ref: '#/spec/panels/0_7' 391 - - kind: Grid 392 - spec: 393 - display: 394 - title: nginx metrics 395 - items: 396 - - x: 0 397 - "y": 0 398 - width: 8 399 - height: 6 400 - content: 401 - $ref: '#/spec/panels/1_0' 402 - - x: 8 403 - "y": 0 404 - width: 8 405 - height: 6 406 - content: 407 - $ref: '#/spec/panels/1_1' 408 - - kind: Grid 409 - spec: 410 - display: 411 - title: pds metrics 412 - items: 413 - - x: 0 414 - "y": 0 415 - width: 8 416 - height: 6 417 - content: 418 - $ref: '#/spec/panels/2_0' 419 - - x: 8 420 - "y": 0 421 - width: 8 422 - height: 6 423 - content: 424 - $ref: '#/spec/panels/2_1' 425 - - kind: Grid 426 - spec: 427 - display: 428 - title: gazesys 429 - items: 430 - - x: 0 431 - "y": 0 432 - width: 8 433 - height: 6 434 - content: 435 - $ref: '#/spec/panels/3_0' 436 - - x: 8 437 - "y": 0 438 - width: 8 439 - height: 6 440 - content: 441 - $ref: '#/spec/panels/3_1' 442 - - kind: Grid 443 - spec: 444 - display: 445 - title: forgejo 446 - items: 447 - - x: 0 448 - "y": 0 449 - width: 8 450 - height: 6 451 - content: 452 - $ref: '#/spec/panels/4_0' 453 - duration: 30m 454 - refreshInterval: 1m
+30
hosts/wolumonde/modules/pocket-id.disabled
··· 1 + { config, ... }: 2 + let 3 + domain = "id.gaze.systems"; 4 + in 5 + { 6 + services.pocket-id = { 7 + enable = true; 8 + settings = { 9 + APP_URL = "https://${domain}"; 10 + TRUST_PROXY = true; 11 + PORT = 6823; 12 + ANALYTICS_DISABLED = true; 13 + }; 14 + }; 15 + 16 + security.acme.certs."gaze.systems".extraDomainNames = [ domain ]; 17 + 18 + services.nginx.virtualHosts.${domain} = { 19 + useACMEHost = "gaze.systems"; 20 + forceSSL = true; 21 + quic = true; 22 + kTLS = true; 23 + locations."/".proxyPass = "http://localhost:${toString config.services.pocket-id.settings.PORT}"; 24 + locations."/".extraConfig = '' 25 + proxy_busy_buffers_size 512k; 26 + proxy_buffers 4 512k; 27 + proxy_buffer_size 256k; 28 + ''; 29 + }; 30 + }
-30
hosts/wolumonde/modules/pocket-id.nix
··· 1 - { config, ... }: 2 - let 3 - domain = "id.gaze.systems"; 4 - in 5 - { 6 - services.pocket-id = { 7 - enable = true; 8 - settings = { 9 - APP_URL = "https://${domain}"; 10 - TRUST_PROXY = true; 11 - PORT = 6823; 12 - ANALYTICS_DISABLED = true; 13 - }; 14 - }; 15 - 16 - security.acme.certs."gaze.systems".extraDomainNames = [ domain ]; 17 - 18 - services.nginx.virtualHosts.${domain} = { 19 - useACMEHost = "gaze.systems"; 20 - forceSSL = true; 21 - quic = true; 22 - kTLS = true; 23 - locations."/".proxyPass = "http://localhost:${toString config.services.pocket-id.settings.PORT}"; 24 - locations."/".extraConfig = '' 25 - proxy_busy_buffers_size 512k; 26 - proxy_buffers 4 512k; 27 - proxy_buffer_size 256k; 28 - ''; 29 - }; 30 - }
-1
hosts/wolumonde/modules/secrets.nix
··· 1 1 { lib, ... }: 2 2 { 3 3 # age.secrets.bernbotToken.file = ../../../secrets/bernbotToken.age; 4 - age.secrets.websiteConfig.file = ../../../secrets/websiteConfig.age; 5 4 age.secrets.pdsConfig.file = ../../../secrets/pdsConfig.age; 6 5 # age.secrets.wgWolumondeKey = { 7 6 # file = ../../../secrets/wgWolumondeKey.age;
+6
hosts/wolumonde/modules/tangled.disabled/default.nix
··· 1 + { 2 + imports = [ 3 + ./knot.nix 4 + ./spindle.nix 5 + ]; 6 + }
+39
hosts/wolumonde/modules/tangled.disabled/knot.nix
··· 1 + { 2 + config, 3 + inputs, 4 + terra, 5 + ... 6 + }: 7 + let 8 + knotCfg = config.services.tangled.knot; 9 + in 10 + { 11 + imports = [ 12 + "${inputs.tangled}/nix/modules/knot.nix" 13 + ]; 14 + 15 + services.tangled.knot = { 16 + enable = true; 17 + package = terra.tangled-knot; 18 + gitUser = "git"; 19 + motdFile = ./motd; 20 + server = { 21 + listenAddr = "0.0.0.0:7777"; 22 + hostname = "knot.gaze.systems"; 23 + owner = "did:plc:dfl62fgb7wtjj3fcbb72naae"; 24 + }; 25 + }; 26 + 27 + security.acme.certs."gaze.systems".extraDomainNames = [ knotCfg.server.hostname ]; 28 + 29 + services.nginx.virtualHosts.${knotCfg.server.hostname} = { 30 + useACMEHost = "gaze.systems"; 31 + forceSSL = true; 32 + quic = true; 33 + kTLS = true; 34 + locations."/" = { 35 + proxyPass = "http://${knotCfg.server.listenAddr}"; 36 + proxyWebsockets = true; 37 + }; 38 + }; 39 + }
+5
hosts/wolumonde/modules/tangled.disabled/motd
··· 1 + 2 + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ 3 + ┃ *paws at your commits* arf :3c ┃ 4 + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ 5 +
+64
hosts/wolumonde/modules/tangled.disabled/spindle.nix
··· 1 + { 2 + lib, 3 + config, 4 + inputs, 5 + terra, 6 + ... 7 + }: 8 + let 9 + spindleCfg = config.services.tangled.spindle; 10 + in 11 + { 12 + imports = [ 13 + "${inputs.tangled}/nix/modules/spindle.nix" 14 + ]; 15 + 16 + services.tangled.spindle = { 17 + enable = true; 18 + package = terra.tangled-spindle; 19 + server = { 20 + listenAddr = "0.0.0.0:7391"; 21 + hostname = "spindle.gaze.systems"; 22 + owner = "did:plc:dfl62fgb7wtjj3fcbb72naae"; 23 + # secrets = { 24 + # provider = "openbao"; 25 + # openbao.proxyAddr = "http://spindle.bao.lan.gaze.systems"; 26 + # }; 27 + secrets.provider = "sqlite"; 28 + }; 29 + }; 30 + users.users.spindle = { 31 + group = "spindle"; 32 + isSystemUser = true; 33 + }; 34 + users.groups.spindle = { }; 35 + users.groups.podman.members = [ "spindle" ]; 36 + systemd.services.spindle = { 37 + # after = lib.mkForce [ "network.target" "openbao-proxy-spindle.service" ]; 38 + serviceConfig = { 39 + User = "spindle"; 40 + Group = "spindle"; 41 + }; 42 + }; 43 + 44 + security.acme.certs."gaze.systems".extraDomainNames = [ spindleCfg.server.hostname ]; 45 + 46 + services.nginx.virtualHosts.${spindleCfg.server.hostname} = { 47 + useACMEHost = "gaze.systems"; 48 + forceSSL = true; 49 + quic = true; 50 + kTLS = true; 51 + locations."/" = { 52 + proxyPass = "http://${spindleCfg.server.listenAddr}"; 53 + proxyWebsockets = true; 54 + }; 55 + }; 56 + 57 + virtualisation.docker.enable = lib.mkForce false; 58 + virtualisation.podman = { 59 + enable = true; 60 + autoPrune.enable = true; 61 + dockerCompat = true; 62 + dockerSocket.enable = true; 63 + }; 64 + }
-6
hosts/wolumonde/modules/tangled.nix/default.nix
··· 1 - { 2 - imports = [ 3 - ./knot.nix 4 - ./spindle.nix 5 - ]; 6 - }
-39
hosts/wolumonde/modules/tangled.nix/knot.nix
··· 1 - { 2 - config, 3 - inputs, 4 - terra, 5 - ... 6 - }: 7 - let 8 - knotCfg = config.services.tangled.knot; 9 - in 10 - { 11 - imports = [ 12 - "${inputs.tangled}/nix/modules/knot.nix" 13 - ]; 14 - 15 - services.tangled.knot = { 16 - enable = true; 17 - package = terra.tangled-knot; 18 - gitUser = "git"; 19 - motdFile = ./motd; 20 - server = { 21 - listenAddr = "0.0.0.0:7777"; 22 - hostname = "knot.gaze.systems"; 23 - owner = "did:plc:dfl62fgb7wtjj3fcbb72naae"; 24 - }; 25 - }; 26 - 27 - security.acme.certs."gaze.systems".extraDomainNames = [ knotCfg.server.hostname ]; 28 - 29 - services.nginx.virtualHosts.${knotCfg.server.hostname} = { 30 - useACMEHost = "gaze.systems"; 31 - forceSSL = true; 32 - quic = true; 33 - kTLS = true; 34 - locations."/" = { 35 - proxyPass = "http://${knotCfg.server.listenAddr}"; 36 - proxyWebsockets = true; 37 - }; 38 - }; 39 - }
-5
hosts/wolumonde/modules/tangled.nix/motd
··· 1 - 2 - ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ 3 - ┃ *paws at your commits* arf :3c ┃ 4 - ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ 5 -
-64
hosts/wolumonde/modules/tangled.nix/spindle.nix
··· 1 - { 2 - lib, 3 - config, 4 - inputs, 5 - terra, 6 - ... 7 - }: 8 - let 9 - spindleCfg = config.services.tangled.spindle; 10 - in 11 - { 12 - imports = [ 13 - "${inputs.tangled}/nix/modules/spindle.nix" 14 - ]; 15 - 16 - services.tangled.spindle = { 17 - enable = true; 18 - package = terra.tangled-spindle; 19 - server = { 20 - listenAddr = "0.0.0.0:7391"; 21 - hostname = "spindle.gaze.systems"; 22 - owner = "did:plc:dfl62fgb7wtjj3fcbb72naae"; 23 - # secrets = { 24 - # provider = "openbao"; 25 - # openbao.proxyAddr = "http://spindle.bao.lan.gaze.systems"; 26 - # }; 27 - secrets.provider = "sqlite"; 28 - }; 29 - }; 30 - users.users.spindle = { 31 - group = "spindle"; 32 - isSystemUser = true; 33 - }; 34 - users.groups.spindle = { }; 35 - users.groups.podman.members = [ "spindle" ]; 36 - systemd.services.spindle = { 37 - # after = lib.mkForce [ "network.target" "openbao-proxy-spindle.service" ]; 38 - serviceConfig = { 39 - User = "spindle"; 40 - Group = "spindle"; 41 - }; 42 - }; 43 - 44 - security.acme.certs."gaze.systems".extraDomainNames = [ spindleCfg.server.hostname ]; 45 - 46 - services.nginx.virtualHosts.${spindleCfg.server.hostname} = { 47 - useACMEHost = "gaze.systems"; 48 - forceSSL = true; 49 - quic = true; 50 - kTLS = true; 51 - locations."/" = { 52 - proxyPass = "http://${spindleCfg.server.listenAddr}"; 53 - proxyWebsockets = true; 54 - }; 55 - }; 56 - 57 - virtualisation.docker.enable = lib.mkForce false; 58 - virtualisation.podman = { 59 - enable = true; 60 - autoPrune.enable = true; 61 - dockerCompat = true; 62 - dockerSocket.enable = true; 63 - }; 64 - }
+55
hosts/wolumonde/modules/unbound.disabled
··· 1 + { config, lib, ... }: 2 + let 3 + cfg = config.services.unbound.settings; 4 + in 5 + { 6 + services.unbound = { 7 + enable = true; 8 + enableRootTrustAnchor = false; 9 + resolveLocalQueries = false; 10 + checkconf = lib.mkForce true; 11 + settings = { 12 + server = { 13 + interface = [ "0.0.0.0" ]; 14 + port = 7272; 15 + 16 + access-control = [ 17 + "0.0.0.0/0 refuse" # lets explicitly refuse any queries 18 + "100.84.0.0/16 allow" # only allow queries from netbird 19 + ]; 20 + 21 + hide-identity = true; 22 + hide-version = true; 23 + harden-glue = true; 24 + harden-referral-path = true; 25 + use-caps-for-id = true; 26 + 27 + ratelimit = 10; 28 + ratelimit-slabs = 4; 29 + ratelimit-size = "4m"; 30 + 31 + unwanted-reply-threshold = 10000; 32 + do-not-query-localhost = true; 33 + deny-any = true; 34 + 35 + prefetch = true; 36 + prefetch-key = true; 37 + }; 38 + forward-zone = [ 39 + { 40 + name = "."; 41 + forward-addr = [ 42 + "1.1.1.1" 43 + "1.0.0.1" 44 + "9.9.9.9" 45 + "8.8.8.8" 46 + ]; 47 + } 48 + ]; 49 + }; 50 + }; 51 + networking.firewall = { 52 + allowedTCPPorts = [ cfg.server.port ]; 53 + allowedUDPPorts = [ cfg.server.port ]; 54 + }; 55 + }
-55
hosts/wolumonde/modules/unbound.nix
··· 1 - { config, lib, ... }: 2 - let 3 - cfg = config.services.unbound.settings; 4 - in 5 - { 6 - services.unbound = { 7 - enable = true; 8 - enableRootTrustAnchor = false; 9 - resolveLocalQueries = false; 10 - checkconf = lib.mkForce true; 11 - settings = { 12 - server = { 13 - interface = [ "0.0.0.0" ]; 14 - port = 7272; 15 - 16 - access-control = [ 17 - "0.0.0.0/0 refuse" # lets explicitly refuse any queries 18 - "100.84.0.0/16 allow" # only allow queries from netbird 19 - ]; 20 - 21 - hide-identity = true; 22 - hide-version = true; 23 - harden-glue = true; 24 - harden-referral-path = true; 25 - use-caps-for-id = true; 26 - 27 - ratelimit = 10; 28 - ratelimit-slabs = 4; 29 - ratelimit-size = "4m"; 30 - 31 - unwanted-reply-threshold = 10000; 32 - do-not-query-localhost = true; 33 - deny-any = true; 34 - 35 - prefetch = true; 36 - prefetch-key = true; 37 - }; 38 - forward-zone = [ 39 - { 40 - name = "."; 41 - forward-addr = [ 42 - "1.1.1.1" 43 - "1.0.0.1" 44 - "9.9.9.9" 45 - "8.8.8.8" 46 - ]; 47 - } 48 - ]; 49 - }; 50 - }; 51 - networking.firewall = { 52 - allowedTCPPorts = [ cfg.server.port ]; 53 - allowedUDPPorts = [ cfg.server.port ]; 54 - }; 55 - }
+70
hosts/wolumonde/modules/victoria.disabled
··· 1 + { lib, config, ... }: 2 + let 3 + # syslogUdp = 5113; 4 + metricsPort = 8428; 5 + logsPort = 9428; 6 + in 7 + { 8 + services.victoriametrics = { 9 + enable = true; 10 + listenAddress = ":${toString metricsPort}"; 11 + }; 12 + 13 + services.victorialogs = { 14 + enable = true; 15 + listenAddress = ":${toString logsPort}"; 16 + # extraOptions = ["-syslog.listenAddr.udp=:${toString syslogUdp}" "-journald.maxRequestSize=1024000000"]; 17 + }; 18 + 19 + services.vmalert.instances."" = { 20 + enable = true; 21 + settings = 22 + let 23 + l = "http://localhost"; 24 + in 25 + { 26 + "datasource.url" = "${l}${config.services.victorialogs.listenAddress}"; 27 + "remoteWrite.url" = "${l}${config.services.victoriametrics.listenAddress}"; 28 + "remoteRead.url" = "${l}${config.services.victoriametrics.listenAddress}"; 29 + "rule.defaultRuleType" = "vlogs"; 30 + }; 31 + }; 32 + 33 + services.fluent-bit.settings.pipeline.outputs = [ 34 + # write metrics to victoriametrics via prometheus 35 + { 36 + name = "prometheus_remote_write"; 37 + match = "metrics.*"; 38 + port = lib.removePrefix ":" config.services.victoriametrics.listenAddress; 39 + uri = "/api/v1/write"; 40 + } 41 + { 42 + name = "http"; 43 + match = "logs.*"; 44 + port = lib.removePrefix ":" config.services.victorialogs.listenAddress; 45 + uri = "/insert/jsonline?_stream_fields=stream&_msg_field=log&_time_field=date"; 46 + format = "json_lines"; 47 + json_date_format = "iso8601"; 48 + } 49 + # write logs via syslog 50 + # { 51 + # name = "syslog"; 52 + # match = "*.log"; 53 + # port = syslogUdp; 54 + # syslog_maxsize = 4096; 55 + # syslog_severity_key = "severity"; 56 + # syslog_facility_key = "facility"; 57 + # syslog_hostname_key = "hostname"; 58 + # syslog_appname_key = "appname"; 59 + # syslog_procid_key = "procid"; 60 + # syslog_msgid_key = "msgid"; 61 + # syslog_sd_key = "sd"; 62 + # syslog_message_key = "message"; 63 + # } 64 + ]; 65 + 66 + # services.journald.upload = { 67 + # enable = true; 68 + # settings.Upload.URL = "http://localhost${config.services.victorialogs.listenAddress}/insert/journald"; 69 + # }; 70 + }
-70
hosts/wolumonde/modules/victoria.nix
··· 1 - { lib, config, ... }: 2 - let 3 - # syslogUdp = 5113; 4 - metricsPort = 8428; 5 - logsPort = 9428; 6 - in 7 - { 8 - services.victoriametrics = { 9 - enable = true; 10 - listenAddress = ":${toString metricsPort}"; 11 - }; 12 - 13 - services.victorialogs = { 14 - enable = true; 15 - listenAddress = ":${toString logsPort}"; 16 - # extraOptions = ["-syslog.listenAddr.udp=:${toString syslogUdp}" "-journald.maxRequestSize=1024000000"]; 17 - }; 18 - 19 - services.vmalert.instances."" = { 20 - enable = true; 21 - settings = 22 - let 23 - l = "http://localhost"; 24 - in 25 - { 26 - "datasource.url" = "${l}${config.services.victorialogs.listenAddress}"; 27 - "remoteWrite.url" = "${l}${config.services.victoriametrics.listenAddress}"; 28 - "remoteRead.url" = "${l}${config.services.victoriametrics.listenAddress}"; 29 - "rule.defaultRuleType" = "vlogs"; 30 - }; 31 - }; 32 - 33 - services.fluent-bit.settings.pipeline.outputs = [ 34 - # write metrics to victoriametrics via prometheus 35 - { 36 - name = "prometheus_remote_write"; 37 - match = "metrics.*"; 38 - port = lib.removePrefix ":" config.services.victoriametrics.listenAddress; 39 - uri = "/api/v1/write"; 40 - } 41 - { 42 - name = "http"; 43 - match = "logs.*"; 44 - port = lib.removePrefix ":" config.services.victorialogs.listenAddress; 45 - uri = "/insert/jsonline?_stream_fields=stream&_msg_field=log&_time_field=date"; 46 - format = "json_lines"; 47 - json_date_format = "iso8601"; 48 - } 49 - # write logs via syslog 50 - # { 51 - # name = "syslog"; 52 - # match = "*.log"; 53 - # port = syslogUdp; 54 - # syslog_maxsize = 4096; 55 - # syslog_severity_key = "severity"; 56 - # syslog_facility_key = "facility"; 57 - # syslog_hostname_key = "hostname"; 58 - # syslog_appname_key = "appname"; 59 - # syslog_procid_key = "procid"; 60 - # syslog_msgid_key = "msgid"; 61 - # syslog_sd_key = "sd"; 62 - # syslog_message_key = "message"; 63 - # } 64 - ]; 65 - 66 - # services.journald.upload = { 67 - # enable = true; 68 - # settings.Upload.URL = "http://localhost${config.services.victorialogs.listenAddress}/insert/journald"; 69 - # }; 70 - }
+85
hosts/wolumonde/modules/website.nix
··· 1 + { 2 + config, 3 + pkgs, 4 + inputs, 5 + ... 6 + }: 7 + let 8 + PUBLIC_BASE_URL = "https://gaze.systems"; 9 + modules = (pkgs.callPackage "${inputs.blog}/nix/modules.nix" { }).overrideAttrs (_: { 10 + outputHash = "sha256-rzfSfiK8FSNFR+1QTwM/ltLZBprG9BoQsPmOt6IdXFc="; 11 + }); 12 + pkg = pkgs.callPackage "${inputs.blog}/nix" { 13 + inherit PUBLIC_BASE_URL; 14 + gazesys-modules = modules; 15 + }; 16 + port = 3003; 17 + in 18 + { 19 + users.users.website = { 20 + isSystemUser = true; 21 + group = "website"; 22 + }; 23 + users.groups.website = { }; 24 + 25 + age.secrets.websiteConfig.file = ../../../secrets/websiteConfig.age; 26 + 27 + systemd.services.website = { 28 + description = "website"; 29 + wantedBy = [ "multi-user.target" ]; 30 + after = [ "network.target" ]; 31 + environment = { 32 + HOME = "/var/lib/website"; 33 + ORIGIN = PUBLIC_BASE_URL; 34 + PORT = toString port; 35 + WEBSITE_DATA_DIR = "/var/lib/website"; 36 + VITE_CLOUDINARY_CLOUD_NAME = "dgtwf7mar"; 37 + }; 38 + serviceConfig = { 39 + User = "website"; 40 + ExecStart = "${pkg}/bin/website"; 41 + Restart = "on-failure"; 42 + RestartSec = 5; 43 + WorkingDirectory = "/var/lib/website"; 44 + EnvironmentFile = config.age.secrets.websiteConfig.path; 45 + KillSignal = "SIGKILL"; 46 + }; 47 + }; 48 + 49 + # systemd.services.annoy-keep-alive = { 50 + # description = "keeps annoy peer connection alive"; 51 + # wantedBy = [ "multi-user.target" ]; 52 + # after = [ "network.target" ]; 53 + # serviceConfig = { 54 + # Type = "oneshot"; 55 + # ExecStart = "${pkgs.curl}/bin/curl http://100.64.0.1:3111/"; 56 + # }; 57 + # }; 58 + # systemd.timers.annoy-keep-alive.timerConfig = { 59 + # OnBootSec = "5 min"; 60 + # OnUnitActiveSec = "5 min"; 61 + # Unit = "annoy-keep-alive.service"; 62 + # }; 63 + 64 + services.nginx.virtualHosts."gaze.systems" = { 65 + locations."/".proxyPass = "http://localhost:${toString port}"; 66 + locations."/annoy/ws/" = { 67 + proxyWebsockets = true; 68 + proxyPass = "http://100.64.0.9:3111/"; 69 + extraConfig = '' 70 + rewrite ^/annoy/ws/(.*) /$1 break; 71 + ''; 72 + }; 73 + locations."/annoy/ws" = { 74 + proxyWebsockets = true; 75 + proxyPass = "http://100.64.0.9:3111/"; 76 + extraConfig = '' 77 + rewrite ^/annoy/ws(.*) /$1 break; 78 + ''; 79 + }; 80 + }; 81 + 82 + services.nginx.virtualHosts."poor.dog" = { 83 + locations."/".return = "301 https://gaze.systems$request_uri"; 84 + }; 85 + }
+12 -4
nvfetcher.toml
··· 29 29 fetch.git = "https://tangled.org/@ptr.pet/nixos-cloud-resources" 30 30 31 31 [limbusart] 32 - src.git = "https://git.gaze.systems/90008/limbusart.git" 33 - fetch.git = "https://git.gaze.systems/90008/limbusart.git" 32 + src.git = "https://github.com/90-008/limbusart.git" 33 + fetch.git = "https://github.com/90-008/limbusart.git" 34 + 35 + [clickee] 36 + src.git = "https://tangled.org/@ptr.pet/clickee" 37 + fetch.git = "https://tangled.org/@ptr.pet/clickee" 34 38 35 39 [clickee-proxy] 36 40 src.git = "https://tangled.org/@ptr.pet/clickee-proxy" ··· 48 52 src.git = "https://tangled.org/@ptr.pet/trill" 49 53 fetch.git = "https://tangled.org/@ptr.pet/trill" 50 54 55 + [dysnomia] 56 + src.git = "https://tangled.org/@ptr.pet/dysnomia" 57 + fetch.git = "https://tangled.org/@ptr.pet/dysnomia" 58 + 51 59 ## TANGLED ## 52 60 53 61 [tangled] 54 - src.git = "https://tangled.org/@tangled.org/core" 55 - fetch.git = "https://tangled.org/@tangled.org/core" 62 + src.git = "https://tangled.org/ptr.pet/core" 63 + fetch.git = "https://tangled.org/ptr.pet/core" 56 64 57 65 [tangled-sqlite-lib] 58 66 src.manual = "3450100"
+10
pkgs-set/overlays/feishin.nix
··· 1 + final: prev: let 2 + nixpkgs = final.fetchFromGitHub { 3 + owner = "nixos"; 4 + repo = "nixpkgs"; 5 + rev = "70adf772dca7804ba7b5701f5b20c01108b83401"; 6 + hash = "sha256-AJjEVxNQnmPucS/t9roICpfPsBDjuNoSeQ1YGP40/gM="; 7 + }; 8 + in { 9 + feishin = prev.callPackage "${nixpkgs}/pkgs/by-name/fe/feishin/package.nix" {}; 10 + }
+6
pkgs-set/overlays/navidrome.nix/default.nix
··· 1 + final: prev: { 2 + navidrome = prev.navidrome.overrideAttrs (old: { 3 + patches = (old.patches or []) ++ [./origin_url.patch]; 4 + doCheck = false; 5 + }); 6 + }
+85
pkgs-set/overlays/navidrome.nix/origin_url.patch
··· 1 + diff --git a/core/agents/listenbrainz/agent.go b/core/agents/listenbrainz/agent.go 2 + index 769b0f5..758eb85 100644 3 + --- a/core/agents/listenbrainz/agent.go 4 + +++ b/core/agents/listenbrainz/agent.go 5 + @@ -3,6 +3,7 @@ package listenbrainz 6 + import ( 7 + "context" 8 + "errors" 9 + + "fmt" 10 + "net/http" 11 + 12 + "github.com/navidrome/navidrome/conf" 13 + @@ -52,6 +53,10 @@ func (l *listenBrainzAgent) formatListen(track *model.MediaFile) listenInfo { 14 + artistNames := slice.Map(track.Participants[model.RoleArtist], func(p model.Participant) string { 15 + return p.Name 16 + }) 17 + + var originURL string 18 + + if v := track.Tags.Values(model.TagSource); len(v) > 0 { 19 + + originURL = v[0] 20 + + } 21 + li := listenInfo{ 22 + TrackMetadata: trackMetadata{ 23 + ArtistName: track.Artist, 24 + @@ -67,9 +72,12 @@ func (l *listenBrainzAgent) formatListen(track *model.MediaFile) listenInfo { 25 + ReleaseMBID: track.MbzAlbumID, 26 + ReleaseGroupMBID: track.MbzReleaseGroupID, 27 + DurationMs: int(track.Duration * 1000), 28 + + OriginURL: originURL, 29 + }, 30 + }, 31 + } 32 + + fmt.Printf("listen info: %+v\n", li) 33 + + fmt.Printf("track tags: %+v\n", track.Tags) 34 + return li 35 + } 36 + 37 + diff --git a/core/agents/listenbrainz/agent_test.go b/core/agents/listenbrainz/agent_test.go 38 + index e99b442..11e7b3c 100644 39 + --- a/core/agents/listenbrainz/agent_test.go 40 + +++ b/core/agents/listenbrainz/agent_test.go 41 + @@ -69,6 +69,7 @@ var _ = Describe("listenBrainzAgent", func() { 42 + "ArtistNames": ConsistOf("Artist 1", "Artist 2"), 43 + "ArtistMBIDs": ConsistOf("mbz-111", "mbz-222"), 44 + "DurationMs": Equal(142200), 45 + + "OriginURL": Ignore(), 46 + }), 47 + }), 48 + })) 49 + diff --git a/core/agents/listenbrainz/client.go b/core/agents/listenbrainz/client.go 50 + index 168aad5..807bdef 100644 51 + --- a/core/agents/listenbrainz/client.go 52 + +++ b/core/agents/listenbrainz/client.go 53 + @@ -82,6 +82,7 @@ type additionalInfo struct { 54 + ReleaseMBID string `json:"release_mbid,omitempty"` 55 + ReleaseGroupMBID string `json:"release_group_mbid,omitempty"` 56 + DurationMs int `json:"duration_ms,omitempty"` 57 + + OriginURL string `json:"origin_url,omitempty"` 58 + } 59 + 60 + func (c *client) validateToken(ctx context.Context, apiKey string) (*listenBrainzResponse, error) { 61 + diff --git a/model/tag.go b/model/tag.go 62 + index 674f688..ecd1a12 100644 63 + --- a/model/tag.go 64 + +++ b/model/tag.go 65 + @@ -194,6 +194,7 @@ const ( 66 + TagISRC TagName = "isrc" 67 + TagBPM TagName = "bpm" 68 + TagExplicitStatus TagName = "explicitstatus" 69 + + TagSource TagName = "source" 70 + 71 + // Dates and years 72 + 73 + diff --git a/resources/mappings.yaml b/resources/mappings.yaml 74 + index d1da5c6..905ad01 100644 75 + --- a/resources/mappings.yaml 76 + +++ b/resources/mappings.yaml 77 + @@ -251,6 +251,8 @@ additional: 78 + aliases: [ txxx:script, script, ----:com.apple.itunes:script, wm/script ] 79 + subtitle: 80 + aliases: [ tit3, subtitle, ----:com.apple.itunes:subtitle, wm/subtitle ] 81 + + source: 82 + + aliases: [ source, woas, audio source, txxx:source, ----:com.apple.itunes:source ] 83 + website: 84 + aliases: [ woar, website, weblink, wm/authorurl ] 85 + work:
+1
pkgs-set/pkgs/clickee.nix
··· 1 + {inputs, callPackage, ...}: callPackage inputs.clickee {}
+1
pkgs-set/pkgs/dysnomia.nix
··· 1 + {inputs, callPackage, ...}: callPackage "${inputs.dysnomia}/nix" {}
+2 -2
pkgs-set/pkgs/helium.nix
··· 5 5 }: 6 6 pkgs.appimageTools.wrapType2 rec { 7 7 pname = "helium"; 8 - version = "0.6.4.1"; 8 + version = "0.7.4.1"; 9 9 10 10 src = let 11 11 platformMap = { ··· 16 16 platform = platformMap.${pkgs.system}; 17 17 18 18 hashes = { 19 - "x86_64-linux" = "sha256-DlEFuFwx2Qjr9eb6uiSYzM/F3r2hdtkMW5drJyJt/YE="; 19 + "x86_64-linux" = "sha256-JFaGuRbjNEzFOEpntbzARxCOxA/2Fxhd31nXaVPfpFg="; 20 20 "aarch64-linux" = "sha256-B63tvOtSRlMRJozvzC7lqG2LM0ZgLIq2G/AHABl+Qqg="; 21 21 }; 22 22
+49
pkgs-set/pkgs/pds-upload.nix/default.nix
··· 1 + { lib 2 + , stdenvNoCC 3 + , makeWrapper 4 + , nushell 5 + , file 6 + , secretsFile ? null 7 + , ... 8 + }: 9 + 10 + stdenvNoCC.mkDerivation { 11 + pname = "pds-upload"; 12 + version = "0.1.0"; 13 + 14 + src = ./pds-upload.nu; 15 + 16 + nativeBuildInputs = [ makeWrapper ]; 17 + 18 + buildInputs = [ nushell ]; 19 + 20 + dontUnpack = true; 21 + dontBuild = true; 22 + 23 + installPhase = '' 24 + runHook preInstall 25 + 26 + mkdir -p $out/bin $out/libexec 27 + 28 + install -Dm755 $src $out/libexec/pds-upload.nu 29 + 30 + makeWrapper ${nushell}/bin/nu $out/bin/pds-upload \ 31 + --add-flags "$out/libexec/pds-upload.nu" \ 32 + --prefix PATH : ${lib.makeBinPath [ file ]} \ 33 + --run ${lib.escapeShellArg '' 34 + # Optional: Set secrets file from argument override 35 + ${lib.optionalString (secretsFile != null) '' 36 + export ATPROTO_SECRETS_FILE="${secretsFile}" 37 + ''} 38 + 39 + # Load secrets if the file exists (to populate ATPROTO_DID/PASSWORD) 40 + if [ -n "$ATPROTO_SECRETS_FILE" ] && [ -f "$ATPROTO_SECRETS_FILE" ]; then 41 + set -a 42 + source "$ATPROTO_SECRETS_FILE" 43 + set +a 44 + fi 45 + ''} 46 + 47 + runHook postInstall 48 + ''; 49 + }
+96
pkgs-set/pkgs/pds-upload.nix/pds-upload.nu
··· 1 + #!/usr/bin/env nu 2 + 3 + # A script to upload a blob and create a record in the AT Protocol (Bluesky). 4 + # Usage: nu pds-upload.nu <path-to-image> 5 + 6 + def main [ 7 + file_path: path # The path to the file you want to upload 8 + ] { 9 + # --- 1. Setup & Configuration --- 10 + let identifier = ($env.ATPROTO_DID? | default "") 11 + let password = ($env.ATPROTO_PASSWORD? | default "") 12 + 13 + # Default to the main network if not specified in env 14 + let pds_host = ($env.ATPROTO_PDS_URL? | default "https://bsky.social") 15 + 16 + # Validation 17 + if ($identifier | is-empty) or ($password | is-empty) { 18 + error make { 19 + msg: "Missing Credentials", 20 + label: { 21 + text: "Please set ATPROTO_DID and ATPROTO_PASSWORD environment variables.", 22 + span: (metadata $identifier).span 23 + } 24 + } 25 + } 26 + 27 + if not ($file_path | path exists) { 28 + error make { msg: $"File not found: ($file_path)" } 29 + } 30 + 31 + # Detect mime-type 32 + let mime_type = (try { 33 + ^file --mime-type -b $file_path | str trim 34 + } catch { 35 + "application/octet-stream" 36 + }) 37 + 38 + # --- 2. Create Session (Authentication) --- 39 + let session_res = (http post 40 + --content-type "application/json" 41 + $"($pds_host)/xrpc/com.atproto.server.createSession" 42 + { identifier: $identifier, password: $password } 43 + ) 44 + 45 + let access_token = $session_res.accessJwt 46 + let repo_did = $session_res.did 47 + 48 + # --- 3. Upload Blob --- 49 + let file_data = (open $file_path) 50 + 51 + let blob_res = (http post 52 + --content-type $mime_type 53 + --headers { Authorization: $"Bearer ($access_token)" } 54 + $"($pds_host)/xrpc/com.atproto.repo.uploadBlob" 55 + $file_data 56 + ) 57 + 58 + let blob_ref = $blob_res.blob 59 + 60 + # --- 4. Create Record --- 61 + let file_name = ($file_path | path basename) 62 + let now = (date now | format date "%Y-%m-%dT%H:%M:%SZ") 63 + 64 + let record_payload = { 65 + repo: $repo_did 66 + collection: "systems.gaze.file" 67 + record: { 68 + "$type": "systems.gaze.file" 69 + createdAt: $now 70 + file: $blob_ref 71 + filename: $file_name 72 + } 73 + } 74 + 75 + let record_res = (http post 76 + --content-type "application/json" 77 + --headers { Authorization: $"Bearer ($access_token)" } 78 + $"($pds_host)/xrpc/com.atproto.repo.createRecord" 79 + $record_payload 80 + ) 81 + 82 + # --- 5. Construct Return Value --- 83 + # We construct the public URL for the blob 84 + # The '$link' key requires special handling to extract 85 + let cid = ($blob_ref.ref | get '$link') 86 + let blob_url = $"($pds_host)/xrpc/com.atproto.sync.getBlob?did=($repo_did)&cid=($cid)" 87 + 88 + # Return a structured record with both the URI and the direct URL 89 + let result = { 90 + uri: $record_res.uri 91 + cid: $record_res.cid 92 + blob_url: $blob_url 93 + } | to json 94 + 95 + return $result 96 + }
+17
secrets/atfileCfg.age
··· 1 + age-encryption.org/v1 2 + -> ssh-rsa Abmvag 3 + cslEDLMgbmTeCxKXG4isYQdts8ET2tb4NSRgoHpk9g3jB3bEOlYdY7LZtZ8YLxJ0 4 + 78YD6v81ssVQzCOoD0MQKveEkDIAie9JlYYDQS0pv/ACP+E1fqbIRo5pE7t9s26x 5 + rBMZntIDx1vzGRM/+87Wz2NOPpNseP7P2CEIltMn3S5xbsl4N9WVx1mnH4NfsPCu 6 + VRh3APe/Ee/Ph0/wBK2wQWRG97dd+p1bY7nzkRYE26DpODez1f9kTlTppIyivJDc 7 + dIPMkykJOos/dwu6nR1XKS6l8f7Y+pQcYF24cqMe3PDQbhb19qwcpMiy0I11R2ik 8 + /yb8pRziazd01gJsSKUWz/WVhKx7A4dj9TQloWO1FXoIB/mPaxZBghQfP55oV6b9 9 + MGIxRcn/fekbCYNSxVo9WFyBsfg4vNzUcBlUInANrxU2mUS5YFpY7jf2iHGeGfRU 10 + ZQsgB/ftScvtoSdKJ3dW4fW/2MZ2qyzjcrvFvikL50fucXhhOGa4ToDy2e04TLpm 11 + fXlKHBgS+xYIgnjw/6P54SwMbgC1fGUq7mC7TVKZiA/AyDyZMxQvNIfx6MKlffDM 12 + ItU2mHjV2i23g3Nk9V6EmSxy/RCivVNZMWktLJrR+XYKGjhqjqObF83kE9vlzl1g 13 + 6hU80Ys0H8q0iCBnceLL1UlODByXczzRhiqrFetkmlc 14 + --- goQ5BSnSK0NTZ13BPhqmduMllp9tF8n4mNHEVvm1dA8 15 + ��?eO��X �=/@��c�fg�7  �ciG��ד`�,q(HT�rPs'Z��l����L�w@2"�?[�:��9��B�] �{+�����8%���%�w_vR���9�N 16 + Q�G�0 �Z�l�C��u 17 + �y���>J
+21
secrets/bunnyApiKey.age
··· 1 + age-encryption.org/v1 2 + -> ssh-rsa Abmvag 3 + XNh6H/W0srZXbGmkLGQ/YpXfamisyK/duLeSftkcrXU67b5s8x40HUv1NaKr/QQt 4 + 7ZBvKfm+8YsKcmmXaIINOHl6/LQ6GTpWprN91VDxTGOGzpO/GmD8MOUk8zfJYh+D 5 + 3soDoZuuk1gr8Q7+f8AIrfT+x3QwHA2h3hCm3un3MqhmAicTTip2C3NFQhlsEwHi 6 + DhgOJ1Wy9/lSXwIzhg62s8KDOQ4cBETA8PRvspWh8GsV1oLU/brk2itwUaj0P8xA 7 + uQrQzo71rbUttXeGnW4yBZjzzGMJe5iHY3H4aQxjklC1yGpInDf3HGaO6X/yaZBx 8 + vRx2YxwCH4AdhgVpllbZo2++uGX8mye6fu5Lap04+dXU+ubglEvDQ1uRDrbXML9/ 9 + PpRszgmu5z7k9u+qWI/aBywUChvVSy4TDWKcj2JAqvCuU7QYiEi6SKhIiDLNd/BQ 10 + 7aa/GHSUpUu6TnpRwuBF4l2g5+jO27hsNWb3nAm/SV5YHEVCn+Tr5PiRPxBK8Fa0 11 + ngJjBK5r4ra+uGulwGn1uoM0jYVCl6EtjtKgLeP5cvbdLylKWRXRYxyL7XTxqmHb 12 + oLJsVvxuF1pFiaUkAmMBctaYdMw9EVwV8vTp4/eebVe6pU0Lmxv5B0u5nDiWar5o 13 + RQzfwfGhtOaE0PUQNqVz7VfdoIzCcUjqnJMwInh+XwU 14 + -> ssh-ed25519 y5W/qA rZ2rTM2n2bPULAefeeUvEFwskCNIEh5KdkC7uEnBcXM 15 + P75OaqdeAt3BVa/xprDvJ/bLoGLkU6qdteVvwD9fO8M 16 + -> ssh-ed25519 LaQclg Bnt8Z3Cve0gG6ItbJq+1+fUT/ykFsngstap8ymEr1m4 17 + filHMr3njOkRpbu4UwutvqxVLf8joTBvqs3JT1gu7kk 18 + --- pkIfClG050A3Kp8c+HUQJDwlxM1BbFaCRx8Vp0++xbI 19 + 4�dc���/\�ڦ �@:e��:e�o;� 20 + �E�d\W�#m 21 + ��WA��#�uaJ��T�<���X�R���X�X"9 ���)�'U:7��+�,�hNϏ�Ul\� FSP8c
secrets/clickeeProxyConfig.age

This is a binary file and will not be displayed.

+22
secrets/cloudflareDnsEdit.age
··· 1 + age-encryption.org/v1 2 + -> ssh-rsa Abmvag 3 + RLzSHns6rm+PKThSJC768KmC2a9odftJWSSWqNR36LA5wb1wU5YpP/EHt6P50AY/ 4 + JsFPydPP+XTso4rSclWuW1gjEEzfQdwBJy0c9QNo6WRwtLsR2jLC/VBULqTPsHUH 5 + bSR138+wtdICBLRMY71VvEcdrtONMm8dqc/STV5e270yDU+HtCW2Vwxu837CpUzQ 6 + 6xHV1NDURR5NugjQspW3mVBrFSx7OpE2iGrSYsCzXNpFK9JsC40yG/YZzqf2ktM4 7 + BlWTNGRd2M/QOXwCOOdsgQHfN4DtHBR/nrC+sdauJahKxSR0RVB2jQgrH2LsmnB9 8 + Xh8ttoYKwkVHQmOEUbtCnqKpzf7qGqyRX2+smkGaB2RzSxhNmUEmdV0dAEMXtGZd 9 + aBFMw233WioqNygHxfgYkUtA2jFjBEVeAp74iKH7fB1/8fKa+SSeLEcv/IuIAOSp 10 + WjqI7El5U882SviAyMuQ6hzWBLejCNBueZTgJVR0Iyk0fTjeLNM4rhqTQswyDjBh 11 + 7jnjAgVMaqZTRHrQFkBimkjX3QXutvRcjyutY3niUNRCZacvJ8bVIuIhNbqFOLJR 12 + Io/bRwys/qR1a44GFMxbQG6Hm0NRIIK791cxxilZpnNiJHs02TLTXzuIq0bfTssz 13 + 3FjUZa6Oaerum2I/BidWJuYm4Cm6tJuftYn7XS1q+4I 14 + -> ssh-ed25519 y5W/qA /qpByEN29ydHS/WgwLlOQjby7fYCI7hDOUSMJ+s0ZHA 15 + Je4qhR22hERajFv/7EbQodKo4ldYqsrUgFdtt1KbXUA 16 + -> ssh-ed25519 KjIL7g v+JVYql3+Tm/eam/1Vl/VSN97rq/8idFMcea1u7JEgE 17 + bqgK9JhL1CF9O/35WzOj3J2fHSUQcMesbamMatJRBbk 18 + -> ssh-ed25519 LaQclg u0qjpT1TcL0sAapagUr6opDbr3FRFsTtnK9wEoIJvxM 19 + Uof2ZOkgEtdY301j0Ql6i9+WjQusspUvn1kMGgaSfp0 20 + --- 8kcgq1sQjU2uSmskmkb3SUmsXubI1HtWBhs2RuuVJcE 21 + �5��;�h9���#`c֎� 22 + ����9�k�4�S 鯘��L:�/����׀P}a��oՇ:$��.����
secrets/develMobiTailscaleAuthKey.age

This is a binary file and will not be displayed.

secrets/headscaleOidcSecret.age

This is a binary file and will not be displayed.

secrets/nixGithubAccessToken.age

This is a binary file and will not be displayed.

+19 -17
secrets/pdsConfig.age
··· 1 1 age-encryption.org/v1 2 2 -> ssh-rsa Abmvag 3 - Ti+WByG/+vCEtMtvVSUYqnjhLnL6gmVHj+8+ARD12zrfV+l0LZxW7TFGqWvtQ+9N 4 - 0aCa5AGao4ngjom0JHhFm+DzklR13V6FyB1zAQugBuPDlJFPPZmRH9jTMpbiRWK0 5 - +uAFreWIkRtsYrOYaFOWIVOUxAl7immdbx7y55Q6u55y936t8aRRP+r8LCIsd+5E 6 - dlWmxTRyYBXG4MNkCfyDeuvCnFxGFlmPXVqJeXyHBL+/Gw4nLzMvRM0PQqlkOLeS 7 - DfJUpeWT0fptykuf7nmYr0sYembv4pks9E4lLNJ51PcdR2NqC4Aaq6s9+dM+b9Yg 8 - p8Zg7HvCWxlSeNuf/gnu5jisj93ImrwJJSpkSv+AqThGkVtRpN6gzErSXPOQe9tn 9 - RuESiumGO+Thh8+1F9iMitCm9pvVDkBrVDPmTBZS5xT8v67VcIcCmkmfh1Svq/di 10 - dWhMereLu9oXd9Nudtg3uvlzWp68kCAQFjOVyhi6Li15FuPw+vvkc72c2OPv9AeZ 11 - vNmIuaCHLa5VIPqOPJEaLGMuHSd80TFCAhYq4laca9gg6cgufyGlFCR4SVXA9qy8 12 - Gi8SI+wdBbi5+RKveju2/58Wbas6oIqmP6IOgTibwYl3uQ8EE4YhG1QocChN553X 13 - 0pjhtSBTyXgVuy3bqz5eA4QAkCcDocwT/4R4eaNGLW0 14 - -> ssh-ed25519 KjIL7g QPvc+LbTi8URL1atJNHHalHRyVGlz7pmrbOeMtjP6gM 15 - lH3IhynTXpQ3Z4hFGn4bJZ/vEWte7qZqeAhixghjoe8 16 - --- rIrWSZf0Q7b4fWtd9+gXxJpD9AoC0xWE7iWkUGCekDc 17 - ��)����ϲX� 0)��J�!���x�'E���vp�O�N~�23x��"��(Q�0�f_]7��ב��V�e���]+_/;:ؿ�g<.rJ��>W�R�K"�L#��/��+�Ƴ3M*Õ��:�Q'L��-}�#�Y�p������I 18 - ��Dm���{��ܫ�L��s��b�;� 19 - c*�ݷ�u�m�����+^d�ؓ�0k2yty��>����������F�L&����qk����Ⱦ��c �Y'{�,�G�V��tS�I���7�W�� ��Qp���a�f{f�2O`x�=��y��7�ߓ�}��{=﷋�Í�O����P0�=f�P�B\p���l�.��F�����bm|Oл;-��ǾS�����Ғ�_Ԥ 3 + SbNEqnr2eT0YR293LnQtJInXLmx7g+iCJwnZ4GmmEM2euePiEY69s8lRQUb7MQU8 4 + xghOLEo/gr74/wtrOUf+4Ge3OM8KiAZt3QLuREJYz1xI6+gnMaievWbinAA+Ly0L 5 + KdmFyshVGl+xKA0QPpc6fTO4XnAEH0g5Rg5upZoAfRARmOYeIQvXaWW2ehjI1Izw 6 + RINcoszonp5egzZ9QJ6huruT2actz2XIAsZX/0NYQdjC6xmChxfTOxuXQskbzzyK 7 + 42eholIkf/5fYre4HmB7ePKuZeUeVRhK0RYemBq/ZNNUCf1ExjE/wDKTWpuPOafV 8 + J2/7kP7OkwIEeEYXvLPvYM2HRasIbDUBmLOlj7L4E8BgMzKV7FmCr2n27m7iCjhz 9 + y0sTpEk1y2N/rDvc/GCuZNtGNZIrbfzGaz5fhgegvO0Jogc2km4LVaEOQlA+AI5w 10 + fxew6hCZkISaw+CjNaBOk45XXhMsONfW63uba6kgzj3h2+9jG1UmEPJAuNdgkjze 11 + 32lBZ58np+cA+aENt4sZu5nKk90Rsq54aNntfaHuFMFIfvK4RZj3HwHCAND+9XJ1 12 + SNkNetcehX9jzZYm5Npnlhleft92TACYbtIIoi/zqgYMLDaHeAW6ZDAnW9sgO7mo 13 + uSVwa8Gf5SwUY6v8IgVDwQVHiq8WTtRgRJmImP/mvS4 14 + -> ssh-ed25519 KjIL7g tRXe9XXGtJyjCQuHU4oD7L5veJ8BKCFHUdXuSAa6/D4 15 + vjVwtS7dKxTkjGHeLzV0G2uzIyEYaaSLplxOvfApIa0 16 + -> ssh-ed25519 LaQclg 81iLpPZTOiW2ZNnfy8lErpeHiQoTtIpariQ5153Nwl4 17 + 5wqZUoo5CxEPHwVy9SSspvECTWAQ8qgjbj44WCx/kdw 18 + --- z1wPplzF3WsIHxojXxcZnq91akMO+Hj1WFth2ujJAvY 19 + �X RM�V˛a^�Z2A욓ר)h���h�� hV�Z��e&�.��l��ɉ/n�aIد-��q��(�id� DT 20 + �d�e��T�cHiɂ*^�4��+�?� �����y��-nD=��]��(������ѝG�Z���ɲ���P�w9�g��j>��d��Ϥ�������F�t�~��P�QS� ,z�%Ad�E�t=�R�B�ُܱ~����7��ެ{1=�� ����kOV=W3���e��CN��q�Ϥ���.\���n�wW����c�R;G 21 + �6�f"�W����7f_�MZ;���.Х�Ѓ�@���3���Ǫ&,��1�ܕ�����]l�J�L!a֟� �r��}9 ��o@�.]��ƈ�fS����=�@��
+17 -16
secrets/persesSecret.age
··· 1 1 age-encryption.org/v1 2 2 -> ssh-rsa Abmvag 3 - gnRXwWRObKH5JCBDDPVRDHsgSj4m3zwOHAFLDAXTmWjs0mVNKSu5AFtKkoJuUuzs 4 - RQFGn3b4pv6duPjpEW4t0DBkAOCwgqTqvF3oSKNBSDuhNU4+XzCJgBZDesO3VZ/S 5 - zZxM8kq14sM484pZSRI0A86VNSlR7q8lyF1kth+bn5dum7Ihq87Re6jW+OyFwL7L 6 - tkTON5L4aMqjI4fMQl/PcRU+04sYkKug6JQO/DDyFXvjvROuO43ZChjqGGj4ol9b 7 - mXPOJuabzUtWGoTwg7+IHhbyUbanoO+2gCMejRGbZbBTh+bOftNx0bvNj8lrxgit 8 - oE5sXhqPeI9BhOGWiJvR+32YdHl2WRYQ/7nNdWsnA0UuiPRHPu827g91NrVgjxBk 9 - SpgoabwZpCUl8GlfihtTvw3NbV6WnIUv0ew9bwlyf129uvH7Rn61o0JMnq5m37Zt 10 - rJjLJ262zIdb4eS1QgycI+ugeb290Vh22niTLLKoJxAFdLyzSr84XsfUVyrjhJfz 11 - Ll+12c7ApTcgwhuhOkFLmU8SUNwxhH523fV8zcQ/1E9yjpa26qQcTF+ujRV8FIwb 12 - kVGLDHUXehU5gm/nsuQVaULYHRC50pvu7wKKZsj0UqdQeKCx1CwBOdFk6Qctxl9N 13 - VvAenIra/FVImcrimQ/sNCeg8UasT+gvbY5KjhwPzkY 14 - -> ssh-ed25519 KjIL7g +FQdRCFxlkayD4Hq9xb4WCE139upxkpSrvh7412gqlo 15 - jxDJlUgJZfftyeyhikKi4zLhtM6fVXxAGMmD7gcQZgM 16 - --- OXRvMmNqRzo4NGF4ihpPSHu77W8dH45HwJJIDI3hUCY 17 - &}͘8��;YX5 18 - �$m3�1r['�%<7�����W�D��h�0�%��C$�Il1;ɛl�1�i�A��E�z��,n݆�|b�?2N�}�m/Ӈ� 3 + IC9ZInud32ueWR3owngph/eKReklaRfgY6bDKDmA0OT5IEvisOYK8lhGwAzOZdIq 4 + i+K5p7C30qe1+1fmZ3ZNcQMKeIq79LdpiR7Xb6DT+BAT5g++wsXqqsvxZYyR4Ux7 5 + dPxr05VJXE6HkoUQ2gcG/rlED1M7EoRq1TBm1UV4wIDiWy/ZdZZRvM8C++CD2h4V 6 + d4cLoDzVZxYdi3s+NRXpbg62fIO//suAYvlMjbKQasEBWv88R8rwj5br+o/AbCR8 7 + hkjctI+EuMHzq7hwlZ211hb/HDLnFckWmIao9Hvw6PpyFMIUmuQWsgn6yHQ6zJQx 8 + zIXNgAYpX5bR8i0VXvwNwlfWOOqNcOU4QD7ZO4qFs+ZYTlHvo1m1RNhDIBbhC9UM 9 + v3C8fU0RTaWhUkcacXn3VXBiJIHXzFLiAfxQ1ft5HPOjsOOhHwphMFwblCukTJ45 10 + SNVErkK32YeW6J0nyQGHRNHNSgbZC274caZ8R3nlTynkYRoF6/dy7Q1OLNILF4Vd 11 + qW54oLZs9A6ralFkDfObl4rxOcz4HPdwH9p/kWzW1C1IrfZk0m5eOppFzZ2fUHra 12 + FED8mJ0vH5E0oCL7JBDVx3A+Ss5vj7zpJePL10UQvfWI8qUIXHZT6wbIt/XfRvtq 13 + rbr0g9tQtnnpOMJwgu1GzL1xQWGelAS8pvV8GPb5Vvg 14 + -> ssh-ed25519 KjIL7g 0DtiBKi0aL82kjE3AgAbwkCw+fuIWXMvzi52eem0JgM 15 + ujkcowuy/vokA+jqV7d5RcZGeg2yhzh8IdQQHJ/wZns 16 + -> ssh-ed25519 LaQclg m/1lrK8ks3LlAQYG0/85pZiyQvhh16/Y5bX+k9HPpgU 17 + zJD9xgF9GuHGHYSkczPGllccYqW7y/+UZrlCveFJIt4 18 + --- ZM1sl++OddBxYlx8/57o/BWcSsU3rHQ41q7cJCoZiPs 19 + �C{���9�C�yC��'�]����P�X��n��ZD��}�q2�[�@�R8�h���'����a�:�B2X��}<5��D�����6�������p���*��
+14 -9
secrets/secrets.nix
··· 1 1 let 2 2 yusdacra = builtins.readFile ./yusdacra.key.pub; 3 - wolumonde = builtins.readFile ./wolumonde.key.pub; 4 3 dzwonek = builtins.readFile ./dzwonek.key.pub; 5 - develMobi = builtins.readFile ./develMobi.key.pub; 4 + trimounts = builtins.readFile ./trimounts.key.pub; 6 5 in 7 6 { 8 7 "nixGithubAccessToken.age".publicKeys = [ yusdacra ]; 9 8 "websiteConfig.age".publicKeys = [ 10 9 yusdacra 11 - wolumonde 10 + trimounts 12 11 ]; 13 12 "pdsConfig.age".publicKeys = [ 14 13 yusdacra 15 - wolumonde 14 + trimounts 16 15 ]; 17 16 "clickeeProxyConfig.age".publicKeys = [ 18 17 yusdacra 19 - wolumonde 18 + trimounts 20 19 ]; 21 - "deployWebhook.age".publicKeys = [ yusdacra ]; 22 20 "persesSecret.age".publicKeys = [ 23 21 yusdacra 24 - wolumonde 22 + trimounts 25 23 ]; 26 24 "headscaleOidcSecret.age".publicKeys = [ 27 25 yusdacra 28 26 dzwonek 29 27 ]; 30 - "develMobiTailscaleAuthKey.age".publicKeys = [ 28 + "cloudflareDnsEdit.age".publicKeys = [ 29 + yusdacra 30 + dzwonek 31 + trimounts 32 + ]; 33 + "bunnyApiKey.age".publicKeys = [ 31 34 yusdacra 32 - develMobi 35 + dzwonek 36 + trimounts 33 37 ]; 38 + "atfileCfg.age".publicKeys = [yusdacra]; 34 39 }
+1
secrets/trimounts.key.pub
··· 1 + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDLuA1/cZ/xTN4dv5U0fvD9Glo6HlF5YA4U1pvFjxx6V
secrets/websiteConfig.age

This is a binary file and will not be displayed.

+46 -5
users/mayer/default.nix
··· 2 2 pkgs, 3 3 lib, 4 4 tlib, 5 - config, 6 5 terra, 7 6 ... 8 7 }@globalAttrs: ··· 34 33 nushell 35 34 ]; 36 35 programs = { 37 - steam.enable = true; 38 - gamescope.enable = true; 36 + steam = { 37 + enable = true; 38 + package = pkgs.steam.override { 39 + extraPkgs = pkgs': with pkgs'; [ 40 + vulkan-loader 41 + wayland 42 + wayland-protocols 43 + xorg.libXcursor 44 + xorg.libXi 45 + xorg.libXinerama 46 + xorg.libXScrnSaver 47 + libpng 48 + libpulseaudio 49 + libvorbis 50 + stdenv.cc.cc.lib # Provides libstdc++.so.6 51 + libkrb5 52 + keyutils 53 + ]; 54 + }; 55 + extraCompatPackages = with pkgs; [ 56 + proton-ge-bin 57 + ]; 58 + }; 59 + gamescope = { 60 + enable = true; 61 + capSysNice = true; 62 + }; 39 63 gamemode.enable = true; 40 64 appimage = { 41 65 enable = true; ··· 73 97 74 98 home-manager.users.mayer = 75 99 { 100 + config, 76 101 pkgs, 77 102 inputs, 78 103 ... ··· 101 126 ] 102 127 [ 103 128 "zen" 104 - "discord" 129 + # "discord" 130 + "clickee" 131 + "arrpc" 105 132 ] 106 133 ]; 107 134 in 108 135 l.flatten [ 109 136 (tlib.prefixStrings "${inputs.self}/users/modules/" modulesToEnable) 137 + ../modules/discord/service.nix 138 + "${inputs.agenix}/modules/age-home.nix" 110 139 ]; 111 140 112 141 home = { ··· 130 159 bs-manager 131 160 cemu 132 161 tor-browser 133 - ]) ++ [terra.helium]; 162 + # supersonic-wayland 163 + feishin 164 + ]) ++ [ 165 + terra.helium 166 + (terra.pds-upload.override { 167 + secretsFile = config.age.secrets.atfileCfg.path; 168 + }) 169 + ]; 170 + }; 171 + 172 + age.secrets.atfileCfg = { 173 + file = ../../secrets/atfileCfg.age; 174 + mode = "600"; 134 175 }; 135 176 136 177 fonts.fontconfig.enable = l.mkForce true;
+14
users/modules/clickee/default.nix
··· 1 + { terra, ... }: 2 + { 3 + systemd.user.services.clickee = { 4 + Install = { 5 + WantedBy = [ "default.target" ]; 6 + }; 7 + Service = { 8 + ExecStart = "${terra.clickee}/bin/clickee"; 9 + Restart = "on-failure"; 10 + RestartSec = 5; 11 + WorkingDirectory = "%h/.config/clickee"; 12 + }; 13 + }; 14 + }
+6
users/modules/clipman/default.nix
··· 1 + { 2 + services.clipman = { 3 + enable = true; 4 + systemdTarget = "graphical-session.target"; 5 + }; 6 + }
+1 -22
users/modules/discord/default.nix
··· 1 1 { 2 2 pkgs, 3 3 terra, 4 - inputs, 5 - lib, 6 4 ... 7 5 }: 8 6 let ··· 14 12 }; 15 13 in 16 14 { 17 - # imports = ["${inputs.moonlight}/nix/home-manager.nix"]; 15 + imports = [./service.nix]; 18 16 19 17 home.packages = [ 20 18 (pkgs.symlinkJoin { ··· 29 27 ''; 30 28 }) 31 29 ]; 32 - 33 - systemd.user.services.discord-socks-proxy = { 34 - Unit = { 35 - Description = "SSH SOCKS5 proxy for Discord"; 36 - After = [ "network-online.target" ]; 37 - Wants = [ "network-online.target" ]; 38 - }; 39 - 40 - Service = { 41 - Type = "simple"; 42 - ExecStart = "${pkgs.openssh}/bin/ssh -N -D 127.0.0.1:1337 root@wolumonde"; 43 - Restart = "on-failure"; 44 - RestartSec = "3s"; 45 - }; 46 - 47 - Install = { 48 - WantedBy = [ "default.target" ]; 49 - }; 50 - }; 51 30 }
+20
users/modules/discord/service.nix
··· 1 + {pkgs, ...}: { 2 + systemd.user.services.discord-socks-proxy = { 3 + Unit = { 4 + Description = "SSH SOCKS5 proxy for Discord"; 5 + After = [ "network-online.target" ]; 6 + Wants = [ "network-online.target" ]; 7 + }; 8 + 9 + Service = { 10 + Type = "simple"; 11 + ExecStart = "${pkgs.openssh}/bin/ssh -N -D 127.0.0.1:1338 root@trimounts"; 12 + Restart = "on-failure"; 13 + RestartSec = "3s"; 14 + }; 15 + 16 + Install = { 17 + WantedBy = [ "default.target" ]; 18 + }; 19 + }; 20 + }
+2 -3
users/modules/git/default.nix
··· 1 1 { pkgs, ... }: 2 2 let 3 - personal = import ../../../personal.nix; 4 - name = personal.name; 5 - email = personal.emails.primary; 3 + name = "dawn"; 4 + email = "90008@gaze.systems"; 6 5 in 7 6 { 8 7 programs.git = {
+21
users/modules/niri/clipboard.nu
··· 1 + #!/usr/bin/env nu 2 + 3 + def main [] { 4 + # Get clipboard history from clipman 5 + let history = clipman show-history 6 + 7 + if ($history | is-empty) { 8 + notify-send "Clipman" "No clipboard history" 9 + exit 1 10 + } 11 + 12 + # Show in tofi and get selection 13 + let selection = ($history | lines | tofi --prompt-text "select clipboard item: " | str trim) 14 + 15 + if ($selection | is-empty) { 16 + exit 0 17 + } 18 + 19 + # Copy selection to clipboard 20 + $selection | wl-copy 21 + }
+3
users/modules/niri/config.kdl
··· 179 179 XF86MonBrightnessUp allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "+10%"; } 180 180 XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "10%-"; } 181 181 182 + Ctrl+Shift+U { spawn-sh "nu %%clipboard-upload%%"; } 183 + Ctrl+Shift+S { spawn-sh "nu %%clipboard-select%%"; } 184 + 182 185 Mod+O repeat=false { toggle-overview; } 183 186 Mod+Q cooldown-ms=50 { close-window; } 184 187
+4 -4
users/modules/niri/default.nix
··· 1 1 { 2 - config, 3 - nixosConfig, 4 2 pkgs, 5 3 lib, 6 - tlib, 7 4 ... 8 5 }: 9 6 let ··· 15 12 ../wlsunset 16 13 ../mako 17 14 ../tofi 15 + ../clipman 18 16 ]; 19 17 20 - home.packages = with pkgs; [niri xwayland-satellite brightnessctl swaybg]; 18 + home.packages = with pkgs; [file libnotify clipman niri xwayland-satellite brightnessctl swaybg]; 21 19 xdg.configFile."niri/config.kdl".text = 22 20 let 23 21 replace = { 24 22 wallpaper = toString ../../mayer/wallpaper.png; 23 + clipboard-upload = toString ./uploader.nu; 24 + clipboard-select = toString ./clipboard.nu; 25 25 }; 26 26 in 27 27 l.replaceStrings
+70
users/modules/niri/uploader.nu
··· 1 + #!/usr/bin/env nu 2 + 3 + def main [] { 4 + # --- 1. Get Clipboard Content --- 5 + let timestamp = (date now | format date '%Y%m%d_%H%M%S') 6 + let temp_file = $"/tmp/clip_($timestamp)" 7 + 8 + # Save clipboard to temp file 9 + # We remove --no-newline to safely handle binary data if necessary, 10 + # though wl-paste usually handles it. 11 + try { 12 + wl-paste | save -f $temp_file 13 + } catch { 14 + notify-send "Upload Failed" "Could not get content from clipboard" 15 + exit 1 16 + } 17 + 18 + # Detect MIME type just for logging/notification 19 + let mime_type = (try { 20 + ^file --mime-type -b $temp_file | str trim 21 + } catch { 22 + "application/octet-stream" 23 + }) 24 + 25 + print $"📤 Uploading ($mime_type)..." 26 + notify-send "ATProto Upload" $"Uploading ($mime_type)..." -t 2000 27 + 28 + try { 29 + # --- 2. Call pds-upload --- 30 + # pds-upload now returns: { uri, cid, blob_url } 31 + let res = pds-upload $temp_file | from json 32 + 33 + let record_uri = $res.uri 34 + let blob_url = $res.blob_url 35 + 36 + print $"🔗 Blob URL: ($blob_url)" 37 + print "✂️ Shortening with is.gd..." 38 + 39 + # --- 3. Shorten URL --- 40 + # is.gd expects the URL to be passed as a query parameter 'url' 41 + # We must URL-encode the blob_url 42 + let encoded_target = ($blob_url | url encode) 43 + let shorten_api = $"https://is.gd/create.php?format=simple&url=($encoded_target)" 44 + 45 + # is.gd returns the short URL as the body text 46 + let short_url = (http get $shorten_api) 47 + 48 + # --- 4. Success & Clipboard --- 49 + # Check if is.gd returned a URL (starts with http) or an error 50 + if ($short_url | str starts-with "http") { 51 + $short_url | wl-copy 52 + notify-send "ATProto Upload" $"Shortened: ($short_url)" 53 + print $"✅ Shortened: ($short_url)" 54 + } else { 55 + # Fallback to the long blob URL if shortening failed 56 + $blob_url | wl-copy 57 + notify-send "ATProto Upload" $"Uploaded (Shorten failed)" 58 + print $"⚠️ Shorten failed: ($short_url)" 59 + } 60 + 61 + } catch {|e| 62 + # Parse error for notification 63 + let err_msg = ($e | to text) 64 + notify-send "ATProto Upload" $"Upload failed: ($err_msg)" -u critical 65 + print $"❌ Upload failed: ($err_msg)" 66 + } 67 + 68 + # Cleanup 69 + rm -f $temp_file 70 + }