Self-hosted deploy control plane

luma Lightweight multi-server control plane

Write one YAML file for the domain, port, exposure, and region. Luma syncs Cloudflare DNS, Traefik HTTPS routes, and Nomad jobs while each server joins the cluster locally.

DNS Cloudflare sync TLS Traefik ACME Nodes region labels Rollback Nomad job versions
Step 1 Install Luma CLI (On your server/machine)
$ curl -fsSL https://raw.githubusercontent.com/LiuTianjie/luma/main/scripts/install-luma.sh | sh
Step 2 Install Luma Skill
Codex Claude Code Gemini
Install the skill from https://github.com/LiuTianjie/luma/tree/main/skills/luma-deployment-yaml
Or install manually via terminal
mkdir -p ~/.codex/skills && git clone --depth 1 https://github.com/LiuTianjie/luma.git /tmp/luma-repo && cp -R /tmp/luma-repo/skills/luma-deployment-yaml ~/.codex/skills/ && rm -rf /tmp/luma-repo
Deploy preview status.example.com
01 Manifest status.yaml domain: status.example.com
exposure: cn-edge
port: 80
02 Control Luma Control syncs DNS, TLS, routes, and services from the manifest
Cloudflare DNS status.example.com -> cn-edge
Traefik Edge Host rule + ACME certificate
Nomad Clients status:80 allocations x2
$ luma deploy status.yaml
ok dns     status.example.com -> cn-edge
ok tls     acme certificate requested
ok route   Host(status.example.com) -> status:80
ok nomad   status allocations x2
Domainstatus.example.com Exposurecn-edge Targetstatus:80
Domain in YAML domain is the service address
DNS in Cloudflare Records point to the selected exposure
HTTPS in Traefik Each Host gets its own certificate
Private images Registry auth stays out of YAML
Docker Compose Support Standard compose.yml with Luma sidecars for multi-service apps
Managed Storage Volumes Register storage classes; Luma mounts volume endpoints dynamically
Runtime Rollback Inspect versions and revert Nomad jobs from CLI or dashboard

Have these ready first.

01 Domain

Use real domains for the control API and public services, for example luma.example.com and status.example.com.

02 Cloudflare DNS

Put the DNS zone in Cloudflare and create a token that can read the zone and edit records.

03 Linux Manager

Start with one sudo-capable Linux server. A 2c2g manager is enough for testing if app resources are capped.

04 Tailscale optional

Skip Tailscale for a single public manager. Use it for home nodes, private joins, or tailscale-relay.

What each command updates.

Install CLI on Manager 01 / 06
Installing luma on the manager
Manager / Control CLI installed
Traefik Edge not created
CN Worker not joined
Global Worker not joined
Client not logged in
Domain no service yet deploy reads the manifest
DNS pending deploy writes the record
Certificate pending Traefik requests the certificate
Route and workload pending Traefik forwards to service:port
status.yaml
name: status
image: traefik/whoami:latest
region: cn
domain: status.example.com
port: 80
exposure: cn-edge
replicas: 2
resources:
  limits:
    cpus: "0.50"
    memory: 512M

Luma reads the manifest and updates the deploy path.

  • 01
    Read service entry

    Read domain, port, and exposure to get the address and target port.

  • 02
    Write DNS record

    Write the Cloudflare record so the domain points to the selected entry node.

  • 03
    Create HTTPS route

    Traefik reads the Host rule, requests a certificate, and creates the HTTPS route.

  • 04
    Pull private image if needed

    For private GHCR or custom registries, Luma uses saved registry credentials without writing tokens into the manifest.

  • 05
    Update service

    Update the Nomad job so status.example.com forwards to status:80.

  • 06
    Keep version history

    Nomad stores job versions so the dashboard and luma rollback can revert the running job.

  • 07
    Limit resources

    Use Nomad resource limits when apps and control services share a small server.

Multi-Service Compose & Declarative Storage

  • 01
    Standard docker-compose.yml

    Zero intrusion. Continue using standard Compose files to describe service dependencies and networks, keeping it useful for local development.

  • 02
    Luma Sidecar (luma.compose.yml)

    Isolate deployment-specific settings (like region, public domain exposure, and storage volumes mapping) into a separate sidecar file.

  • 03
    Managed Storage Classes

    Register NFS or local storage classes in Luma Control. Luma dynamically resolves mounting endpoints at deploy time based on node and region topology.

  • 04
    Data Loss Safeguards

    Strict data-loss warnings. Luma blocks deployments if a volume's backend storage path changes, demanding explicit adopted or initialize overrides.

luma.compose.yml
name: app-stack
compose: docker-compose.yml
region: cn

volumes:
  pg-data:
    storageClass: cn-nfs
    path: postgres/pg-data

services:
  app:
    exposure: cn-edge
    domain: app.example.com
    port: 3000
docker-compose.yml
version: '3.8'
services:
  app:
    image: company/app:latest
    volumes:
      - pg-data:/var/lib/pg/data
  postgres:
    image: postgres:15
    volumes:
      - pg-data:/var/lib/postgresql/data

volumes:
  pg-data: {}

Run the command for each machine role.

Install the CLI

Install luma on the manager first. Workers and clients install the same command later when needed.

curl -fsSL https://raw.githubusercontent.com/LiuTianjie/luma/main/scripts/install-luma.sh | sh
~/.local/bin/luma preflight

Initialize the control plane

Initialize the Nomad server on the first machine, then deploy Traefik, Luma Control, and the egress gateway as Nomad jobs.

luma bootstrap manager --domain luma.example.com

Join workload nodes

Each server runs join locally and gets a region label. Scheduling mainly follows region.

luma node join https://luma.example.com --token <join-token> --region global --name global-sg-1

Save private registry credentials

Use saved credentials when the image registry is private.

luma login https://luma.example.com --token <deploy-token>
printf '%s' "$GHCR_TOKEN" | luma registry login ghcr.io --username <user> --password-stdin

Deploy from a client

After login, the client submits the manifest. Luma prints DNS, certificate, route, and stack progress.

luma login https://luma.example.com --token <deploy-token>
luma deploy status.yaml

Documentation & Guides

Explore detailed specifications, architecture principles, and usage guides for every component.