Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I086cdbfcd0a0d1d87173a2cf97f5b5416a6a6964
173 lines
4.4 KiB
Nix
173 lines
4.4 KiB
Nix
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 = {
|
|
port = mkOption {
|
|
type = port;
|
|
default = 3000;
|
|
};
|
|
|
|
user = mkOption {
|
|
type = str;
|
|
default = "troutbot";
|
|
description = "User to run Troutbot under";
|
|
};
|
|
|
|
group = mkOption {
|
|
type = str;
|
|
default = "troutbot";
|
|
description = "Group to run Troutbot under";
|
|
};
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
users = {
|
|
groups.${cfg.settings.group} = {};
|
|
users.${cfg.settings.user} = {
|
|
isSystemUser = true;
|
|
inherit (cfg.settings) group;
|
|
};
|
|
};
|
|
|
|
systemd.services.troutbot = {
|
|
description = "Troutbot - GitHub PR/Issue Analysis Bot";
|
|
documentation = ["https://github.com/notashelf/troutbot"];
|
|
after = ["network-online.target"];
|
|
wants = ["network-online.target"];
|
|
wantedBy = ["multi-user.target"];
|
|
|
|
environment = {
|
|
NODE_ENV = "production";
|
|
CONFIG_PATH = cfg.configPath;
|
|
PORT = toString cfg.port;
|
|
};
|
|
|
|
serviceConfig = {
|
|
Type = "simple";
|
|
User = cfg.user;
|
|
Group = cfg.group;
|
|
ExecStart = "${lib.getExe cfg.package}";
|
|
|
|
# Restart policy with rate limiting
|
|
Restart = "on-failure";
|
|
RestartSec = "5s";
|
|
StartLimitInterval = "60s";
|
|
StartLimitBurst = 3;
|
|
|
|
# Timeouts
|
|
TimeoutStartSec = "30s";
|
|
TimeoutStopSec = "30s";
|
|
|
|
# Working directory and state
|
|
WorkingDirectory = "/var/lib/troutbot";
|
|
StateDirectory = "troutbot";
|
|
StateDirectoryMode = "0750";
|
|
|
|
# Environment file for secrets
|
|
EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
|
|
|
|
# Security hardening
|
|
# Filesystem restrictions
|
|
ProtectSystem = "strict";
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
PrivateDevices = true;
|
|
|
|
# Process restrictions
|
|
NoNewPrivileges = true;
|
|
ProtectKernelTunables = true;
|
|
ProtectKernelModules = true;
|
|
ProtectControlGroups = true;
|
|
ProtectClock = true;
|
|
|
|
# Memory and execution restrictions
|
|
MemoryDenyWriteExecute = true;
|
|
RestrictRealtime = true;
|
|
RestrictSUIDSGID = true;
|
|
LockPersonality = true;
|
|
|
|
# IPC cleanup
|
|
RemoveIPC = true;
|
|
|
|
# Capabilities
|
|
CapabilityBoundingSet = [""]; # no capabilities needed
|
|
AmbientCapabilities = []; # no ambient capabilities
|
|
|
|
# System call filtering
|
|
SystemCallFilter = [
|
|
"@system-service"
|
|
"~@privileged"
|
|
"~@resources"
|
|
];
|
|
SystemCallErrorNumber = "EPERM";
|
|
|
|
# Address families, only IPv4/IPv6 needed
|
|
RestrictAddressFamilies = [
|
|
"AF_INET"
|
|
"AF_INET6"
|
|
"AF_UNIX"
|
|
"AF_NETLINK" # for DNS resolution
|
|
];
|
|
|
|
UMask = "0027";
|
|
DeviceAllow = [];
|
|
};
|
|
};
|
|
|
|
serviceConfig = {
|
|
Type = "simple";
|
|
User = cfg.settings.user;
|
|
Group = cfg.settings.group;
|
|
ExecStart = "${lib.getExe cfg.package}";
|
|
Restart = "on-failure";
|
|
EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile;
|
|
WorkingDirectory = "/var/lib/troutbot";
|
|
StateDirectory = "troutbot";
|
|
ProtectSystem = "strict";
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
NoNewPrivileges = true;
|
|
};
|
|
};
|
|
}
|