{ pkgs, config, lib, ... }: let cfg = config.services.signal-irc-bridge; commonServiceOptions = { User = "signal-irc"; Group = "signal-irc"; StateDirectory = "signal-cli"; RuntimeDirectory = "signal-cli"; PrivateDevices = true; PrivateTmp = true; ProtectControlGroups = true; ProtectKernelTunables = true; RestrictSUIDSGID = true; ProtectSystem = "strict"; ProtectKernelLogs = true; ProtectProc = "invisible"; PrivateUsers = true; ProtectHome = true; UMask = "0027"; RuntimeDirectoryMode = "0750"; StateDirectoryMode = "0750"; }; in { options = { services.signal-irc-bridge = { enable = lib.mkEnableOption "signal-irc bridge"; package = lib.mkOption { type = lib.types.package; default = pkgs.signal-irc-bridge; }; configFile = lib.mkOption { type = lib.types.path; description = "Path to the toml config file"; }; }; }; config = { nixpkgs.overlays = [ (import ./overlay.nix) ]; systemd.services = lib.mkIf cfg.enable { signal-irc-bridge = { script = '' CONFIG_PATH=$CREDENTIALS_DIRECTORY/config ${lib.getExe cfg.package} ''; unitConfig = { BindsTo = [ "signal-irc-bridge-signal-cli.service" ]; After = [ "signal-irc-bridge-signal-cli.service" ]; }; serviceConfig = commonServiceOptions // { Restart = "always"; RestartSec = "5s"; LoadCredential = [ "config:${cfg.configFile}" ]; # Change state/runtime dirs because it deletes the socket else StateDirectory = "signal-irc"; RuntimeDirectory = "signal-irc"; }; }; signal-irc-bridge-signal-cli = { serviceConfig = commonServiceOptions // { ExecStart = "${lib.getExe pkgs.signal-cli} --config \"\${STATE_DIRECTORY}\"/signal-cli-config/ daemon --socket \"\${RUNTIME_DIRECTORY}\"/socket --receive-mode=manual"; Restart = "always"; RestartSec = "5s"; }; }; }; environment.systemPackages = lib.mkIf cfg.enable [ pkgs.signal-cli ]; users = lib.mkIf cfg.enable { users.signal-irc = { isSystemUser = true; group = "signal-irc"; }; groups.signal-irc = { }; }; }; }