caveman/nixos-module.nix

319 lines
9.4 KiB
Nix
Raw Normal View History

2022-11-03 19:49:00 +01:00
{ config, lib, pkgs, ... }:
let
cfg = config.services.caveman;
2023-01-26 00:49:00 +01:00
blocklistPath = "/etc/caveman.blocklist";
profanityPath = "/etc/caveman.profanity";
2023-01-26 00:49:00 +01:00
2022-11-03 19:49:00 +01:00
hunterDefaultSettings = {
redis = "redis://127.0.0.1:${toString cfg.redis.port}/";
2023-08-08 18:42:34 +02:00
database = "host=/var/run/postgresql user=caveman-hunter dbname=caveman";
hosts = [ "mastodon.social" ];
2022-11-03 19:49:00 +01:00
max_workers = 16;
2022-12-26 03:44:42 +01:00
prometheus_port = 9101;
2023-01-26 00:49:00 +01:00
blocklist = blocklistPath;
2022-11-03 19:49:00 +01:00
};
2022-11-03 20:48:36 +01:00
hunterSettings = lib.recursiveUpdate hunterDefaultSettings cfg.hunter.settings;
2022-11-03 19:49:00 +01:00
hunterConfigFile = builtins.toFile "hunter.yaml" (
2022-11-03 20:48:36 +01:00
builtins.toJSON hunterSettings
2022-11-03 19:49:00 +01:00
);
2023-01-22 00:05:10 +01:00
butcherDefaultSettings = {
redis = "redis://127.0.0.1:${toString cfg.redis.port}/";
profanity = profanityPath;
2023-01-22 00:05:10 +01:00
};
butcherSettings = lib.recursiveUpdate butcherDefaultSettings cfg.butcher.settings;
butcherConfigFile = builtins.toFile "butcher.yaml" (
builtins.toJSON butcherSettings
);
2022-11-10 02:47:46 +01:00
gathererDefaultSettings = {
redis = "redis://127.0.0.1:${toString cfg.redis.port}/";
2023-08-08 18:42:34 +02:00
database = "host=/var/run/postgresql user=caveman-gatherer dbname=caveman";
2022-11-10 02:47:46 +01:00
listen_port = 8000;
};
gathererSettings = lib.recursiveUpdate gathererDefaultSettings cfg.gatherer.settings;
gathererConfigFile = builtins.toFile "gatherer.yaml" (
builtins.toJSON gathererSettings
);
2022-11-17 00:09:46 +01:00
smokestackDefaultSettings = {
redis = "redis://127.0.0.1:${toString cfg.redis.port}/";
listen_port = 23;
};
smokestackSettings = lib.recursiveUpdate smokestackDefaultSettings cfg.smokestack.settings;
smokestackConfigFile = builtins.toFile "smokestack.yaml" (
builtins.toJSON smokestackSettings
);
2022-11-11 23:19:37 +01:00
limitNOFILE = 1000000;
2022-11-03 19:49:00 +01:00
in
{
options.services.caveman = with lib; {
redis.port = mkOption {
type = types.int;
default = 6379;
};
redis.maxmemory = mkOption {
type = types.int;
default = 1024 * 1024 * 1024;
};
redis.maxmemory-samples = mkOption {
type = types.int;
default = 8;
};
hunter.enable = mkEnableOption "caveman hunter";
hunter.settings = mkOption {
type = types.anything;
default = hunterDefaultSettings;
};
hunter.logLevel = mkOption {
type = types.enum [ "ERROR" "WARN" "INFO" "DEBUG" "TRACE" ];
default = "DEBUG";
};
2022-11-10 02:47:46 +01:00
2023-01-22 00:05:10 +01:00
butcher.enable = mkEnableOption "caveman butcher";
butcher.settings = mkOption {
type = types.anything;
default = butcherDefaultSettings;
};
butcher.logLevel = mkOption {
type = types.enum [ "ERROR" "WARN" "INFO" "DEBUG" "TRACE" ];
default = "DEBUG";
};
2022-11-10 02:47:46 +01:00
gatherer.enable = mkEnableOption "caveman gatherer";
gatherer.settings = mkOption {
type = types.anything;
default = gathererDefaultSettings;
};
gatherer.logLevel = mkOption {
type = types.enum [ "ERROR" "WARN" "INFO" "DEBUG" "TRACE" ];
default = "DEBUG";
};
2022-11-17 00:09:46 +01:00
smokestack.enable = mkEnableOption "caveman smokestack";
smokestack.settings = mkOption {
type = types.anything;
default = smokestackDefaultSettings;
};
smokestack.logLevel = mkOption {
type = types.enum [ "ERROR" "WARN" "INFO" "DEBUG" "TRACE" ];
default = "DEBUG";
};
2022-11-03 19:49:00 +01:00
};
config = {
2022-11-11 23:19:37 +01:00
systemd.extraConfig = ''
DefaultLimitNOFILE=${toString limitNOFILE}
'';
2022-12-26 03:44:42 +01:00
networking.firewall.allowedTCPPorts = [
hunterSettings.prometheus_port
];
systemd.tmpfiles.rules = [
"L ${profanityPath} - - - - ${./profanity.txt}"
];
# redis restore can be slow
systemd.services.redis-caveman.serviceConfig.TimeoutStartSec = "infinity";
2023-08-08 22:06:06 +02:00
services.redis.servers.caveman = {
2022-11-03 19:49:00 +01:00
enable = true;
port = cfg.redis.port;
settings = {
inherit (cfg.redis) maxmemory maxmemory-samples;
maxmemory-policy = "allkeys-lru";
};
};
2023-08-08 18:42:34 +02:00
services.postgresql = {
enable = true;
ensureDatabases = [ "caveman" ];
ensureUsers = [ {
2023-08-08 22:06:06 +02:00
name = "caveman-gatherer";
ensurePermissions = {
"DATABASE caveman" = "ALL PRIVILEGES";
};
} {
name = "caveman-hunter";
2023-08-08 18:42:34 +02:00
ensurePermissions = {
"DATABASE caveman" = "ALL PRIVILEGES";
};
} ];
};
2022-11-03 19:49:00 +01:00
systemd.services.caveman-hunter = lib.mkIf cfg.hunter.enable {
wantedBy = [ "multi-user.target" ];
requires = [ "redis-caveman.service" ];
2022-11-03 19:49:00 +01:00
after = [ "redis-caveman.service" "network-online.target" ];
environment.RUST_LOG = "caveman=${cfg.hunter.logLevel}";
2022-11-03 19:49:00 +01:00
serviceConfig = {
ExecStart = "${pkgs.caveman-hunter}/bin/caveman-hunter ${hunterConfigFile}";
Type = "notify";
WatchdogSec = 600;
2022-11-03 19:49:00 +01:00
Restart = "always";
RestartSec = 30;
2022-11-03 19:49:00 +01:00
DynamicUser = true;
User = "caveman-hunter";
ProtectSystem = "strict";
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
2023-01-22 00:05:10 +01:00
RestrictNamespaces = true;
RestrictRealtime = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
LimitNOFile = limitNOFILE;
LimitRSS = "4G:6G";
};
};
systemd.services.caveman-butcher = lib.mkIf cfg.butcher.enable {
wantedBy = [ "multi-user.target" ];
requires = [ "redis-caveman.service" ];
after = [ "redis-caveman.service" "network-online.target" ];
environment.RUST_LOG = "caveman=${cfg.butcher.logLevel}";
serviceConfig = {
ExecStart = "${pkgs.caveman-butcher}/bin/caveman-butcher ${butcherConfigFile}";
Type = "notify";
WatchdogSec = 600;
Restart = "always";
RestartSec = 30;
DynamicUser = true;
User = "caveman-butcher";
ProtectSystem = "strict";
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
2022-11-03 19:49:00 +01:00
RestrictNamespaces = true;
RestrictRealtime = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
2022-11-11 23:19:37 +01:00
LimitNOFile = limitNOFILE;
LimitRSS = "4G:6G";
2022-11-10 02:47:46 +01:00
};
};
systemd.services.caveman-gatherer = lib.mkIf cfg.gatherer.enable {
wantedBy = [ "multi-user.target" ];
requires = [ "redis-caveman.service" ];
after = [ "redis-caveman.service" "network-online.target" ];
environment.RUST_LOG = "caveman=${cfg.gatherer.logLevel}";
serviceConfig = {
ExecStart = "${pkgs.caveman-gatherer}/bin/caveman-gatherer ${gathererConfigFile}";
Type = "notify";
WatchdogSec = 90;
2022-11-10 02:47:46 +01:00
Restart = "always";
RestartSec = 1;
2022-11-10 02:47:46 +01:00
DynamicUser = true;
User = "caveman-gatherer";
ProtectSystem = "strict";
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
RestrictNamespaces = true;
RestrictRealtime = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
2022-11-11 23:19:37 +01:00
LimitNOFile = limitNOFILE;
2022-11-10 02:47:46 +01:00
WorkingDirectory = "${pkgs.caveman-gatherer}/share/caveman/gatherer";
LimitRSS = "512M:1G";
2022-11-03 19:49:00 +01:00
};
};
systemd.timers.caveman-gatherer-probe = lib.mkIf cfg.gatherer.enable {
wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = "minutely";
};
systemd.services.caveman-gatherer-probe = lib.mkIf cfg.gatherer.enable {
requires = [ "caveman-gatherer.service" ];
serviceConfig = {
Type = "oneshot";
User = "caveman-gatherer-probe";
DynamicUser = true;
ProtectSystem = "full";
};
path = with pkgs; [ wget ];
script = ''
wget -O /dev/null --user-agent=caveman-gatherer-probe 127.0.0.1:${toString gathererSettings.listen_port}/
'';
};
2022-11-17 00:09:46 +01:00
systemd.services.caveman-smokestack = lib.mkIf cfg.smokestack.enable {
wantedBy = [ "multi-user.target" ];
requires = [ "redis-caveman.service" ];
after = [ "redis-caveman.service" "network-online.target" ];
environment.RUST_LOG = "caveman=${cfg.smokestack.logLevel}";
serviceConfig = {
ExecStart = "${pkgs.caveman-smokestack}/bin/caveman-smokestack ${smokestackConfigFile}";
Type = "notify";
WatchdogSec = 10;
Restart = "always";
RestartSec = 10;
DynamicUser = true;
User = "caveman-smokestack";
ProtectSystem = "strict";
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
RestrictNamespaces = true;
RestrictRealtime = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
LimitNOFile = limitNOFILE;
LimitRSS = "64M:256M";
# Allow listening on ports <1024
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
};
};
2023-01-26 00:49:00 +01:00
systemd.services.blocklist-update = lib.mkIf cfg.hunter.enable {
after = [ "network.target" ];
2023-01-26 00:49:00 +01:00
path = with pkgs; [ coreutils wget ];
script = ''
T=$(mktemp blocklistXXXX)
wget -O $T https://raw.githubusercontent.com/gardenfence/blocklist/main/gardenfence.txt
chmod a+r $T
2023-01-26 00:49:00 +01:00
mv $T ${lib.escapeShellArg blocklistPath}
'';
serviceConfig = {
Type = "oneshot";
Restart = "on-failure";
RestartSec = 600;
};
};
systemd.timers.blocklist-update = lib.mkIf cfg.hunter.enable {
wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = "hourly";
};
2022-11-03 19:49:00 +01:00
};
}