# module.nix self: { config, lib, pkgs, ... }: let cfg = config.services.conmorfeusz; # Helper function to convert attrset to CLI arguments # { host = "0.0.0.0"; port = 8888; } -> "--host '0.0.0.0' --port '8888'" attrsToArgs = attrs: lib.concatStringsSep " " ( lib.mapAttrsToList (name: value: "--${name} ${lib.escapeShellArg (toString value)}") attrs ); # Helper function to convert attrset to CLI arguments with prefix # { port = 3000; bin = "..."; } -> "--ccpl-port '3000' --ccpl-bin '...'" attrsToArgsWithPrefix = prefix: attrs: lib.concatStringsSep " " ( lib.mapAttrsToList (name: value: "--${prefix}-${name} ${lib.escapeShellArg (toString value)}") attrs ); in { options.services.conmorfeusz = { enableMorfeusz = lib.mkEnableOption "Morfeusz in environment.systemPackages"; enableConcraftPl = lib.mkEnableOption "Concraft-pl in environment.systemPackages"; conmorfeusz = { enable = lib.mkEnableOption "Conmorfeusz service"; config = lib.mkOption { type = lib.types.attrsOf (lib.types.oneOf [lib.types.str lib.types.int lib.types.bool]); default = {}; example = { host = "0.0.0.0"; port = 8888; workers = 4; }; description = '' Configuration passed to conmorfeusz as CLI arguments. Each key will be transformed into --key value. ''; }; concraft-pl = lib.mkOption { type = lib.types.attrsOf (lib.types.oneOf [lib.types.str lib.types.int lib.types.bool]); default = {}; example = { port = 3000; bin = "/\${pkgs.concraft-pl}/bin/concraft-pl"; core-num = 4; }; description = '' Concraft-pl configuration passed to conmorfeusz as CLI arguments. Each key will be transformed into --ccpl-key value. ''; }; openFirewall = lib.mkOption { type = lib.types.bool; default = false; description = "Whether to open the conmorfeusz port in the firewall."; }; openConcraftPlFirewall = lib.mkOption { type = lib.types.bool; default = false; description = "Whether to open the concraft-pl port in the firewall."; }; }; }; config = lib.mkMerge [ # Add morfeusz to systemPackages if enabled (lib.mkIf cfg.enableMorfeusz { environment.systemPackages = [self.packages.${pkgs.system}.morfeusz]; }) # Add concraft-pl to systemPackages if enabled (lib.mkIf cfg.enableConcraftPl { environment.systemPackages = [self.packages.${pkgs.system}.concraft-pl]; }) # Conmorfeusz service configuration (lib.mkIf cfg.conmorfeusz.enable { systemd.services.conmorfeusz = { description = "Conmorfeusz - Morfeusz + Concraft-pl service"; wantedBy = ["multi-user.target"]; serviceConfig = { Type = "simple"; ExecStart = let mainArgs = attrsToArgs cfg.conmorfeusz.config; ccplArgs = attrsToArgsWithPrefix "ccpl" cfg.conmorfeusz.concraft-pl; allArgs = lib.concatStringsSep " " (lib.filter (s: s != "") [mainArgs ccplArgs]); in "${self.packages.${pkgs.system}.conmorfeusz}/bin/conmorfeusz ${allArgs}"; Restart = "on-failure"; RestartSec = 5; # Security hardening DynamicUser = true; NoNewPrivileges = true; ProtectSystem = "strict"; ProtectHome = true; PrivateTmp = true; }; }; # Open conmorfeusz port in firewall networking.firewall.allowedTCPPorts = lib.mkIf cfg.conmorfeusz.openFirewall (lib.optional (cfg.conmorfeusz.config ? port) cfg.conmorfeusz.config.port); }) # Open concraft-pl port in firewall (separate, as it can be enabled independently) (lib.mkIf (cfg.conmorfeusz.enable && cfg.conmorfeusz.openConcraftPlFirewall) { networking.firewall.allowedTCPPorts = lib.optional (cfg.conmorfeusz.concraft-pl ? port) cfg.conmorfeusz.concraft-pl.port; }) ]; }