self: { config, pkgs, lib, ... }: let inherit (lib.modules) mkIf; inherit (lib.options) mkOption mkEnableOption literalExpression; inherit (lib.types) nullOr str port package; defaultPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.troutbot; cfg = config.services.troutbot; in { options.services.troutbot = { enable = mkEnableOption "troutbot"; package = mkOption { type = nullOr package; default = defaultPackage; defaultText = literalExpression "inputs.troutbot.packages.${pkgs.stdenv.hostPlatform.system}.troutbot"; description = '' The Troutbot package to use. By default, this option will use the `packages.default` as exposed by this flake. ''; }; environmentFile = mkOption { type = nullOr str; default = null; description = '' Environment file for specifying additional settings such as secrets. ''; }; configPath = mkOption { type = nullOr str; default = null; description = '' File path containing the Troutbot Typescript config. ''; }; settings = { user = mkOption { type = str; default = "troutbot"; description = "User to run Troutbot under"; }; group = mkOption { type = str; default = "troutbot"; description = "Group to run Troutbot under"; }; port = mkOption { type = port; default = 3000; description = "Port to bind to"; }; }; }; config = mkIf cfg.enable { users = { groups.${cfg.settings.group} = {}; users.${cfg.settings.user} = { isSystemUser = true; inherit (cfg.settings) group; }; }; systemd.services.troutbot = { description = "Troutbot"; after = ["network-online.target"]; wants = ["network-online.target"]; wantedBy = ["multi-user.target"]; environment = { NODE_ENV = "production"; CONFIG_PATH = cfg.configPath; PORT = toString cfg.settings.port; }; serviceConfig = { Type = "simple"; User = cfg.settings.user; Group = cfg.settings.group; ExecStart = "${lib.getExe cfg.package}"; EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile; Restart = "on-failure"; RestartSec = "5s"; TimeoutStartSec = "10s"; TimeoutStopSec = "10s"; WorkingDirectory = "/var/lib/troutbot"; StateDirectory = "troutbot"; StateDirectoryMode = "0750"; # Hardening ProtectSystem = "strict"; ProtectHome = true; PrivateTmp = true; PrivateDevices = true; NoNewPrivileges = true; ProtectKernelTunables = true; ProtectKernelModules = true; ProtectControlGroups = true; ProtectClock = true; LockPersonality = true; }; }; }; }