{ config, pkgs, lib, ... }: { options.local = { hostname = lib.mkOption { type = lib.types.str; default = "nixos-default"; description = "System hostname"; }; username = lib.mkOption { type = lib.types.str; default = "user"; description = "Primary user username"; }; userDescription = lib.mkOption { type = lib.types.str; default = "NixOS User"; description = "Primary user description"; }; address = lib.mkOption { type = lib.types.str; default = "10.1.1.100"; description = "Static IP address"; }; }; imports = [ ./modules/desktop-manager/sway_greetd_homemanager.nix ./modules/local/hostname_username.nix ./modules/local/networking_local.nix ./modules/bootloader/seabios-assigned-iso-at-birth.nix ./modules/lix-default.nix # Optionally: ./modules/toolsets/remote_building.nix ]; config = { local.hostname = "nixos-traefik"; local.username = "traefikprg"; local.userDescription = "NixOS PRG Traefik Service"; local.address = "10.1.1.250"; services.traefik = { enable = true; group = "acme"; staticConfigOptions = { entryPoints = { web = { address = ":80"; asDefault = true; http.redirections.entrypoint = { to = "websecure"; scheme = "https"; }; }; websecure = { address = ":443"; asDefault = true; http.tls = { domains = [ { main = "prg-radio.org"; sans = ["*.prg-radio.org"]; } ]; }; }; # Federation entrypoint: external TLS on 8448 federation = { address = ":8448"; }; # TeamSpeak entry points teamspeak-voice = { address = ":9987/udp"; }; teamspeak-squery = { address = ":10022/tcp"; }; teamspeak-data = { address = ":30033/tcp"; }; }; log = { level = "INFO"; filePath = "${config.services.traefik.dataDir}/traefik.log"; format = "json"; }; api.dashboard = true; api.insecure = true; }; dynamicConfigOptions = { tls.certificates = [ { certFile = "/var/lib/acme/prg-radio.org/cert.pem"; keyFile = "/var/lib/acme/prg-radio.org/key.pem"; } ]; http.routers = { forgejo = { rule = "Host(`git.prg-radio.org`)"; service = "forgejo"; entryPoints = ["websecure"]; tls = {}; }; # Matrix HTTP router for client requests (Element etc.) matrix = { rule = "Host(`lgbtq.prg-radio.org`)"; service = "matrix"; entryPoints = ["websecure"]; tls = {}; }; wavelog = { rule = "Host(`wavelog.prg-radio.org`)"; service = "wavelog"; entryPoints = ["websecure"]; tls = {}; }; partdb = { rule = "Host(`partdb.prg-radio.org`)"; service = "partdb"; entryPoints = ["websecure"]; tls = {}; }; }; http.services = { forgejo.loadBalancer = { servers = [ {url = "http://10.1.1.4:3000";} ]; }; matrix.loadBalancer = { servers = [ {url = "http://10.1.1.248:12244";} ]; }; wavelog.loadBalancer = { servers = [ {url = "http://10.1.1.249:8086";} ]; }; partdb.loadBalancer = { servers = [ {url = "http://10.1.1.249:8087";} ]; }; }; # TCP routing for TeamSpeak tcp.routers = { teamspeak-squery = { rule = "HostSNI(`*`)"; service = "teamspeak-squery"; entryPoints = ["teamspeak-squery"]; }; teamspeak-data = { rule = "HostSNI(`*`)"; service = "teamspeak-data"; entryPoints = ["teamspeak-data"]; }; # Federation TCP router: incoming on :8448 -> Conduit backend matrix-federation = { rule = "HostSNI(`*`)"; service = "matrix-federation"; entryPoints = ["federation"]; }; }; tcp.services = { teamspeak-squery.loadBalancer = { servers = [ {address = "10.1.1.248:10022";} ]; }; teamspeak-data.loadBalancer = { servers = [ {address = "10.1.1.248:30033";} ]; }; matrix-federation.loadBalancer = { servers = [ {address = "10.1.1.248:12244";} ]; }; }; # UDP routing for TeamSpeak voice udp.routers = { teamspeak-voice = { entryPoints = ["teamspeak-voice"]; service = "teamspeak-voice"; }; }; udp.services = { teamspeak-voice.loadBalancer = { servers = [ {address = "10.1.1.248:9987";} ]; }; }; }; }; security.acme = { acceptTerms = true; defaults.email = "dtu.prg@gmail.com"; certs."prg-radio.org" = { domain = "*.prg-radio.org"; group = "acme"; dnsProvider = "cloudflare"; environmentFile = "/home/traefikprg/cloudflare/cloudflare.env"; reloadServices = ["traefik.service"]; }; }; # Enable Tailscale for remote access to Traefik dashboard and configuration services.tailscale.enable = true; systemd.services.traefik = { after = ["acme-finished-prg-radio.org.target"]; wants = ["acme-finished-prg-radio.org.target"]; }; networking.firewall.allowedTCPPorts = [80 443 10022 30033 8448]; networking.firewall.allowedUDPPorts = [80 443 9987]; system.stateVersion = "25.11"; }; }