Deployment
Production deployment patterns for Luminarys — Docker Compose, resource tuning, and operational best practices.
Quick reference
A complete two-node cluster demo with Docker Compose is available at github.com/LuminarysAI/mcp-demo-cluster.
Docker Compose — single node
FROM alpine:latest
ARG LUMINARYS_VERSION=0.1.0
ARG SKILLS_VERSION=0.1.0
RUN apk add --no-cache ca-certificates curl
WORKDIR /app
RUN curl -sL "https://github.com/LuminarysAI/luminarys/releases/download/v${LUMINARYS_VERSION}/luminarys-${LUMINARYS_VERSION}-linux-amd64.tar.gz" \
| tar xz -C /app luminarys lmsk && chmod +x /app/luminarys /app/lmsk
RUN mkdir -p /app/skills && \
curl -sL "https://github.com/LuminarysAI/skill-examples/releases/download/v${SKILLS_VERSION}/skill-examples-${SKILLS_VERSION}.tar.gz" \
| tar xz -C /app/skills
RUN mkdir -p /app/data
EXPOSE 8080
ENTRYPOINT ["/app/luminarys"]
CMD ["-config", "/app/config/host.yaml"]
services:
luminarys:
build: .
ports:
- "8080:8080"
volumes:
- ./config:/app/config:ro
- app-data:/app/data
restart: unless-stopped
volumes:
app-data:
Docker Compose — cluster
Uses the same Dockerfile from the single-node example for both master and slave. Add a separate Dockerfile.nats for the NATS server with file transfer relay:
FROM golang:1.25-alpine AS builder
RUN apk add --no-cache git
WORKDIR /build
RUN git clone --depth 1 https://github.com/LuminarysAI/nats-server.git . && \
CGO_ENABLED=0 go build -o /nats-server .
FROM alpine:latest
RUN apk add --no-cache ca-certificates curl
COPY --from=builder /nats-server /app/nats-server
EXPOSE 4222 4223 8222
ENTRYPOINT ["/app/nats-server"]
services:
nats:
build:
context: .
dockerfile: Dockerfile.nats
command: ["-c", "/app/config/nats-server.conf", "-relay", ":4223"]
volumes:
- ./config/nats-server.conf:/app/config/nats-server.conf:ro
restart: unless-stopped
master:
build: .
command: ["-config", "/app/config/master.yaml"]
ports:
- "8080:8080"
volumes:
- ./config:/app/config:ro
- master-data:/app/data
- shared-data:/data
depends_on: [nats]
restart: unless-stopped
slave-1:
build: .
command: ["-config", "/app/config/slave.yaml"]
volumes:
- ./config:/app/config:ro
- slave-data:/app/data
- shared-data:/data
depends_on: [nats, master]
restart: unless-stopped
volumes:
master-data:
slave-data:
shared-data:
File transfer between nodes requires the Luminarys NATS server fork with built-in relay. A standard NATS server is sufficient for skill invocations and node discovery.
A complete working example is available at github.com/LuminarysAI/mcp-demo-cluster.
Volume mounts
| Mount path | Purpose | Persistence |
|---|---|---|
/app/config | Host config and skill manifests | Read-only recommended |
/app/skills | Signed .skill packages | Read-only recommended |
/app/data | Database, module cache | Required — must persist |
/data | Shared data volume (for skills) | Depends on use case |
Memory tuning
Skill memory limit
The runtime.memory_limit_mb controls the maximum linear memory per skill:
runtime:
memory_limit_mb: 64
| Workload | Recommended limit |
|---|---|
| AssemblyScript / Rust only | 32 MB |
| Mixed (Go + AS/Rust) | 64 MB |
| Large Go skills with heavy processing | 128 MB |
| Unlimited (development only) | 0 |
Module cache
Enable runtime.cache_dir to cache compiled modules between restarts:
runtime:
cache_dir: "/app/data/cache"
This significantly speeds up startup — skills are compiled once and loaded from cache on subsequent starts.
Container memory
Set the container memory limit higher than the sum of all skill memory limits plus host overhead:
container_memory = (num_skills × memory_limit_mb) + 200 MB (host overhead)
Monitoring
Health endpoint
/health is always available without authentication:
curl http://localhost:8080/health
Use for Docker health checks, Kubernetes probes, or load balancer monitoring.
Endpoints
| Endpoint | Auth required | Description |
|---|---|---|
/health | No | Health check |
/mcp | Yes (if configured) | MCP Streamable HTTP |
/sse | Yes (if configured) | MCP Legacy SSE |
/skills | Yes (if configured) | REST skill listing |
/openapi.json | Yes (if configured) | OpenAPI specification |
Log configuration
Production
log:
level: "info"
stderr: false
skill_log: false
file:
enabled: true
path: "/app/data/logs/host.log"
max_size_mb: 100
max_backups: 3
Debug
log:
level: "debug"
stderr: true
skill_log: true
skill_log: true forwards output from skills that use the log_write ABI — useful for debugging skill behavior.
Production checklist
Authentication
-
http.auth.tokensis set with strong, unique tokens - NATS authentication token is configured (if clustering)
- Tokens loaded from environment variables, not hardcoded
Network
- TLS termination configured (reverse proxy or NATS TLS)
- Host not exposed directly to the internet without a reverse proxy
- NATS port not exposed publicly
Permissions
- File system permissions use specific directory paths
- HTTP/TCP allowlists are as narrow as possible
- Shell commands use specific allowlists
-
can_be_invoked_byis set to specific skill IDs where possible
Operations
- File logging enabled with rotation
- Health checks configured in Docker / Kubernetes
- Skill packages signed with
lmsk sign - Config validated with
luminarys -validate - Data volume is persistent and backed up
- Container memory limits set appropriately
- Module cache enabled (
runtime.cache_dir)