This commit is contained in:
Harald Hoyer 2026-02-24 13:25:42 +01:00
parent 27343e49bd
commit 04150f10d4
32 changed files with 475 additions and 404 deletions

View file

@ -6,7 +6,7 @@
enable = true;
nextcloudUrl = "https://nc.hoyer.xyz";
botSecretFile = config.sops.secrets."nextcloud-claude-bot/secret".path;
allowedUsers = []; # Allow all registered users
allowedUsers = [ ]; # Allow all registered users
# Optional extra instructions (base prompt is hardcoded in bot.py)
# systemPrompt = "Additional custom instructions here";
};

View file

@ -13,10 +13,10 @@
# 1. Use the official package if available in nixpkgs
# 2. Package it yourself
# 3. Use a binary wrapper
# Option 1: If claude-code is in nixpkgs (check latest state)
# environment.systemPackages = [ pkgs.claude-code ];
# Option 2: Manual binary installation wrapper
nixpkgs.overlays = [
(final: prev: {
@ -30,22 +30,22 @@
# Create bot secret
# Generate with: openssl rand -hex 32
# Store in a file, e.g., /var/secrets/nextcloud-claude-bot
services.nextcloud-claude-bot = {
enable = true;
port = 8085;
host = "127.0.0.1";
nextcloudUrl = "https://cloud.example.com";
botSecretFile = "/var/secrets/nextcloud-claude-bot";
# Only allow specific users
allowedUsers = [ "harald" ];
# Claude settings
maxTokens = 4096;
timeout = 120;
# Optional system prompt
systemPrompt = ''
Du bist ein hilfreicher Assistent. Antworte auf Deutsch,
@ -62,7 +62,7 @@
# If you need external access (e.g., Nextcloud on different server):
services.nginx.virtualHosts."cloud.example.com" = {
# ... your existing Nextcloud config ...
locations."/_claude-bot/" = {
proxyPass = "http://127.0.0.1:8085/";
extraConfig = ''
@ -70,7 +70,7 @@
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Only allow from Nextcloud itself
allow 127.0.0.1;
deny all;

View file

@ -1,61 +1,72 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.nextcloud-claude-bot;
pythonEnv = pkgs.python3.withPackages (ps: with ps; [
fastapi
uvicorn
httpx
]);
pythonEnv = pkgs.python3.withPackages (
ps: with ps; [
fastapi
uvicorn
httpx
]
);
botModule = pkgs.runCommand "nextcloud-claude-bot-module" {} ''
botModule = pkgs.runCommand "nextcloud-claude-bot-module" { } ''
mkdir -p $out
cp ${./bot.py} $out/nextcloud_claude_bot.py
'';
in {
in
{
options.services.nextcloud-claude-bot = {
enable = mkEnableOption "Nextcloud Talk Claude Bot";
port = mkOption {
type = types.port;
default = 8085;
description = "Port for the webhook listener";
};
host = mkOption {
type = types.str;
default = "127.0.0.1";
description = "Host to bind to";
};
nextcloudUrl = mkOption {
type = types.str;
example = "https://cloud.example.com";
description = "Base URL of your Nextcloud instance";
};
botSecretFile = mkOption {
type = types.path;
description = "Path to file containing the bot secret (shared with Nextcloud)";
};
claudePath = mkOption {
type = types.path;
default = "${pkgs.claude-code}/bin/claude";
description = "Path to claude CLI binary";
};
allowedUsers = mkOption {
type = types.listOf types.str;
default = [];
example = [ "harald" "admin" ];
default = [ ];
example = [
"harald"
"admin"
];
description = "Nextcloud usernames allowed to talk to the bot (empty = all)";
};
contextMessages = mkOption {
type = types.int;
default = 6;
@ -67,7 +78,7 @@ in {
default = 120;
description = "Timeout in seconds for Claude CLI";
};
systemPrompt = mkOption {
type = types.nullOr types.str;
default = null;
@ -75,13 +86,13 @@ in {
description = "Optional system prompt for Claude";
};
};
config = mkIf cfg.enable {
systemd.services.nextcloud-claude-bot = {
description = "Nextcloud Talk Claude Bot";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
environment = {
HOME = "/var/lib/nextcloud-claude-bot";
BOT_HOST = cfg.host;
@ -133,8 +144,8 @@ in {
home = "/var/lib/nextcloud-claude-bot";
};
users.groups.claude-bot = {};
users.groups.claude-bot = { };
# Nginx reverse proxy config (optional, if you want external access)
# services.nginx.virtualHosts."cloud.example.com".locations."/claude-bot/" = {
# proxyPass = "http://${cfg.host}:${toString cfg.port}/";