1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# Local deployment — Mac Mini, home server, or LAN machine.
# No TLS. Access at http://localhost:8080
#
# Usage:
# cp .env.example .env # fill in KERNEX_AUTH_TOKEN + CLAUDE_CREDENTIALS_PATH
# docker compose -f docker-compose.local.yml up -d
networks:
kx_net:
driver: bridge
volumes:
kx_data: # persistent job data, skills, and workflows
services:
kx:
image: ghcr.io/kernex-dev/kernex-agent:latest
pull_policy: always
networks:
- kx_net
ports:
- "8080:8080"
env_file: .env
# ── Provider selection ───────────────────────────────────────────────────────
# Recommended for local: "claude-code" uses your Claude subscription (no API key needed).
# To switch, set KERNEX_PROVIDER in .env and add the matching key:
# groq -> GROQ_API_KEY (fast, low-cost)
# deepseek -> DEEPSEEK_API_KEY (very low-cost)
# openai -> OPENAI_API_KEY
# anthropic -> ANTHROPIC_API_KEY
# gemini -> GEMINI_API_KEY
# openrouter -> OPENROUTER_API_KEY (routes to many models via one key)
# mistral -> MISTRAL_API_KEY
# fireworks -> FIREWORKS_API_KEY
# xai -> XAI_API_KEY
# ollama -> set KERNEX_BASE_URL=http://host.docker.internal:11434 (local, no key)
# Or use KERNEX_API_KEY as a unified key regardless of provider.
environment:
KERNEX_PROVIDER: ${KERNEX_PROVIDER:-claude-code}
KERNEX_MODEL: ${KERNEX_MODEL:-}
KERNEX_API_KEY: ${KERNEX_API_KEY:-}
KERNEX_BASE_URL: ${KERNEX_BASE_URL:-}
command:
- serve
- --host
- "0.0.0.0"
- --port
- "8080"
- --workers
- "${KX_WORKERS:-4}"
volumes:
# Persistent data directory — skills and workflows are bootstrapped here on first run
- kx_data:/home/kx/.kx
# Claude subscription credentials (required when KERNEX_PROVIDER=claude-code)
- type: bind
source: ${CLAUDE_CREDENTIALS_PATH:-/dev/null}
target: /home/kx/.claude/.credentials.json
read_only: true
# Optional: override bundled skills with your own directory
# - type: bind
# source: ./my-skills
# target: /home/kx/.kx/skills
# read_only: true
# Optional: override bundled workflows with your own directory
# - type: bind
# source: ./my-workflows
# target: /home/kx/.kx/workflows
# read_only: true
restart: unless-stopped
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
read_only: true
tmpfs:
- /tmp:noexec,nosuid,size=64m
mem_limit: 1g
memswap_limit: 1g
cpus: "2.0"
pids_limit: 512
ulimits:
nofile:
soft: 65536
hard: 65536
logging:
driver: json-file
options:
max-size: "20m"
max-file: "5"
healthcheck:
test:
interval: 30s
timeout: 5s
retries: 3
start_period: 15s