{ config, lib, pkgs, ... }: let cfg = config.services.phishboard; in { options.services.phishboard = { enable = lib.mkEnableOption "AZ Phishboard Next.js service"; package = lib.mkOption { type = lib.types.nullOr lib.types.package; default = null; description = "Phishboard package to run."; }; host = lib.mkOption { type = lib.types.str; default = "127.0.0.1"; description = "Host address the Phishboard service should bind to."; }; port = lib.mkOption { type = lib.types.port; default = 3000; description = "Port the Phishboard service should listen on."; }; environmentFile = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; description = '' File containing runtime environment variables, for example BASEROW_API_TOKEN, BASEROW_PHISHING_TABLE_URL, BASEROW_CAMPAIGNS_TABLE_URL, and DASHBOARD_PASSWORD. ''; }; }; config = lib.mkIf cfg.enable { assertions = [ { assertion = cfg.package != null; message = "services.phishboard.package must be set."; } ]; systemd.services.phishboard = { description = "AZ Phishboard"; wantedBy = ["multi-user.target"]; after = ["network-online.target"]; wants = ["network-online.target"]; environment = { HOSTNAME = cfg.host; PORT = toString cfg.port; NODE_ENV = "production"; NEXT_TELEMETRY_DISABLED = "1"; }; serviceConfig = { Type = "simple"; ExecStart = "${pkgs.nodejs_22}/bin/node ${cfg.package}/server.js"; WorkingDirectory = cfg.package; DynamicUser = true; Restart = "on-failure"; RestartSec = "10s"; CapabilityBoundingSet = ""; LockPersonality = true; NoNewPrivileges = true; PrivateDevices = true; PrivateTmp = true; ProtectClock = true; ProtectControlGroups = true; ProtectHome = true; ProtectHostname = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; ProtectSystem = "strict"; RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6"]; RestrictNamespaces = true; RestrictRealtime = true; RestrictSUIDSGID = true; SystemCallArchitectures = "native"; SystemCallFilter = ["@system-service" "~@privileged"]; } // lib.optionalAttrs (cfg.environmentFile != null) { EnvironmentFile = cfg.environmentFile; }; }; }; }