{ config, lib, pkgs, ... }: let cfg = config.services.k8shost; in { options.services.k8shost = { enable = lib.mkEnableOption "k8shost service"; port = lib.mkOption { type = lib.types.port; default = 50087; description = "Port for k8shost gRPC API server"; }; httpPort = lib.mkOption { type = lib.types.port; default = 8085; description = "Port for k8shost HTTP REST API server"; }; iamAddr = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "IAM service endpoint address (http://host:port)"; example = "http://10.0.0.1:50080"; }; chainfireAddr = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "ChainFire endpoint address (http://host:port) for cluster coordination"; example = "http://10.0.0.1:2379"; }; prismnetAddr = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "PrismNET service endpoint address (http://host:port)"; example = "http://10.0.0.1:50081"; }; flaredbPdAddr = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "FlareDB Placement Driver address (host:port)"; example = "10.0.0.1:2479"; }; flaredbDirectAddr = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "FlareDB direct address (host:port)"; example = "10.0.0.1:50052"; }; fiberlbAddr = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "FiberLB service endpoint address (http://host:port)"; example = "http://10.0.0.1:50085"; }; flashdnsAddr = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "FlashDNS service endpoint address (http://host:port)"; example = "http://10.0.0.1:50084"; }; dataDir = lib.mkOption { type = lib.types.path; default = "/var/lib/k8shost"; description = "Data directory for k8shost"; }; settings = lib.mkOption { type = lib.types.attrs; default = {}; description = "Additional configuration settings"; }; package = lib.mkOption { type = lib.types.package; default = pkgs.k8shost-server or (throw "k8shost-server package not found"); description = "Package to use for k8shost"; }; }; config = lib.mkIf cfg.enable { # Create system user users.users.k8shost = { isSystemUser = true; group = "k8shost"; description = "K8shost Kubernetes Hosting Service user"; home = cfg.dataDir; }; users.groups.k8shost = {}; # Create systemd service systemd.services.k8shost = { description = "K8shost Kubernetes Hosting Service"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" "iam.service" "flaredb.service" "chainfire.service" "prismnet.service" ]; requires = [ "iam.service" "flaredb.service" "chainfire.service" "prismnet.service" ]; serviceConfig = { Type = "simple"; User = "k8shost"; Group = "k8shost"; Restart = "on-failure"; RestartSec = "10s"; # State directory management StateDirectory = "k8shost"; StateDirectoryMode = "0750"; # Security hardening NoNewPrivileges = true; PrivateTmp = true; ProtectSystem = "strict"; ProtectHome = true; ReadWritePaths = [ cfg.dataDir ]; # Environment variables for service endpoints Environment = [ "RUST_LOG=info" ]; # Start command ExecStart = lib.concatStringsSep " " ([ "${cfg.package}/bin/k8shost-server" "--addr 0.0.0.0:${toString cfg.port}" "--http-addr 127.0.0.1:${toString cfg.httpPort}" ] ++ lib.optional (cfg.iamAddr != null) "--iam-server-addr ${cfg.iamAddr}" ++ lib.optional (cfg.chainfireAddr != null) "--chainfire-endpoint ${cfg.chainfireAddr}" ++ lib.optional (cfg.prismnetAddr != null) "--prismnet-server-addr ${cfg.prismnetAddr}" ++ lib.optional (cfg.flaredbPdAddr != null) "--flaredb-pd-addr ${cfg.flaredbPdAddr}" ++ lib.optional (cfg.flaredbDirectAddr != null) "--flaredb-direct-addr ${cfg.flaredbDirectAddr}" ++ lib.optional (cfg.fiberlbAddr != null) "--fiberlb-server-addr ${cfg.fiberlbAddr}" ++ lib.optional (cfg.flashdnsAddr != null) "--flashdns-server-addr ${cfg.flashdnsAddr}"); }; }; }; }