{ config, lib, pkgs, ... }: let cfg = config.services.chainfire; in { options.services.chainfire = { enable = lib.mkEnableOption "chainfire service"; port = lib.mkOption { type = lib.types.port; default = 2379; description = "Port for chainfire API"; }; raftPort = lib.mkOption { type = lib.types.port; default = 2380; description = "Port for chainfire Raft protocol"; }; gossipPort = lib.mkOption { type = lib.types.port; default = 2381; description = "Port for chainfire gossip protocol"; }; dataDir = lib.mkOption { type = lib.types.path; default = "/var/lib/chainfire"; description = "Data directory for chainfire"; }; settings = lib.mkOption { type = lib.types.attrs; default = {}; description = "Additional configuration settings"; }; package = lib.mkOption { type = lib.types.package; default = pkgs.chainfire-server or (throw "chainfire-server package not found"); description = "Package to use for chainfire"; }; }; config = lib.mkIf cfg.enable { # Create system user users.users.chainfire = { isSystemUser = true; group = "chainfire"; description = "Chainfire service user"; home = cfg.dataDir; }; users.groups.chainfire = {}; # Create systemd service systemd.services.chainfire = { description = "Chainfire Distributed Configuration Service"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; serviceConfig = { Type = "simple"; User = "chainfire"; Group = "chainfire"; Restart = "on-failure"; RestartSec = "10s"; # State directory management StateDirectory = "chainfire"; StateDirectoryMode = "0750"; # Security hardening NoNewPrivileges = true; PrivateTmp = true; ProtectSystem = "strict"; ProtectHome = true; ReadWritePaths = [ cfg.dataDir ]; # Start command ExecStart = "${cfg.package}/bin/chainfire --api-addr 0.0.0.0:${toString cfg.port} --raft-addr 0.0.0.0:${toString cfg.raftPort} --gossip-addr 0.0.0.0:${toString cfg.gossipPort} --data-dir ${cfg.dataDir}"; }; }; }; }