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:
ashisgreat22 2026-03-17 20:55:15 +01:00
parent f013863986
commit 3a885463f0
4 changed files with 210 additions and 0 deletions

View file

@ -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}
'';
};
}

View file

@ -5,5 +5,6 @@
./podman.nix
./nginx.nix
./searxng.nix
./openclaw.nix
];
}

View 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
View 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;
};
};
}