Add OpenClaw AI Agent module
- Systemd service running OpenClaw gateway - Configurable via sops secrets - Runs on localhost:18789 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f013863986
commit
3a885463f0
4 changed files with 210 additions and 0 deletions
|
|
@ -86,4 +86,22 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# === OpenClaw ===
|
||||||
|
myModules.openclaw = {
|
||||||
|
enable = true;
|
||||||
|
port = 18789;
|
||||||
|
environmentFile = config.sops.templates."openclaw.env".path;
|
||||||
|
};
|
||||||
|
|
||||||
|
# OpenClaw secrets
|
||||||
|
sops.secrets.openclaw_discord_token = { };
|
||||||
|
sops.secrets.openclaw_openai_api_key = { };
|
||||||
|
|
||||||
|
sops.templates."openclaw.env" = {
|
||||||
|
content = ''
|
||||||
|
DISCORD_TOKEN=${config.sops.placeholder.openclaw_discord_token}
|
||||||
|
OPENAI_API_KEY=${config.sops.placeholder.openclaw_openai_api_key}
|
||||||
|
'';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,6 @@
|
||||||
./podman.nix
|
./podman.nix
|
||||||
./nginx.nix
|
./nginx.nix
|
||||||
./searxng.nix
|
./searxng.nix
|
||||||
|
./openclaw.nix
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
80
modules/openclaw-config.json
Normal file
80
modules/openclaw-config.json
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
{
|
||||||
|
"gateway": {
|
||||||
|
"port": 18789,
|
||||||
|
"bind": "loopback",
|
||||||
|
"trustedProxies": ["::1", "127.0.0.1", "10.88.0.0/16", "10.89.0.0/16"],
|
||||||
|
"auth": {
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"controlUi": {
|
||||||
|
"dangerouslyAllowHostHeaderOriginFallback": true,
|
||||||
|
"allowedOrigins": ["*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"channels": {
|
||||||
|
"whatsapp": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"discord": {
|
||||||
|
"enabled": true,
|
||||||
|
"groupPolicy": "open",
|
||||||
|
"dmPolicy": "open",
|
||||||
|
"allowFrom": ["*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"agents": {
|
||||||
|
"defaults": {
|
||||||
|
"model": {
|
||||||
|
"primary": "openai/gemini-3.1-pro-high"
|
||||||
|
},
|
||||||
|
"memorySearch": {
|
||||||
|
"provider": "openai",
|
||||||
|
"model": "nomic-embed-text",
|
||||||
|
"remote": {
|
||||||
|
"baseUrl": "http://localhost:11434/v1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tools": {
|
||||||
|
"exec": {
|
||||||
|
"security": "full",
|
||||||
|
"ask": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"skills": {
|
||||||
|
"entries": {}
|
||||||
|
},
|
||||||
|
"commands": {
|
||||||
|
"native": true,
|
||||||
|
"nativeSkills": "auto",
|
||||||
|
"restart": true,
|
||||||
|
"ownerDisplay": "raw"
|
||||||
|
},
|
||||||
|
"models": {
|
||||||
|
"mode": "merge",
|
||||||
|
"providers": {
|
||||||
|
"openai": {
|
||||||
|
"baseUrl": "http://localhost:8045/v1/chat/completions",
|
||||||
|
"apiKey": "${OPENAI_API_KEY}",
|
||||||
|
"api": "openai",
|
||||||
|
"models": [
|
||||||
|
{
|
||||||
|
"id": "gemini-3.1-pro-high",
|
||||||
|
"name": "Gemini 3.1 Pro High",
|
||||||
|
"reasoning": true,
|
||||||
|
"contextWindow": 1000000,
|
||||||
|
"maxTokens": 65536
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "claude-opus-4-6-thinking",
|
||||||
|
"name": "Claude Opus 4.6 Thinking",
|
||||||
|
"reasoning": true,
|
||||||
|
"contextWindow": 1000000,
|
||||||
|
"maxTokens": 65536
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
111
modules/openclaw.nix
Normal file
111
modules/openclaw.nix
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
# 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}"
|
||||||
|
];
|
||||||
|
|
||||||
|
ExecStartPre = [
|
||||||
|
"${pkgs.coreutils}/bin/mkdir -p ${configDir} ${dataDir} ${workspaceDir}"
|
||||||
|
"${pkgs.coreutils}/bin/cp -n /etc/openclaw/openclaw.json ${configDir}/ || true"
|
||||||
|
];
|
||||||
|
|
||||||
|
ExecStart = "${pkgs.nodejs_22}/bin/npx openclaw gateway start --port ${toString cfg.port}";
|
||||||
|
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = "10s";
|
||||||
|
|
||||||
|
# Security
|
||||||
|
PrivateTmp = true;
|
||||||
|
ProtectSystem = "strict";
|
||||||
|
ReadWritePaths = [ configDir dataDir workspaceDir ];
|
||||||
|
NoNewPrivileges = true;
|
||||||
|
};
|
||||||
|
} // lib.optionalAttrs (cfg.environmentFile != null) {
|
||||||
|
serviceConfig.EnvironmentFile = cfg.environmentFile;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue