{ config, lib, pkgs, ... }: let cfg = config.services.creditservice; defaultFlaredbPort = if (config.services ? flaredb) && (config.services.flaredb ? port) then config.services.flaredb.port else 2479; localDependencies = lib.optionals ((config.services ? flaredb) && config.services.flaredb.enable) [ "flaredb.service" ] ++ lib.optionals ((config.services ? chainfire) && config.services.chainfire.enable) [ "chainfire.service" ]; tomlFormat = pkgs.formats.toml { }; generatedConfig = { listen_addr = "0.0.0.0:${toString cfg.grpcPort}"; http_addr = "127.0.0.1:${toString cfg.httpPort}"; flaredb_endpoint = if cfg.flaredbAddr != null then cfg.flaredbAddr else "127.0.0.1:${toString defaultFlaredbPort}"; storage_backend = cfg.storageBackend; single_node = cfg.singleNode; iam_server_addr = if cfg.iamAddr != null then cfg.iamAddr else "127.0.0.1:50080"; } // lib.optionalAttrs (cfg.chainfireAddr != null) { chainfire_endpoint = "http://${cfg.chainfireAddr}"; }; configFile = tomlFormat.generate "creditservice.toml" generatedConfig; in { options.services.creditservice = { enable = lib.mkEnableOption "minimal auth-integrated creditservice reference"; grpcPort = lib.mkOption { type = lib.types.port; default = 3010; description = "Port for creditservice gRPC API"; }; httpPort = lib.mkOption { type = lib.types.port; default = 3011; description = "Port for creditservice HTTP REST API"; }; chainfireAddr = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "ChainFire endpoint address (host:port) for cluster coordination only"; example = "10.0.0.1:2379"; }; flaredbAddr = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "FlareDB endpoint address (host:port) for metadata/user data"; example = "10.0.0.1:2479"; }; iamAddr = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "IAM service endpoint address (host:port)"; example = "10.0.0.1:50080"; }; storageBackend = lib.mkOption { type = lib.types.enum [ "flaredb" "postgres" "sqlite" ]; default = "flaredb"; description = "Persistent storage backend for the minimal creditservice reference."; }; databaseUrl = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "SQL database URL for storage (required when storageBackend is postgres/sqlite)."; example = "postgres://creditservice:secret@10.0.0.10:5432/creditservice"; }; singleNode = lib.mkOption { type = lib.types.bool; default = false; description = "Enable single-node mode (required when storage backend is SQLite)"; }; package = lib.mkOption { type = lib.types.package; default = pkgs.creditservice-server or (throw "creditservice-server package not found"); description = "Package to use for creditservice"; }; }; config = lib.mkIf cfg.enable { users.users.creditservice = { isSystemUser = true; group = "creditservice"; description = "CreditService reference service user"; }; users.groups.creditservice = {}; systemd.services.creditservice = { description = "CreditService Minimal Auth-Integrated Credit Control Reference"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ] ++ localDependencies; wants = localDependencies; environment = lib.mkMerge [ (lib.mkIf (cfg.databaseUrl != null) { CREDITSERVICE_DATABASE_URL = cfg.databaseUrl; }) ]; serviceConfig = { Type = "simple"; User = "creditservice"; Group = "creditservice"; Restart = "on-failure"; RestartSec = "10s"; StateDirectory = "creditservice"; StateDirectoryMode = "0750"; NoNewPrivileges = true; PrivateTmp = true; ProtectSystem = "strict"; ProtectHome = true; ReadWritePaths = [ "/var/lib/creditservice" ]; ExecStart = "${cfg.package}/bin/creditservice-server --config ${configFile}"; }; }; }; }