diff --git a/common/auths.yaml b/common/auths.yaml index 1683407..8f795d2 100644 --- a/common/auths.yaml +++ b/common/auths.yaml @@ -1,5 +1,5 @@ -cloudflare: - singularity: ENC[AES256_GCM,data:pb2HNPTSAJ47oOeo77+lR1WrCpjMm8UtqOvHJWpKlnOcvw+2q2S2SpB3CbY5Ovp28Vq29paVUOnc5f2SZA==,iv:H5tf/Uq9uk4u0ZPxmW7UrgRXuHMGBU8KTMwnhODC7IQ=,tag:xvte0Rkh8Rgds6r5VIkTUA==,type:str] +cloudflare: ENC[AES256_GCM,data:g1aQmfbkgiNOblIz/4CUU1MYgIPV5obFiH37+80hrPqFpAeR78PKOWJ9gmpwvwq2yKbyr59Urn0JyhOqsQ==,iv:I1Qjn6KSlokRwa5lMX3YwhsSFDpgd7RX+xVbS61z/ys=,tag:ycXEik7WAV92JRLP4huLFw==,type:str] +coturn: ENC[AES256_GCM,data:3JQCzWn3RJcGgMyfS+Wm/IL1cTSh/BFcVHhI,iv:aCmkJJt6wIjL2dIe6MUDNZieoq4siyb4T1x7SuwNrIg=,tag:OKtbQE+ykC7iASQq0pwe9w==,type:str] mail: macronova: password: ENC[AES256_GCM,data:wJMS3WqmAMQiOiyDUvmwH6Bes4L8GZC/2MxXP23M+RUrN7esqQsaMXLksY/33TuopuekVAvW9K+D2go5quaxdZhB/cVrhXqIjLVLV6Wa+WkYlbeQvJ5ix3R40X455opndrCQCQslatzcgGxmMS8qj5j0UcOfng==,iv:jfo7REVvIDI9MiWRsBi4MoTHfO6lHY5oQI9WyUecnnQ=,tag:hrSHzh4DK5Skav6A3fwD5A==,type:str] @@ -48,8 +48,8 @@ sops: UnlUY25pOGJ2T1VoTW0yeTFEL2NNTVUKHFdlBryccJAKz26+oECG8tx/FvhZEe0E MBRoWFu+LHaAUgaOKEBMUHZKzY7Q+TahAsdsy+VErmRkI6i/Hh10ww== -----END AGE ENCRYPTED FILE----- - lastmodified: "2023-11-28T05:25:46Z" - mac: ENC[AES256_GCM,data:e6p67apo/byZ1dNhvHqcbcUOnTFInoL9t2RGki8Wd114w+1IZxfPAmXzvoea3txXWnrvCuuZBVD+RglcWjbkvE54J8YfACgRN5+93NLWVVHrgbwL7WiI+W+rpzUqiWxByD72ee9rvG1dehAEAT0QEARVehIHpPK8F9/i/a3F+IA=,iv:rjtqpbKe4FyrX4RdVMwyqkCDMSP1rUaZoC9U9CAlzR0=,tag:4KSAB5eooNTdd/2ff9zL5Q==,type:str] + lastmodified: "2024-09-01T06:31:43Z" + mac: ENC[AES256_GCM,data:w6s0HiUCsaVU0aYkCuIwLxW/NTP3dZbDZOS8zOAKgK4mBecs9MlBzFY6cQzM657aYvK/JibyD2L6AsjrdX9HOiN0dEFikDAaZ6OvyCoaxYawZF/aFPKR92sWzuMMvaU8g+g3F3tyhq/SR1ojHyPFztbkrfxIkm+ORl17w56Eb5E=,iv:7088zB1C/1Dt7zBJNRaTcDVJRa28dwPV43vR/yRc/mA=,tag:geuuukzQ4A8wofkK5Co4jg==,type:str] pgp: [] unencrypted_suffix: _unencrypted - version: 3.8.1 + version: 3.9.0 diff --git a/common/constants.nix b/common/constants.nix index 6451c25..753eedf 100644 --- a/common/constants.nix +++ b/common/constants.nix @@ -31,6 +31,10 @@ with lib; { default = { aria2 = 30206; conduit = 29800; + coturn = 12616; + coturn-tls = 38313; + coturn-relay-udp-min = 17105; + coturn-relay-udp-max = 17184; forgejo = 47674; headscale = 27327; http = 80; @@ -55,7 +59,7 @@ with lib; { type = types.listOf types.str; default = if config.services.openssh.enable - then builtins.map (key: key.path) config.services.openssh.hostKeys + then map (key: key.path) config.services.openssh.hostKeys else ["/root/.ssh/${config.networking.hostName}"]; description = '' The private key files for sops. diff --git a/common/secrets.yaml b/common/secrets.yaml index 59799d5..128699c 100644 --- a/common/secrets.yaml +++ b/common/secrets.yaml @@ -1,5 +1,4 @@ aria2: ENC[AES256_GCM,data:wXS/Qgbu3bc9YDwVLCz+EIm8yMl8Un8XPwMv,iv:6j/mRhbA+Ps/8pvfmx0CYH2/iqxcG+roi50Gr6hC3SI=,tag:TK6D/9nmM76ODPH1irbREg==,type:str] -coturn: ENC[AES256_GCM,data:JvywrYxRl9QM4+WXH3xhkl4HZwGZurVYRX+S,iv:x6qmAS+11djd2w6pRr5KZYOy7vNtaC6rIw+XXDuu2aY=,tag:fT202mZDyRknuZK27RzgbA==,type:str] users: macronova: password: ENC[AES256_GCM,data:b1ct21IrepupexfV5CZV31/HRLRbhPY8EZDAA5rkYisSkke5Z6K8IlFePkbRAEre08qastLPr8FARal+s/co6kfR+aFcqD55hMcLaXvthg4xI6K4NRX0Ifp28JaEy0c515qLbvDLiyMsHQ==,iv:uK96mBa7ewu6SjPWb5aJDPKKASSqWFNGfRt88jWhbP8=,tag:eeVXcr3JOOpqO35y0wcXIQ==,type:str] @@ -36,8 +35,8 @@ sops: TG5mYWd3MnI5TlZiNXBjb0JJY3BvN0EKUd0ldQPe0/zdHjsmKEUhH7xkpO4nLfd5 fnTk1jGonJg+t+TqLLg/YYKlcNkgExWaIZ7wrd0RVKXOeC2BtM/wzQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-09-01T04:16:17Z" - mac: ENC[AES256_GCM,data:eGWeRIt35PZ09tYOFwSm5OMC/cehI8Y2W6x2zd4PXLDxZpJi1I7wdvQ1ch/sHabD9Q9SLA4YbisHdCCNEXUc2y0sjfjK9CMvQjsOKhkvtDVPtPvlpK99CthNT2EGER22FxCOr2Ozp95Xji1NQrtxEozZF1IhI2HlZ9a8hZvcue8=,iv:rtnEIZetXDS9QSlOwjWfSFWH56e1C2He0qxQjWjiYxA=,tag:rTQSKM7erUfHscW4dsJJHQ==,type:str] + lastmodified: "2024-09-01T04:30:14Z" + mac: ENC[AES256_GCM,data:ct8vaGlaPj69vzRm9baA2rxbuBM+MYX3Gjtg8m1cdHtldifvrYcw+hb1b9qC/Jhn3ppqpPO/8PhqqMU9U+aUBaSRV0AdDZs63T1/591SU3NDC6rmRBtkbrGk4g4jw4/Guw9Gs8F2r6xWf91KobAoHg9HLI+PK+pOSlfl4o8PBww=,iv:iPGlDkj5mnUxdtoSMztH8BPwSID0FJQDZfc2JenQngw=,tag:1QUCclV0Cs6hsPBANupj1g==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.9.0 diff --git a/linux/nebula/conduit.nix b/linux/nebula/conduit.nix index 3ca84a0..a518803 100644 --- a/linux/nebula/conduit.nix +++ b/linux/nebula/conduit.nix @@ -1,24 +1,19 @@ {config, ...}: { - services = with config.constants; { - coturn = { - enable = true; - realm = localhost; - static-auth-secret-file = config.sops.secrets.coturn.path; - use-auth-secret = true; - }; - matrix-conduit = { - enable = true; - settings.global = { - address = wildcard; - port = port.conduit; - turn_secret = "TbbL8a4tsv6HkR9esjkPa4$fTKX"; - turn_uris = [ - "turn:${localhost}?transport=udp" - "turn:${localhost}?transport=tcp" - ]; - server_name = domain; - }; + services.matrix-conduit = with config.constants; { + enable = true; + settings.global = { + address = wildcard; + port = port.conduit; + # Use secret file when possible + turn_secret = "84EoJSEVnlH@eiqqV7K!2vmAr^G"; + turn_uris = let + coturn-realm = "turn.${domain}"; + in [ + "turn:${coturn-realm}:${toString port.coturn-tls}?transport=udp" + "turn:${coturn-realm}:${toString port.coturn-tls}?transport=tcp" + ]; + turn_user_lifetime = "1h"; + server_name = domain; }; }; - sops.secrets.coturn = {}; } diff --git a/linux/singularity/caddy.nix b/linux/singularity/caddy.nix index 3478209..49d32d9 100644 --- a/linux/singularity/caddy.nix +++ b/linux/singularity/caddy.nix @@ -8,65 +8,74 @@ with config.constants; { enable = true; email = postMaster; virtualHosts = let + acme = fqdns: + builtins.listToAttrs (map (fqdn: { + name = fqdn; + value = { + extraConfig = '' + file_server ${wn "acme-challenge"}/* { + root ${config.security.acme.defaults.webroot}/ + } + ''; + useACMEHost = fqdn; + }; + }) + fqdns); + portStr = builtins.mapAttrs (n: v: toString v) port; homeSrv = s: "nebula:${portStr.${s}}"; localSrv = s: "${localhost}:${portStr.${s}}"; - msfqdn = config.mailserver.fqdn; mtfqdn = "matrix.${domain}"; - portStr = builtins.mapAttrs (n: v: toString v) port; wn = s: "/.well-known/${s}"; - in { - "${domain}".extraConfig = let - wnm = wn "matrix"; - in '' - header ${wnm}/* Content-Type application/json - header ${wnm}/* Access-Control-Allow-Origin * - respond ${wnm}/server `{ "m.server": "${mtfqdn}:${portStr.https}" }` - respond ${wnm}/client `{ - "m.homeserver": { "base_url": "https://${mtfqdn}" }, - "m.identity_server": { "base_url": "https://${mtfqdn}" } - }` - ''; - "aria2.${domain}".extraConfig = '' - reverse_proxy /jsonrpc ${homeSrv "aria2"} - file_server { - root ${pkgs.ariang}/share/ariang - } - ''; - "forgejo.${domain}".extraConfig = '' - reverse_proxy ${homeSrv "forgejo"} - ''; - "headscale.${domain}".extraConfig = '' - reverse_proxy ${localSrv "headscale"} - ''; - "jellyfin.${domain}".extraConfig = '' - reverse_proxy ${homeSrv "jellyfin"} - ''; - "jellyseerr.${domain}".extraConfig = '' - reverse_proxy ${homeSrv "jellyseerr"} - ''; - ${msfqdn} = { - extraConfig = '' - file_server ${wn "acme-challenge"}/* { - root ${config.security.acme.defaults.webroot}/ + in + { + "${domain}".extraConfig = let + wnm = wn "matrix"; + in '' + header ${wnm}/* Content-Type application/json + header ${wnm}/* Access-Control-Allow-Origin * + respond ${wnm}/server `{ "m.server": "${mtfqdn}:${portStr.https}" }` + respond ${wnm}/client `{ + "m.homeserver": { "base_url": "https://${mtfqdn}" }, + "m.identity_server": { "base_url": "https://${mtfqdn}" } + }` + ''; + "aria2.${domain}".extraConfig = '' + reverse_proxy /jsonrpc ${homeSrv "aria2"} + file_server { + root ${pkgs.ariang}/share/ariang } ''; - useACMEHost = msfqdn; - }; - "matrix.${domain}".extraConfig = '' - reverse_proxy /_matrix/* ${homeSrv "conduit"} - file_server { - root ${pkgs.fluffychat-web} - } - ''; - "vault.${domain}".extraConfig = '' - reverse_proxy ${localSrv "vault"} { - header_up X-Real-IP {remote_host} - } - ''; - "writefreely.${domain}".extraConfig = '' - reverse_proxy ${homeSrv "writefreely"} - ''; - }; + "forgejo.${domain}".extraConfig = '' + reverse_proxy ${homeSrv "forgejo"} + ''; + "headscale.${domain}".extraConfig = '' + reverse_proxy ${localSrv "headscale"} + ''; + "jellyfin.${domain}".extraConfig = '' + reverse_proxy ${homeSrv "jellyfin"} + ''; + "jellyseerr.${domain}".extraConfig = '' + reverse_proxy ${homeSrv "jellyseerr"} + ''; + "matrix.${domain}".extraConfig = '' + reverse_proxy /_matrix/* ${homeSrv "conduit"} + file_server { + root ${pkgs.fluffychat-web} + } + ''; + "vault.${domain}".extraConfig = '' + reverse_proxy ${localSrv "vault"} { + header_up X-Real-IP {remote_host} + } + ''; + "writefreely.${domain}".extraConfig = '' + reverse_proxy ${homeSrv "writefreely"} + ''; + } + // (acme [ + config.mailserver.fqdn + config.services.coturn.realm + ]); }; security.acme = { diff --git a/linux/singularity/coturn.nix b/linux/singularity/coturn.nix new file mode 100644 index 0000000..2bb711c --- /dev/null +++ b/linux/singularity/coturn.nix @@ -0,0 +1,19 @@ +{config, ...}: { + services.coturn = with config.constants; let + acmeDir = config.security.acme.certs.${coturn-realm}.directory; + coturn-realm = "turn.${domain}"; + in { + enable = true; + cert = "${acmeDir}/fullchain.pem"; + listening-port = port.coturn; + min-port = port.coturn-relay-udp-min; + max-port = port.coturn-relay-udp-max; + pkey = "${acmeDir}/key.pem"; + realm = coturn-realm; + static-auth-secret-file = config.sops.secrets.coturn.path; + tls-listening-port = port.coturn-tls; + use-auth-secret = true; + }; + + sops.secrets.coturn = {}; +} diff --git a/linux/singularity/default.nix b/linux/singularity/default.nix index 405b2eb..553dfcb 100644 --- a/linux/singularity/default.nix +++ b/linux/singularity/default.nix @@ -4,6 +4,7 @@ ../../common ./caddy.nix ./configuration.nix + ./coturn.nix ./hardware-configuration.nix ./headscale.nix ./mailserver.nix diff --git a/linux/singularity/network.nix b/linux/singularity/network.nix index 502060e..0682fd8 100644 --- a/linux/singularity/network.nix +++ b/linux/singularity/network.nix @@ -1,8 +1,15 @@ -{config, ...}: let - hn = config.networking.hostName; -in { +{config, ...}: { networking = { - firewall.allowedTCPPorts = with config.constants.port; [http https]; + firewall = with config.constants.port; { + allowedTCPPorts = [coturn coturn-tls http https]; + allowedUDPPorts = [coturn coturn-tls]; + allowedUDPPortRanges = [ + { + from = coturn-relay-udp-min; + to = coturn-relay-udp-max; + } + ]; + }; hostId = "2cadb253"; nftables.enable = true; }; @@ -10,11 +17,11 @@ in { services = { cloudflare-dyndns = { enable = true; - apiTokenFile = config.sops.secrets."cloudflare/${hn}".path; + apiTokenFile = config.sops.secrets.cloudflare.path; domains = builtins.attrNames config.services.caddy.virtualHosts; }; openssh.enable = true; }; - sops.secrets."cloudflare/${hn}" = {}; + sops.secrets.cloudflare = {}; }