the_prg_server_configuratio.../nix-system-configs/modules/system/traefik.nix
Christine Elisabeth Koppel 387fb668b3
All checks were successful
Build Nix modules (dry-run) / build-modules (push) Successful in 3m32s
Alejandra'd repo, added better dry run script.
2026-02-12 20:11:30 +01:00

256 lines
7.4 KiB
Nix

{
config,
pkgs,
lib,
...
}: let
choose = paths: builtins.head (builtins.filter (p: builtins.pathExists p) paths);
in {
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 = [
(choose [./modules/desktop-manager/sway_greetd_homemanager.nix ../desktop-manager/sway_greetd_homemanager.nix])
(choose [./modules/local/hostname_username.nix ../local/hostname_username.nix])
(choose [./modules/local/networking_local.nix ../local/networking_local.nix])
(choose [./modules/bootloader/seabios-assigned-iso-at-birth.nix ../bootloader/seabios-assigned-iso-at-birth.nix])
(choose [./modules/lix-default.nix ../lix-default.nix])
# Optionally: (choose [ ./modules/toolsets/remote_building.nix ../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 = {
# Bind on IPv6 as well as IPv4 by using [::]:80
address = "[::]:80";
asDefault = true;
http.redirections.entrypoint = {
to = "websecure";
scheme = "https";
};
};
websecure = {
# Bind on IPv6 as well as IPv4 by using [::]:443
address = "[::]:443";
asDefault = true;
http.tls = {
domains = [
{
main = "prg-radio.org";
sans = ["*.prg-radio.org"];
}
];
};
};
# Federation entrypoint: external TLS on 8448
federation = {
# Bind on IPv6 as well as IPv4 by using [::]:8448
address = "[::]:8448";
};
# TeamSpeak entry points
teamspeak-voice = {
# UDP entrypoint bind to IPv6 as well
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"];
# Pass TLS through to the backend (Conduit handles TLS on port 12244)
tls = {
passthrough = true;
};
};
# Also accept TLS passthrough on port 443 for the Matrix host so
# other servers that contact :443/_matrix/*
# will be forwarded to Conduit as well.
# I guess I had to declare the rule explicitly here again?
matrix-tls443 = {
# match by SNI to avoid interfering with other HTTPS sites
rule = "HostSNI(`lgbtq.prg-radio.org`)";
service = "matrix-federation";
entryPoints = ["websecure"];
tls = {
passthrough = true;
};
};
};
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";
};
}