yep, more dotfiles
1{ self 2, config 3, pkgs 4, ... 5}: 6 7let 8 inherit (self.inputs) srvos hypixel-bank-tracker tangled; 9 10 json-format = pkgs.formats.json { }; 11 12 ext-if = "eth0"; 13 external-ip = "91.99.55.74"; 14 external-netmask = 27; 15 external-gw = "144.x.x.255"; 16 external-ip6 = "2a01:4f8:c2c:76d2::1"; 17 external-netmask6 = 64; 18 external-gw6 = "fe80::1"; 19 20 well-known-discord-dir = pkgs.writeTextDir ".well-known/discord" '' 21 dh=919234284ceb2aba439d15b9136073eb2308989b 22 ''; 23 webfinger-dir = pkgs.writeTextDir ".well-known/webfinger" '' 24 { 25 "subject": "acct:milo@wiro.world", 26 "aliases": [ 27 "mailto:milo@wiro.world", 28 "https://wiro.world/" 29 ], 30 "links": [ 31 { 32 "rel": "http://wiro.world/rel/avatar", 33 "href": "https://wiro.world/logo.jpg", 34 "type": "image/jpeg" 35 }, 36 { 37 "rel": "http://webfinger.net/rel/profile-page", 38 "href": "https://wiro.world/", 39 "type": "text/html" 40 }, 41 { 42 "rel": "http://openid.net/specs/connect/1.0/issuer", 43 "href": "https://auth.wiro.world" 44 } 45 ] 46 } 47 ''; 48 49 website-hostname = "wiro.world"; 50 51 pds-port = 3001; 52 pds-hostname = "pds.wiro.world"; 53 54 grafana-port = 3002; 55 grafana-hostname = "console.wiro.world"; 56 57 tangled-owner = "did:plc:xhgrjm4mcx3p5h3y6eino6ti"; 58 tangled-knot-port = 3003; 59 tangled-knot-hostname = "knot.wiro.world"; 60 tangled-spindle-port = 3004; 61 tangled-spindle-hostname = "spindle.wiro.world"; 62 63 thelounge-port = 3005; 64 thelounge-hostname = "lounge.wiro.world"; 65 66 headscale-port = 3006; 67 headscale-derp-port = 3478; 68 headscale-hostname = "headscale.wiro.world"; 69 70 lldap-port = 3007; 71 lldap-hostname = "ldap.wiro.world"; 72 73 authelia-port = 3008; 74 authelia-hostname = "auth.wiro.world"; 75 76 matrix-port = 3009; 77 matrix-hostname = "matrix.wiro.world"; 78 79 goatcounter-port = 3010; 80 goatcounter-hostname = "stats.wiro.world"; 81 82 vaultwarden-port = 3011; 83 vaultwarden-hostname = "vault.wiro.world"; 84 85 miniflux-port = 3012; 86 miniflux-hostname = "news.wiro.world"; 87 88 static-hostname = "static.wiro.world"; 89 90 hbt-main-port = 3013; 91 hbt-banana-port = 3014; 92 93 warrior-port = 3015; 94 warrior-hostname = "warrior.wiro.world"; 95 96 prometheus-port = 9001; 97 prometheus-node-exporter-port = 9002; 98 headscale-metrics-port = 9003; 99 authelia-metrics-port = 9004; 100in 101{ 102 imports = [ 103 srvos.nixosModules.server 104 srvos.nixosModules.hardware-hetzner-cloud 105 srvos.nixosModules.mixins-terminfo 106 107 hypixel-bank-tracker.nixosModules.default 108 109 tangled.nixosModules.knot 110 tangled.nixosModules.spindle 111 ]; 112 113 config = { 114 boot.loader.grub.enable = true; 115 boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" "ext4" ]; 116 117 # Single network card is `eth0` 118 networking.usePredictableInterfaceNames = false; 119 120 networking.nameservers = [ "2001:4860:4860::8888" "2001:4860:4860::8844" ]; 121 122 networking = { 123 interfaces.${ext-if} = { 124 ipv4.addresses = [{ address = external-ip; prefixLength = external-netmask; }]; 125 ipv6.addresses = [{ address = external-ip6; prefixLength = external-netmask6; }]; 126 }; 127 defaultGateway = { interface = ext-if; address = external-gw; }; 128 defaultGateway6 = { interface = ext-if; address = external-gw6; }; 129 130 # Reflect firewall configuration on Hetzner 131 firewall.allowedTCPPorts = [ 22 80 443 ]; 132 firewall.allowedUDPPorts = [ headscale-derp-port ]; 133 }; 134 135 services.qemuGuest.enable = true; 136 137 services.openssh.enable = true; 138 139 services.tailscale.enable = true; 140 141 security.sudo.wheelNeedsPassword = false; 142 143 local.fragment.nix.enable = true; 144 145 programs.fish.enable = true; 146 147 services.fail2ban = { 148 enable = true; 149 150 maxretry = 5; 151 ignoreIP = [ ]; 152 153 bantime = "24h"; 154 bantime-increment = { 155 enable = true; 156 multipliers = "1 2 4 8 16 32 64"; 157 maxtime = "168h"; 158 overalljails = true; 159 }; 160 161 jails = { }; 162 }; 163 164 services.caddy = { 165 enable = true; 166 167 globalConfig = '' 168 metrics { per_host } 169 170 on_demand_tls { 171 ask http://localhost:${toString pds-port}/tls-check 172 } 173 ''; 174 175 virtualHosts.${website-hostname}.extraConfig = 176 '' 177 @discord { 178 path /.well-known/discord 179 method GET HEAD 180 } 181 route @discord { 182 header { 183 Access-Control-Allow-Origin "*" 184 X-Robots-Tag "noindex" 185 } 186 root ${well-known-discord-dir} 187 file_server 188 } 189 '' + 190 '' 191 @webfinger { 192 path /.well-known/webfinger 193 method GET HEAD 194 query resource=acct:milo@wiro.world 195 query resource=mailto:milo@wiro.world 196 query resource=https://wiro.world 197 query resource=https://wiro.world/ 198 } 199 route @webfinger { 200 header { 201 Content-Type "application/jrd+json" 202 Access-Control-Allow-Origin "*" 203 X-Robots-Tag "noindex" 204 } 205 root ${webfinger-dir} 206 file_server 207 } 208 '' + 209 '' 210 reverse_proxy /.well-known/matrix/* http://localhost:${toString matrix-port} 211 '' + 212 # TODO: host website on server with automatic deployment 213 '' 214 reverse_proxy https://mrnossiom.github.io { 215 header_up Host {http.request.host} 216 } 217 ''; 218 219 virtualHosts.${grafana-hostname}.extraConfig = '' 220 reverse_proxy http://localhost:${toString grafana-port} 221 ''; 222 223 virtualHosts.${pds-hostname} = { 224 serverAliases = [ "*.${pds-hostname}" ]; 225 extraConfig = '' 226 tls { on_demand } 227 reverse_proxy http://localhost:${toString pds-port} 228 ''; 229 }; 230 231 virtualHosts.${tangled-knot-hostname}.extraConfig = '' 232 reverse_proxy http://localhost:${toString tangled-knot-port} 233 ''; 234 235 virtualHosts.${tangled-spindle-hostname}.extraConfig = '' 236 reverse_proxy http://localhost:${toString tangled-spindle-port} 237 ''; 238 239 virtualHosts.${thelounge-hostname}.extraConfig = '' 240 reverse_proxy http://localhost:${toString thelounge-port} 241 ''; 242 243 virtualHosts.${headscale-hostname}.extraConfig = '' 244 reverse_proxy http://localhost:${toString headscale-port} 245 ''; 246 247 virtualHosts.${lldap-hostname}.extraConfig = '' 248 reverse_proxy http://localhost:${toString lldap-port} 249 ''; 250 251 virtualHosts.${authelia-hostname}.extraConfig = '' 252 reverse_proxy http://localhost:${toString authelia-port} 253 ''; 254 255 virtualHosts.${matrix-hostname}.extraConfig = '' 256 reverse_proxy /_matrix/* http://localhost:${toString matrix-port} 257 ''; 258 259 virtualHosts.${goatcounter-hostname}.extraConfig = '' 260 reverse_proxy http://localhost:${toString goatcounter-port} 261 ''; 262 263 virtualHosts.${vaultwarden-hostname}.extraConfig = '' 264 reverse_proxy http://localhost:${toString vaultwarden-port} 265 ''; 266 267 virtualHosts.${miniflux-hostname}.extraConfig = '' 268 reverse_proxy http://localhost:${toString miniflux-port} 269 ''; 270 271 virtualHosts.${static-hostname}.extraConfig = '' 272 root /var/www/static 273 file_server browse 274 ''; 275 276 virtualHosts."hypixel-bank-tracker.xyz".extraConfig = '' 277 reverse_proxy http://localhost:${toString hbt-main-port} 278 ''; 279 virtualHosts."banana.hypixel-bank-tracker.xyz".extraConfig = '' 280 reverse_proxy http://localhost:${toString hbt-banana-port} 281 ''; 282 283 virtualHosts.${warrior-hostname}.extraConfig = '' 284 forward_auth localhost:${toString authelia-port} { 285 uri /api/authz/forward-auth 286 } 287 reverse_proxy http://localhost:${toString warrior-port} 288 ''; 289 }; 290 291 age.secrets.pds-env.file = ../../secrets/pds-env.age; 292 services.bluesky-pds = { 293 enable = true; 294 295 settings = { 296 PDS_HOSTNAME = "pds.wiro.world"; 297 PDS_PORT = pds-port; 298 # is in systemd /tmp subfolder 299 LOG_DESTINATION = "/tmp/pds.log"; 300 }; 301 302 environmentFiles = [ 303 config.age.secrets.pds-env.path 304 ]; 305 }; 306 307 services.tangled.knot = { 308 enable = true; 309 openFirewall = true; 310 311 motd = "Welcome to @wiro.world's knot!\n"; 312 server = { 313 listenAddr = "localhost:${toString tangled-knot-port}"; 314 hostname = tangled-knot-hostname; 315 owner = tangled-owner; 316 }; 317 }; 318 319 services.tangled.spindle = { 320 enable = true; 321 322 server = { 323 listenAddr = "localhost:${toString tangled-spindle-port}"; 324 hostname = tangled-spindle-hostname; 325 owner = tangled-owner; 326 }; 327 }; 328 329 age.secrets.grafana-oidc-secret = { file = ../../secrets/grafana-oidc-secret.age; owner = "grafana"; }; 330 services.grafana = { 331 enable = true; 332 333 settings = { 334 server = { 335 http_port = grafana-port; 336 domain = grafana-hostname; 337 root_url = "https://${grafana-hostname}"; 338 }; 339 340 "auth.generic_oauth" = { 341 enable = true; 342 name = "Authelia"; 343 icon = "signin"; 344 345 client_id = "grafana"; 346 client_secret_path = config.age.secrets.grafana-oidc-secret.path; 347 auto_login = true; 348 349 scopes = [ "openid" "profile" "email" "groups" ]; 350 auth_url = "https://auth.wiro.world/api/oidc/authorization"; 351 token_url = "https://auth.wiro.world/api/oidc/token"; 352 api_url = "https://auth.wiro.world/api/oidc/userinfo"; 353 use_pkce = true; 354 }; 355 }; 356 }; 357 358 services.prometheus = { 359 enable = true; 360 port = prometheus-port; 361 362 scrapeConfigs = [ 363 { 364 job_name = "caddy"; 365 static_configs = [{ targets = [ "localhost:${toString 2019}" ]; }]; 366 } 367 { 368 job_name = "node-exporter"; 369 static_configs = [{ targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ]; }]; 370 } 371 { 372 job_name = "headscale"; 373 static_configs = [{ targets = [ "localhost:${toString headscale-metrics-port}" ]; }]; 374 } 375 { 376 job_name = "authelia"; 377 static_configs = [{ targets = [ "localhost:${toString authelia-metrics-port}" ]; }]; 378 } 379 { 380 job_name = "miniflux"; 381 static_configs = [{ targets = [ "localhost:${toString miniflux-port}" ]; }]; 382 } 383 ]; 384 385 exporters.node = { 386 enable = true; 387 port = prometheus-node-exporter-port; 388 }; 389 }; 390 391 services.thelounge = { 392 enable = true; 393 port = thelounge-port; 394 public = false; 395 396 extraConfig = { 397 host = "127.0.0.1"; 398 reverseProxy = true; 399 400 # TODO: use ldap, find a way to hide password 401 }; 402 }; 403 404 age.secrets.headscale-oidc-secret = { file = ../../secrets/headscale-oidc-secret.age; owner = config.services.headscale.user; }; 405 # TODO: add dependency on authelia 406 services.headscale = { 407 enable = true; 408 409 port = headscale-port; 410 settings = { 411 server_url = "https://${headscale-hostname}"; 412 metrics_listen_addr = "127.0.0.1:${toString headscale-metrics-port}"; 413 414 policy.path = json-format.generate "policy.json" { 415 acls = [ 416 { 417 action = "accept"; 418 src = [ "autogroup:member" ]; 419 dst = [ "autogroup:self:*" ]; 420 } 421 ]; 422 ssh = [ 423 { 424 action = "accept"; 425 src = [ "autogroup:member" ]; 426 dst = [ "autogroup:self" ]; 427 # Adding root here is privilege escalation as a feature :) 428 users = [ "autogroup:nonroot" ]; 429 } 430 ]; 431 }; 432 433 # disable TLS 434 tls_cert_path = null; 435 tls_key_path = null; 436 437 dns = { 438 magic_dns = true; 439 base_domain = "net.wiro.world"; 440 441 override_local_dns = true; 442 # Quad9 nameservers 443 nameservers.global = [ "9.9.9.9" "149.112.112.112" "2620:fe::fe" "2620:fe::9" ]; 444 }; 445 446 oidc = { 447 only_start_if_oidc_is_available = true; 448 issuer = "https://auth.wiro.world"; 449 client_id = "headscale"; 450 client_secret_path = config.age.secrets.headscale-oidc-secret.path; 451 scope = [ "openid" "profile" "email" "groups" ]; 452 pkce.enabled = true; 453 }; 454 455 derp.server = { 456 enable = true; 457 stun_listen_addr = "0.0.0.0:${toString headscale-derp-port}"; 458 }; 459 }; 460 }; 461 462 age.secrets.lldap-env.file = ../../secrets/lldap-env.age; 463 users.users.lldap = { isSystemUser = true; group = "lldap"; }; 464 users.groups.lldap = { }; 465 age.secrets.lldap-user-pass = { file = ../../secrets/lldap-user-pass.age; owner = "lldap"; }; 466 services.lldap = { 467 enable = true; 468 settings = { 469 http_url = "https://${lldap-hostname}"; 470 http_port = lldap-port; 471 472 ldap_user_pass_file = config.age.secrets.lldap-user-pass.path; 473 force_ldap_user_pass_reset = false; 474 475 ldap_base_dn = "dc=wiro,dc=world"; 476 }; 477 environmentFile = config.age.secrets.lldap-env.path; 478 }; 479 480 age.secrets.authelia-jwt-secret = { file = ../../secrets/authelia-jwt-secret.age; owner = config.services.authelia.instances.main.user; }; 481 age.secrets.authelia-issuer-private-key = { file = ../../secrets/authelia-issuer-private-key.age; owner = config.services.authelia.instances.main.user; }; 482 age.secrets.authelia-storage-key = { file = ../../secrets/authelia-storage-key.age; owner = config.services.authelia.instances.main.user; }; 483 age.secrets.authelia-ldap-password = { file = ../../secrets/authelia-ldap-password.age; owner = config.services.authelia.instances.main.user; }; 484 age.secrets.authelia-smtp-password = { file = ../../secrets/authelia-smtp-password.age; owner = config.services.authelia.instances.main.user; }; 485 services.authelia.instances.main = { 486 enable = true; 487 488 secrets = { 489 jwtSecretFile = config.age.secrets.authelia-jwt-secret.path; 490 oidcIssuerPrivateKeyFile = config.age.secrets.authelia-issuer-private-key.path; 491 storageEncryptionKeyFile = config.age.secrets.authelia-storage-key.path; 492 }; 493 environmentVariables = { 494 AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = config.age.secrets.authelia-ldap-password.path; 495 AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = config.age.secrets.authelia-smtp-password.path; 496 }; 497 settings = { 498 server.address = "localhost:${toString authelia-port}"; 499 storage.local.path = "/var/lib/authelia-main/db.sqlite3"; 500 telemetry.metrics = { 501 enabled = true; 502 address = "tcp://:${toString authelia-metrics-port}/metrics"; 503 }; 504 505 session = { 506 cookies = [{ 507 domain = "wiro.world"; 508 authelia_url = "https://${authelia-hostname}"; 509 default_redirection_url = "https://wiro.world"; 510 }]; 511 }; 512 513 authentication_backend.ldap = { 514 address = "ldap://localhost:3890"; 515 timeout = "5m"; # replace with systemd dependency 516 517 user = "uid=authelia,ou=people,dc=wiro,dc=world"; 518 # Set in `AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE`. 519 # password = ""; 520 521 base_dn = "dc=wiro,dc=world"; 522 users_filter = "(&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=person))"; 523 additional_users_dn = "ou=people"; 524 groups_filter = "(&(member={dn})(objectClass=groupOfNames))"; 525 additional_groups_dn = "ou=groups"; 526 527 attributes = { 528 username = "uid"; 529 display_name = "cn"; 530 given_name = "givenname"; 531 family_name = "last_name"; 532 mail = "mail"; 533 picture = "avatar"; 534 535 group_name = "cn"; 536 }; 537 }; 538 539 access_control = { 540 default_policy = "deny"; 541 # Rules are sequential and do not apply to OIDC 542 rules = [ 543 { 544 domain = "headscale.wiro.world"; 545 policy = "two_factor"; 546 547 } 548 { 549 domain = "news.wiro.world"; 550 policy = "one_factor"; 551 552 subject = [ [ "group:miniflux" "oauth2:client:miniflux" ] ]; 553 } 554 { 555 domain = "*.wiro.world"; 556 policy = "two_factor"; 557 } 558 ]; 559 }; 560 561 identity_providers.oidc = { 562 enforce_pkce = "always"; 563 564 authorization_policies = 565 let 566 mkStrictPolicy = policy: subject: 567 { default_policy = "deny"; rules = [{ inherit policy subject; }]; }; 568 in 569 { 570 headscale = mkStrictPolicy "two_factor" [ "group:headscale" ]; 571 tailscale = mkStrictPolicy "two_factor" [ "group:headscale" ]; 572 grafana = mkStrictPolicy "one_factor" [ "group:grafana" ]; 573 miniflux = mkStrictPolicy "one_factor" [ "group:miniflux" ]; 574 }; 575 576 claims_policies.headscale = { id_token = [ "email" "name" "preferred_username" "picture" "groups" ]; }; 577 578 clients = [ 579 { 580 client_name = "Headscale"; 581 client_id = "headscale"; 582 client_secret = "$pbkdf2-sha256$310000$XY680D9gkSoWhD0UtYHNFg$ptWB3exOYCga6uq1N.oimuV3ILjK3F8lBWBpsBpibos"; 583 redirect_uris = [ "https://${headscale-hostname}/oidc/callback" ]; 584 authorization_policy = "headscale"; 585 claims_policy = "headscale"; 586 } 587 { 588 client_name = "Tailscale"; 589 client_id = "tailscale"; 590 client_secret = "$pbkdf2-sha256$310000$PcUaup9aWKI9ZLeCF6.avw$FpsTxkDaxcoQlBi8aIacegXpjEDiCI6nXcaHyZ2Sxyc"; 591 redirect_uris = [ "https://login.tailscale.com/a/oauth_response" ]; 592 authorization_policy = "tailscale"; 593 } 594 { 595 client_name = "Grafana Console"; 596 client_id = "grafana"; 597 client_secret = "$pbkdf2-sha256$310000$UkwrqxTZodGMs9.Ca2cXAA$HCWFgQbFHGXZpuz.I3HHdkTZLUevRVGlhKEFaOlPmKs"; 598 redirect_uris = [ "https://${grafana-hostname}/login/generic_oauth" ]; 599 authorization_policy = "grafana"; 600 } 601 { 602 client_name = "Miniflux"; 603 client_id = "miniflux"; 604 client_secret = "$pbkdf2-sha256$310000$uPqbWfCOBXDY6nV1vsx3uA$HOWG2hL.c/bs9Dwaee3b9DxjH7KFO.SaZMbasXV9Vdw"; 605 redirect_uris = [ "https://${miniflux-hostname}/oauth2/oidc/callback" ]; 606 authorization_policy = "miniflux"; 607 } 608 ]; 609 }; 610 611 notifier.smtp = { 612 address = "smtp://smtp.resend.com:2587"; 613 username = "resend"; 614 # Set in `AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE`. 615 # password = ""; 616 sender = "authelia@wiro.world"; 617 }; 618 }; 619 }; 620 621 age.secrets.tuwunel-registration-tokens = { file = ../../secrets/tuwunel-registration-tokens.age; owner = config.services.matrix-tuwunel.user; }; 622 services.matrix-tuwunel = { 623 enable = true; 624 625 settings.global = { 626 address = [ "127.0.0.1" ]; 627 port = [ matrix-port ]; 628 629 server_name = "wiro.world"; 630 well_known = { 631 client = "https://matrix.wiro.world"; 632 server = "matrix.wiro.world:443"; 633 }; 634 635 grant_admin_to_first_user = true; 636 new_user_displayname_suffix = ""; 637 638 allow_registration = true; 639 registration_token_file = config.age.secrets.tuwunel-registration-tokens.path; 640 }; 641 }; 642 643 services.goatcounter = { 644 enable = true; 645 646 port = goatcounter-port; 647 proxy = true; 648 extraArgs = [ "-automigrate" ]; 649 }; 650 651 age.secrets.vaultwarden-env.file = ../../secrets/vaultwarden-env.age; 652 services.vaultwarden = { 653 enable = true; 654 655 environmentFile = config.age.secrets.vaultwarden-env.path; 656 config = { 657 ROCKET_PORT = vaultwarden-port; 658 DOMAIN = "https://${vaultwarden-hostname}"; 659 SIGNUPS_ALLOWED = false; 660 ADMIN_TOKEN = "$argon2id$v=19$m=65540,t=3,p=4$YIe9wmrTsmjgZNPxe8m34O/d3XW3Fl/uZPPLQs79dAc$mjDVQSdBJqz2uBJuxtAvCIoHPzOnTDhNPuhER3dhHrY"; 661 662 SMTP_HOST = "smtp.resend.com"; 663 SMTP_PORT = 2465; 664 SMTP_SECURITY = "force_tls"; 665 SMTP_USERNAME = "resend"; 666 # SMTP_PASSWORD = ...; # Via secret env 667 SMTP_FROM = "bitwarden@wiro.world"; 668 SMTP_FROM_NAME = "Bitwarden wiro.world"; 669 }; 670 }; 671 672 users.users.miniflux = { isSystemUser = true; group = "miniflux"; }; 673 users.groups.miniflux = { }; 674 age.secrets.miniflux-oidc-secret = { file = ../../secrets/miniflux-oidc-secret.age; owner = "miniflux"; }; 675 services.miniflux = { 676 enable = true; 677 678 createDatabaseLocally = true; 679 config = { 680 BASE_URL = "https://${miniflux-hostname}/"; 681 LISTEN_ADDR = "127.0.0.1:${toString miniflux-port}"; 682 CREATE_ADMIN = 0; 683 684 METRICS_COLLECTOR = 1; 685 686 OAUTH2_PROVIDER = "oidc"; 687 OAUTH2_OIDC_PROVIDER_NAME = "wiro.world SSO"; 688 OAUTH2_CLIENT_ID = "miniflux"; 689 OAUTH2_CLIENT_SECRET_FILE = config.age.secrets.miniflux-oidc-secret.path; 690 OAUTH2_REDIRECT_URL = "https://${miniflux-hostname}/oauth2/oidc/callback"; 691 OAUTH2_OIDC_DISCOVERY_ENDPOINT = "https://auth.wiro.world"; 692 OAUTH2_USER_CREATION = 1; 693 DISABLE_LOCAL_AUTH = 1; 694 695 RUN_MIGRATIONS = 1; 696 697 # NetNewsWire is a very good iOS oss client that integrates well 698 # https://b.j4.lc/2025/05/05/setting-up-netnewswire-with-miniflux/ 699 }; 700 }; 701 702 age.secrets.hypixel-bank-tracker-main.file = ../../secrets/hypixel-bank-tracker-main.age; 703 services.hypixel-bank-tracker.instances.main = { 704 enable = true; 705 706 port = hbt-main-port; 707 environmentFile = config.age.secrets.hypixel-bank-tracker-main.path; 708 }; 709 710 age.secrets.hypixel-bank-tracker-banana.file = ../../secrets/hypixel-bank-tracker-banana.age; 711 services.hypixel-bank-tracker.instances.banana = { 712 enable = true; 713 714 port = hbt-banana-port; 715 environmentFile = config.age.secrets.hypixel-bank-tracker-banana.path; 716 }; 717 718 virtualisation.oci-containers.containers.archive-warrior = { 719 image = "atdr.meo.ws/archiveteam/warrior-dockerfile"; 720 ports = [ "127.0.0.1:${toString warrior-port}:8001" ]; 721 pull = "newer"; 722 }; 723 }; 724}