Skip to main content

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

Dockerfile
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"]
docker-compose.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:

Dockerfile.nats
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"]
docker-compose.yaml
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:
note

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 pathPurposePersistence
/app/configHost config and skill manifestsRead-only recommended
/app/skillsSigned .skill packagesRead-only recommended
/app/dataDatabase, module cacheRequired — must persist
/dataShared 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
WorkloadRecommended limit
AssemblyScript / Rust only32 MB
Mixed (Go + AS/Rust)64 MB
Large Go skills with heavy processing128 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

EndpointAuth requiredDescription
/healthNoHealth check
/mcpYes (if configured)MCP Streamable HTTP
/sseYes (if configured)MCP Legacy SSE
/skillsYes (if configured)REST skill listing
/openapi.jsonYes (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.tokens is 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_by is 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)