{ config, pkgs, lib, ... }: with lib; let cfg = config.services.naxos.api; in { options.services.naxos.api = { enable = mkEnableOption "NaxOS Management Daemon & REST/WebSocket API Service"; port = mkOption { type = types.port; default = 8088; description = "Internal daemon listen port."; }; host = mkOption { type = types.str; default = "127.0.0.1"; description = "Internal daemon bind host."; }; dataDir = mkOption { type = types.str; default = "/var/lib/naxos"; description = "Persistent state directory for NaxOS daemon."; }; configRepoDir = mkOption { type = types.str; default = "/etc/naxos/repo"; description = "Directory of the local GitOps configuration repository."; }; }; config = mkIf cfg.enable { systemd.services.naxos-api = { description = "NaxOS Declarative Management Daemon"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" "zfs.target" ]; path = with pkgs; [ zfs git nix systemd smartmontools util-linux shadow samba curl bash ]; environment = { NODE_ENV = "production"; PORT = toString cfg.port; HOST = cfg.host; NAXOS_DATA_DIR = cfg.dataDir; NAXOS_CONFIG_REPO = cfg.configRepoDir; SYSTEM_PROFILE = "/nix/var/nix/profiles/system"; }; serviceConfig = { Type = "simple"; ExecStart = "${pkgs.nodejs}/bin/node /opt/naxos/api/dist/server.js"; WorkingDirectory = cfg.dataDir; Restart = "always"; RestartSec = "3s"; StateDirectory = "naxos"; RuntimeDirectory = "naxos"; # Sandboxing / Security hardening ProtectSystem = "strict"; ProtectHome = "read-only"; ReadWritePaths = [ cfg.dataDir cfg.configRepoDir "/var/log" "/etc/naxos" "/nix/var/nix/profiles" ]; AmbientCapabilities = [ "CAP_SYS_ADMIN" ]; # For ZFS operations & systemd manipulation }; }; systemd.tmpfiles.rules = [ "d ${cfg.dataDir} 0750 root root -" "d ${cfg.configRepoDir} 0750 root root -" "d /etc/naxos 0755 root root -" ]; }; }