From 47d830eaed879fb03ec46c2f70f9478eadb1f2cd Mon Sep 17 00:00:00 2001 From: arcnmx Date: Sun, 23 Jun 2024 15:49:17 -0700 Subject: [PATCH] chore(syncplay): move to hakurei --- modules/nixos/syncplay.nix | 81 +++++++++++++++++++++++++++++ modules/system/exports/syncplay.nix | 25 +++++++++ nixos/secrets/syncplay.yaml | 7 +-- nixos/syncplay.nix | 55 ++++++++------------ systems/hakurei/default.nix | 1 + systems/hakurei/nixos.nix | 16 +++++- systems/tei/nixos.nix | 1 - tf/cloudflare_records.tf | 2 + 8 files changed, 151 insertions(+), 37 deletions(-) create mode 100644 modules/nixos/syncplay.nix create mode 100644 modules/system/exports/syncplay.nix diff --git a/modules/nixos/syncplay.nix b/modules/nixos/syncplay.nix new file mode 100644 index 00000000..89fa31a0 --- /dev/null +++ b/modules/nixos/syncplay.nix @@ -0,0 +1,81 @@ +{ + pkgs, + config, + gensokyo-zone, + lib, + ... +}: let + inherit (gensokyo-zone.lib) mkAlmostOptionDefault; + inherit (lib.options) mkOption; + inherit (lib.modules) mkIf mkMerge; + cfg = config.services.syncplay; + acme = config.security.acme.certs.${cfg.useACMECert}; + acmeDir = acme.directory; +in { + options.services.syncplay = with lib.types; { + openFirewall = mkOption { + type = bool; + default = false; + }; + useACMECert = mkOption { + type = nullOr str; + default = null; + }; + }; + + config.services.syncplay = { + certDir = let + certDir = pkgs.linkFarm "syncplay-certs" [ + { + name = "privkey.pem"; + path = "${acmeDir}/key.pem"; + } + rec { + name = "cert.pem"; + path = "${acmeDir}/${name}"; + } + rec { + name = "chain.pem"; + path = "${acmeDir}/${name}"; + } + ]; + in + mkIf (cfg.useACMECert != null) (mkAlmostOptionDefault certDir); + }; + + config.users = mkIf cfg.enable { + users.syncplay = mkIf (cfg.user == "syncplay") { + group = mkAlmostOptionDefault cfg.group; + isSystemUser = true; + home = mkAlmostOptionDefault "/var/lib/syncplay"; + }; + groups.syncplay = + mkIf (cfg.group == "syncplay") { + }; + }; + + config.networking.firewall = mkIf cfg.enable { + allowedTCPPorts = mkIf cfg.openFirewall [cfg.port]; + }; + + config.systemd.services.syncplay = mkIf cfg.enable { + wants = mkIf (cfg.useACMECert != null) ["acme-finished-${cfg.useACMECert}.target"]; + after = mkIf (cfg.useACMECert != null) ["acme-${cfg.useACMECert}.service"]; + confinement = { + enable = mkAlmostOptionDefault true; + packages = config.systemd.services.syncplay.path; + }; + path = mkIf (cfg.passwordFile != null || cfg.saltFile != null) [pkgs.coreutils]; + serviceConfig = { + StateDirectory = mkAlmostOptionDefault "syncplay"; + BindReadOnlyPaths = mkMerge [ + (mkIf (cfg.useACMECert != null) [ + "${acmeDir}" + ]) + (mkIf (cfg.certDir != null) [ + "${cfg.certDir}" + ]) + ]; + }; + }; +} diff --git a/modules/system/exports/syncplay.nix b/modules/system/exports/syncplay.nix new file mode 100644 index 00000000..9a8ccf99 --- /dev/null +++ b/modules/system/exports/syncplay.nix @@ -0,0 +1,25 @@ +{ + lib, + gensokyo-zone, + ... +}: let + inherit (gensokyo-zone.lib) mkAlmostOptionDefault; + inherit (lib.modules) mkIf; +in { + config.exports.services.syncplay = {config, ...}: { + displayName = mkAlmostOptionDefault "Syncplay"; + nixos = { + serviceAttr = "syncplay"; + assertions = mkIf config.enable [ + (nixosConfig: { + assertion = config.ports.default.port == nixosConfig.services.syncplay.port; + message = "port mismatch"; + }) + ]; + }; + ports.default = { + port = mkAlmostOptionDefault 8999; + protocol = "tcp"; + }; + }; +} diff --git a/nixos/secrets/syncplay.yaml b/nixos/secrets/syncplay.yaml index 1d4d8c57..b3446ebb 100644 --- a/nixos/secrets/syncplay.yaml +++ b/nixos/secrets/syncplay.yaml @@ -1,4 +1,5 @@ -syncplay-env: ENC[AES256_GCM,data:2u4RT6hJYuDhvRbYVO5t0T0EDnW8QUNdM2krbuJ5WBqKXfTXlIjLb5Bynt5J3/mSSp9DRCggqtXvZaUTxr4Oia5HIms4mxBkUrfareaRNm0=,iv:+IWjGtsmSUfw1wNpSSFA7Kvnhv+lG1F9a6T6N+QLAq8=,tag:ucEwim9yePrgEZOqQKsL2Q==,type:str] +syncplay-password: ENC[AES256_GCM,data:ZfzBG7SAV3cHoEHRYxqn5dshxP6DZAlXCCDPPYeo1g7aGWghqevotxWw,iv:BQ+V6ZLE/BmY4CfqM+CA+EpkNUx8lzbKzhuJp1J3n60=,tag:ABmwK8y2qwcnCE55CBVeEQ==,type:str] +syncplay-salt: ENC[AES256_GCM,data:rMxqzmJURbz+prQBwUMoCfOKOPWAxRsowkFrFjZ1ZWVZmvo/Td7kcpzACSlf/al6SSiI/367NBw/bmfyFH5G3w==,iv:zGGPzAOZL3fYRfREpPDxgoZmbyX1LDFSBCaryhTYyP4=,tag:GHATSzdorg9fcuLfy/lPMA==,type:str] sops: shamir_threshold: 1 kms: [] @@ -33,8 +34,8 @@ sops: QXlqSjU2N3ZvUmlYTXgwNWlJSHhPaVUKmSWxiM269wNw5VBh/OcHa6y21navnYIG 1hLHyeJFNXmCX/4+gTxjphcUaWc0zYx8duH63L66CTtCK/RT+Kdchg== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-01-16T19:11:23Z" - mac: ENC[AES256_GCM,data:mev1gtAUq0ujMdYVz4ipkGeyPn/rtLJZx993CVQRxTLVNOIdFkvJlbUwuSKWdZ29r1EdQgqDc7OoPekYfdO/7aMa/AyFoL1e/ohzD1mklGZLTP4YLB3/jB8fkqZUZXCdWtA2Ej1sRlBY2bUZx9rL/FpG9OyWA8zOlItReAEhDPM=,iv:rLXIGy4kY+tMHX6OHFE2DGtFU6niFUFCk/+CadXFP2w=,tag:j0GR5K4yxMQwVUyXCEyJrA==,type:str] + lastmodified: "2024-06-23T22:38:07Z" + mac: ENC[AES256_GCM,data:pHo5NfYGHV9WEp3SC8uG8M4XKS0qApgWbad9uF9LeANaZw1dDjlGUOVFjnwuXqFBUPT5lPjqxnavgllM8wZjyrIjD4j6QDjsMYmzKfqf1VmZG6TDG75u1VLBlrXQpDqzYzm3ioq2bZISkHkurVaQtY/HSZGOGm1Ltiy6MHySbiA=,iv:ezlHpCHifphzbmPjkvPhl5x2bxOldnRtX+KcP9GUbhI=,tag:Zzpz4wQGv0vti13p09A0vw==,type:str] pgp: - created_at: "2024-01-19T19:08:56Z" enc: |- diff --git a/nixos/syncplay.nix b/nixos/syncplay.nix index a142afe7..a203dbe6 100644 --- a/nixos/syncplay.nix +++ b/nixos/syncplay.nix @@ -1,45 +1,36 @@ { config, lib, - pkgs, - utils, ... -}: -with lib; let +}: let + inherit (lib.modules) mkIf mkDefault; cfg = config.services.syncplay; - args = - [ - "--disable-ready" - "--port" - cfg.port - ] - ++ optionals (cfg.certDir != null) ["--tls" cfg.certDir]; in { - sops.secrets.syncplay-env = { + sops.secrets = let sopsFile = mkDefault ./secrets/syncplay.yaml; owner = cfg.user; - }; - - users.users.${cfg.user} = { - inherit (cfg) group; - isSystemUser = true; - home = "/var/lib/syncplay"; - }; - users.groups.${cfg.group} = {}; - - networking.firewall.interfaces.local.allowedTCPPorts = [cfg.port]; + in + mkIf cfg.enable { + syncplay-password = { + inherit sopsFile owner; + }; + syncplay-salt = { + inherit sopsFile owner; + }; + }; services.syncplay = { - enable = true; - user = "syncplay"; + enable = mkDefault true; + extraArgs = [ + "--disable-ready" + ]; + user = mkDefault "syncplay"; + group = mkDefault "syncplay"; + saltFile = mkDefault config.sops.secrets.syncplay-salt.path; + passwordFile = mkDefault config.sops.secrets.syncplay-password.path; }; - systemd.services.syncplay = mkIf cfg.enable { - serviceConfig = { - StateDirectory = "syncplay"; - EnvironmentFile = singleton config.sops.secrets.syncplay-env.path; - ExecStart = mkForce [ - "${pkgs.syncplay-nogui}/bin/syncplay-server ${utils.escapeSystemdExecArgs args}" - ]; - }; + + networking.firewall = mkIf (cfg.enable && !cfg.openFirewall) { + interfaces.local.allowedTCPPorts = [cfg.port]; }; } diff --git a/systems/hakurei/default.nix b/systems/hakurei/default.nix index 00a9231f..797c5111 100644 --- a/systems/hakurei/default.nix +++ b/systems/hakurei/default.nix @@ -20,6 +20,7 @@ services = { tailscale.enable = true; samba.enable = true; + syncplay.enable = true; vouch-proxy = { enable = true; displayName = "Vouch Proxy/local"; diff --git a/systems/hakurei/nixos.nix b/systems/hakurei/nixos.nix index a3c0a660..b90c8c71 100644 --- a/systems/hakurei/nixos.nix +++ b/systems/hakurei/nixos.nix @@ -6,7 +6,7 @@ ... }: let inherit (lib.modules) mkIf mkMerge; - inherit (config.services) nginx; + inherit (config.services) nginx syncplay; inherit (nginx) virtualHosts; hassVouch = false; in { @@ -53,6 +53,7 @@ in { nixos.access.invidious nixos.wake-chen nixos.samba + nixos.syncplay ./reisen-ssh.nix ]; @@ -109,6 +110,15 @@ in { (mkIf config.services.tailscale.enable "smb.tail.${config.networking.domain}") ]; }; + syncplay = { + inherit (syncplay) group; + domain = "syncplay.${config.networking.domain}"; + extraDomainNames = [ + "syncplay.local.${config.networking.domain}" + "syncplay.int.${config.networking.domain}" + (mkIf config.services.tailscale.enable "syncplay.tail.${config.networking.domain}") + ]; + }; sso = { inherit (nginx) group; domain = virtualHosts.keycloak.serverName; @@ -400,6 +410,10 @@ in { services.samba.tls = { useACMECert = "samba"; }; + services.syncplay = { + openFirewall = true; + useACMECert = "syncplay"; + }; services.tailscale.advertiseExitNode = true; diff --git a/systems/tei/nixos.nix b/systems/tei/nixos.nix index cc1d9a94..5b303f8b 100644 --- a/systems/tei/nixos.nix +++ b/systems/tei/nixos.nix @@ -23,7 +23,6 @@ in { nixos.access.nfandroidtv nixos.home-assistant nixos.zigbee2mqtt - nixos.syncplay nixos.grocy nixos.barcodebuddy ./cloudflared.nix diff --git a/tf/cloudflare_records.tf b/tf/cloudflare_records.tf index 96530f9e..5dc18a31 100644 --- a/tf/cloudflare_records.tf +++ b/tf/cloudflare_records.tf @@ -34,6 +34,7 @@ module "hakurei_system_records" { "z2m", "grocy", "bbuddy", + "syncplay", "yt", ] global_subdomains = [ @@ -46,6 +47,7 @@ module "hakurei_system_records" { "mqtt", "kitchen", "webrx", + "syncplay", "yt", ] }