# OpenClaw Module # Provides: AI Agent with Discord integration # # Usage: # myModules.openclaw = { # enable = true; # port = 18789; # }; { config, lib, pkgs, ... }: let cfg = config.myModules.openclaw; configDir = "/var/lib/openclaw/config"; dataDir = "/var/lib/openclaw/data"; workspaceDir = "/var/lib/openclaw/workspace"; in { options.myModules.openclaw = { enable = lib.mkEnableOption "OpenClaw AI Agent"; port = lib.mkOption { type = lib.types.port; default = 18789; description = "Gateway port for OpenClaw"; }; environmentFile = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; description = "Path to environment file with API keys"; }; }; config = lib.mkIf cfg.enable { # Create user for openclaw users.users.openclaw = { isSystemUser = true; group = "openclaw"; home = "/var/lib/openclaw"; createHome = true; }; users.groups.openclaw = { }; # Create directories systemd.tmpfiles.settings."10-openclaw" = { "${configDir}".d = { user = "openclaw"; group = "openclaw"; mode = "0700"; }; "${dataDir}".d = { user = "openclaw"; group = "openclaw"; mode = "0700"; }; "${workspaceDir}".d = { user = "openclaw"; group = "openclaw"; mode = "0700"; }; }; # Copy config file environment.etc."openclaw/openclaw.json".source = ./openclaw-config.json; # Systemd service systemd.services.openclaw = { description = "OpenClaw AI Agent"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "simple"; User = "openclaw"; Group = "openclaw"; WorkingDirectory = dataDir; Environment = [ "NODE_ENV=production" "OPENCLAW_CONFIG_DIR=${configDir}" "OPENCLAW_DATA_DIR=${dataDir}" "OPENCLAW_WORKSPACE_DIR=${workspaceDir}" "PATH=${pkgs.nodejs_22}/bin:${pkgs.git}/bin:${pkgs.bash}/bin:${pkgs.coreutils}/bin" ]; EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile; ExecStartPre = [ "${pkgs.coreutils}/bin/mkdir -p ${configDir} ${dataDir} ${workspaceDir}" "${pkgs.bash}/bin/bash -c 'cp -n /etc/openclaw/openclaw.json ${configDir}/ || true'" ]; ExecStart = "${pkgs.nodejs_22}/bin/npx openclaw gateway --port ${toString cfg.port} --allow-unconfigured"; Restart = "on-failure"; RestartSec = "10s"; # Security PrivateTmp = true; ProtectSystem = "strict"; ReadWritePaths = [ "/var/lib/openclaw" configDir dataDir workspaceDir ]; NoNewPrivileges = true; }; }; }; }