Luma CLI#
完整的当前命令和选项清单见自动生成的 CLI 参考。本文介绍工作流程和运维语义。
Luma CLI 用于安装节点、连接服务提供方、渲染 Nomad job 和部署服务。底层编排器是 HashiCorp Nomad,部署单位是 Nomad job。
默认流程以控制面为入口、Nomad 为编排后端:
luma deploy service.yaml -> Luma Control API -> render jobspec on manager -> sync DNS -> Nomad API (/v1/jobs) -> docker driver
Luma Control 负责认证和编排,将清单渲染为 Nomad jobspec,直接提交到 Nomad HTTP API。通过 luma status、控制台或 Manager 上的 nomad job status 检查部署。
安装#
CI runner 应安装已发布的软件包,而不是运行 Shell 安装程序:
python -m pip install "luma-infra==0.1.365"
软件包名称是 luma-infra,安装后的命令仍为 luma。
交互式机器使用安装程序:
curl -fsSL https://raw.githubusercontent.com/LiuTianjie/luma/main/scripts/install-luma.sh | sh
~/.local/bin/luma preflight
安装程序使用 GitHub 归档,而非 git clone。它安装到 ~/.local/share/luma/venv,写入 ~/.local/bin/luma,并在需要时将 ~/.local/bin 加入 Shell 配置。可立即使用 ~/.local/bin/luma;要使用简写 luma,请打开新 Shell 或执行 exec $SHELL -l。
安装固定版本:
curl -fsSL https://raw.githubusercontent.com/LiuTianjie/luma/main/scripts/install-luma.sh | LUMA_INSTALL_REF=v0.1.365 sh
从开发检出目录运行:
./scripts/install-luma.sh
. .venv/bin/activate
卸载本地 CLI:
curl -fsSL https://raw.githubusercontent.com/LiuTianjie/luma/main/scripts/uninstall-luma.sh | sh
默认保留 ~/.luma.config.json 和 ~/.config/luma,便于重装后继续使用本地配置和登录 context。如需一并删除:
curl -fsSL https://raw.githubusercontent.com/LiuTianjie/luma/main/scripts/uninstall-luma.sh | sh -s -- --purge
这只卸载本地 CLI,不删除 Docker、Nomad、Traefik、Luma Control、已部署服务或服务器端 /opt/luma 状态。
CI 使用#
CI 可将 Luma 作为无状态控制面客户端使用,无需 SSH、Docker、Cloudflare、Nomad 或 ~/.config/luma 中的文件。
PR 校验:
python -m pip install "luma-infra==0.1.365"
export LUMA_CONTROL_URL="https://luma.example.com"
export LUMA_DEPLOY_TOKEN="$CI_LUMA_MANAGEMENT_TOKEN"
luma validate deploy/app.yaml --format json
luma deploy deploy/app.yaml --dry-run --format json
主分支或发布部署:
python -m pip install "luma-infra==0.1.365"
export LUMA_CONTROL_URL="https://luma.example.com"
export LUMA_DEPLOY_TOKEN="$CI_LUMA_MANAGEMENT_TOKEN"
luma status --format json
luma deploy deploy/app.yaml --format ndjson --timeout 3000
控制上下文优先级依次为 CLI 参数、环境变量、本地登录 context。CI 常用变量:
LUMA_CONTROL_URLLUMA_DEPLOY_TOKENLUMA_INSECURE=true|falseLUMA_RESOLVE_IPLUMA_CONTROL_CONTEXT(选择已保存的集群,不改变当前 context)
LUMA_RESOLVE_IP 保留 Host 请求头中的 Control 主机名,并要求启用不安全 TLS 模式。
支持共享 Control 选项的命令可通过 --control-context CLUSTER 为本次调用选择已保存 context。显式参数覆盖环境变量,环境变量覆盖所选 context。显式 Control URL 与保存端点不同时,不会继承原令牌、TLS 或 IP 覆盖设置,需要提供目标端点凭据。doctor、service restart 和 service remove 也遵循此规则,无需预先登录即可在 CI 中运行。
交互登录可隐藏输入令牌,或从标准输入读取:
luma login https://luma.example.com
printf '%s' "$LUMA_DEPLOY_TOKEN" | luma login https://luma.example.com --token-stdin
luma context list --format json
luma doctor --control-context staging --format json
login 先接受 --token 或 --token-stdin,再回退到 LUMA_DEPLOY_TOKEN,最后才是隐藏的交互提示。非交互登录未提供令牌会失败并给出设置提示。优先用环境变量或标准输入,避免令牌出现在进程参数中。
声明支持 --format 的命令可输出 text、json、ndjson;除响应内容外还应检查退出状态。Doctor 返回 healthy 布尔值和各项检查,不健康时非零退出。流式服务日志支持文本和 NDJSON,快照支持 JSON。
Git 提供方凭据#
仓库导入可使用保存的 GitHub/Gitea 凭据,无需在单次仓库 URL 中携带令牌。令牌只写不读,仅注入 Builder 获得短期授权的克隆任务。
printf '%s' "$GITHUB_TOKEN" | luma git-provider set github personal --username octo --token-stdin
printf '%s' "$GITEA_TOKEN" | luma git-provider set gitea lin \
--base-url https://gcode.example.com \
--username lin \
--token-stdin
列出账户并查询仓库:
luma git-provider list
luma git-provider repos gitea:lin
luma git-provider refs gitea:lin acme/app
导入时使用所选提供方账户:
luma import --provider-id gitea:lin --repository acme/app --build-node builder --env .env
公共 GitHub 仓库的位置参数也可写成 owner/repo,Luma 展开为 https://github.com/owner/repo.git。Gitea/自托管 Git 请使用完整 URL 或 --provider-id ... --repository ...。
配置#
luma.yaml 是项目配置的唯一来源:
project: example
providers:
dns:
type: cloudflare
zone: example.com
zoneId: ""
apiTokenEnv: CLOUDFLARE_API_TOKEN
edgeTarget: 203.0.113.10
nodes:
manager-1:
host: manager-1
publicIp: 203.0.113.10
region: cn
roles:
- nomad-server
- edge
- egress
defaults:
exposure: cn-edge
registry: ghcr.io/liutianjie
stackRoot: stacks
routesRoot: routes
egressNetwork: egress
entrypoint: websecure
certResolver: letsencrypt
engine: nomad
密钥不进入 Git。正常使用时直接运行所需命令:
luma bootstrap manager --domain luma.example.com
本地缺少必需值时,Luma 会先提示填写,以 0600 权限保存到 ~/.luma.config.json 后继续。工作节点在以下操作时也会如此:
luma node join https://luma.example.com --token <node-join-token> --region global --name global-sg-1
可通过 luma configure --role manager|worker 预先编辑本地密钥,luma configure --show 仅列出已配置键名而不显示值。Luma 自动加载 .env 和 ~/.luma.config.json;--env-file <path> 指定其他本地环境文件,--no-env 禁用本地密钥加载。Shell 已导出的变量优先。Manager 初始化与更新会把必需的 Cloudflare 值保存在 Control 状态(旧数据导入后为 control.sqlite3),客户端无需这些密钥。存在 CLOUDFLARE_API_TOKEN 但缺少 providers.dns 时,初始化和 luma update manager 根据 Control 域名推导 Cloudflare zone,在安装 /opt/luma/luma.yaml 前写入配置。没有边缘 DNS 目标时,交互初始化询问 LUMA_DNS_EDGE_TARGET;非交互更新使用已配置边缘节点公网 IP 或已有的该变量。
命令#
初始化配置:
luma init
检查本地依赖与 .env:
luma preflight
从任意已登录客户端查看控制面与集群状态:
luma status
luma status 输出 DNS 就绪状态、编排器 Nomad 及其 server leader,以及 Control 状态中已注册、role=client 的 Luma 节点。
保存私有仓库镜像拉取凭据:
printf '%s' "$GHCR_TOKEN" | luma registry login ghcr.io --username <user> --password-stdin
luma registry list
luma registry remove ghcr.io
部署集群内镜像仓库,供源码构建使用:
luma registry serve --node build-1
luma registry serve 在有 docker-build 能力的节点部署 registry:2,并为所有就绪的非 Manager Linux 节点配置 insecure-registries,使其能通过 Tailscale 拉取构建镜像。BuildKit 和目标节点都使用可达的 Builder Tailscale 端点 <build-node-tailscale-host>:5000;不要再配置已移除的 localhost:5000 推送端点。可选参数:--port 默认 5000,--storage-class 为可选遗留 class(省略则用节点本地 Docker volume),--image 默认 registry:2,--name 默认 luma-registry,--timeout 默认 1800。完整源码到镜像流程见使用手册的仓库导入章节。
同一控制面也提供网页控制台:
https://<control-domain>/dashboard/
在可信浏览器输入管理令牌,查看就绪状态、节点、服务和推导的流量路径。
Luma 提供两类用户令牌:
- 管理令牌:供可信 CLI 客户端和控制台使用,适用于
luma login、控制台登录、部署、存储、密钥、镜像仓库及节点操作。 - 节点加入令牌:供加入集群或刷新本地 agent 的服务器使用,适用于
luma node join,以及无 agent 元数据的旧节点上的luma update --control-url ... --token ...。
每个节点的 agent 凭据由内部自动安装。用户应通过 luma node status 检查状态,无需复制或管理 agent 凭据。
仅列出本地 luma.yaml 中的节点:
luma node list
直接在 Manager 服务器执行初始化:
luma bootstrap manager --domain luma.example.com
对于 single-node,会安装 Docker,按配置连接 Tailscale,安装并启动 Nomad server,应用节点 meta,以 Nomad job 部署 Traefik 和 Luma Control,配置防火墙及出网。Manager 需要代理拉取 Control 镜像时,先设置 EGRESS_SUBSCRIPTION_URL。中国大陆 Manager 使用默认 GHCR 镜像时不应跳过出网。
命令实时输出进度:
[start] Install Nomad server
[ok] Nomad server ready
[start] Deploy Luma Control
[fail] Deploy Luma Control
Fix: Re-run luma bootstrap manager after fixing the error
只有可直连 Control 仓库,或 LUMA_CONTROL_IMAGE / defaults.images.lumaControl 指向可拉取仓库时,才跳过出网:
luma bootstrap manager --domain luma.example.com --skip-egress
从任意客户端登录:
luma login https://luma.example.com --token <management-token>
luma context list
luma context use <cluster-id>
在每台新增服务器上执行加入:
luma region create batch-a --egress proxy
luma region list
luma node join https://luma.example.com --token <node-join-token> --region cn --name cn-worker-1
luma node join https://luma.example.com --token <node-join-token> --region global --name global-sg-1
luma node join https://luma.example.com --token <node-join-token> --region home --name home-mac-mini
luma node join https://luma.example.com --token <node-join-token> --region batch-a --name batch-a-01
--region 指定调度池,内置 cn、global、home。使用 luma region create <name> --egress proxy|direct(节点页也可操作)创建更多区域,再将机器加入该区域。自定义区域默认仅内部工作负载(exposure: none)。--egress proxy 与 cn/home 一样,在加入和拉取镜像时使用 Manager 网关。
--name 是 luma status 和服务清单使用的 Luma 节点名,写入 Nomad client 的 meta.luma_node_name,用于固定调度。Nomad 节点身份是稳定 UUID,同名重新加入不会使固定服务失效。--engine nomad 可显式指定默认的 Nomad client 流程。
升级旧节点后刷新已加入的 agent:
luma update --control-url https://luma.example.com --token <node-join-token>
更新所有已注册且 agent 就绪的节点:
luma update fleet
luma update fleet --install-ref v0.1.365 --timeout 900
luma update fleet --include-manager
--install-ref 接受版本标签、分支或完整 40 字符 Git commit。协调候选版本发布时应使用完整 commit,避免分支移动导致 Manager 与节点 agent 解析到不同版本。
批量更新通过节点 agent 执行:更新就绪的非 Manager 节点 CLI,再刷新本地 agent 服务和 Tailscale 看门狗。默认跳过 Nomad server(Manager),请在 Manager 主机上单独运行 luma update manager。--include-manager 用于显式修复,常规批量更新应避免影响活动控制面。Agent 太旧、未声明 luma-update 时会跳过;先在节点执行一次 luma update,后续即可加入批量更新。
Manager 的 /opt/luma/control 仅 root 可访问。运维账户无免密 sudo 时,应提权执行应急 CLI 更新(如 sudo ~/.local/bin/luma update manager),或通过 luma configure --role manager 配置 LUMA_SUDO_PASSWORD。无法访问时,luma update 不应回退到用户的客户端 context。旧版本可能走错路径,并因客户端令牌过期返回 401;修改凭据前应先恢复对 Manager 状态的访问。
推荐通过控制台更新中心更新 Manager。它先把所选 Control 镜像镜像化到内部 Registry,再启动持久化的 Manager 操作。直接 CLI 更新会自行拉取镜像;无法访问 GHCR 时,通过 LUMA_CONTROL_IMAGE 指定可拉取的内部镜像,或使用控制台流程。
恢复公网 IPv4 已改变的 Manager:先在 Manager 主机上预览,再移除 --dry-run 执行:
luma manager ip-change \
--old 8.147.65.253 \
--new 8.145.62.128 \
--domain luma.itool.tech \
--dry-run
luma manager ip-change \
--old 8.147.65.253 \
--new 8.145.62.128 \
--domain luma.itool.tech
命令通过 HTTPS 验证新地址,并保留 Control 主机名用于 SNI 和证书检查。只修改 Manager 节点 publicIp、providers.dns.edgeTarget,以及内容精确等于旧地址的 Cloudflare A 记录。备份 luma.yaml,复用运行中 luma-control Nomad job 的镜像,协调控制面,不重装 CLI 或重新部署用户应用。不会全局替换 Control 状态,历史事件内容不变。操作幂等,可重新执行以完成 Cloudflare 部分失败遗留的记录。
排空本地 Nomad client,并可选从控制面注销节点:
luma node exit --endpoint https://luma.example.com --token <management-or-node-join-token> --name home-mac-mini
从任意已登录客户端移除节点:
luma node remove home-mac-mini
控制面删除 Luma 注册记录,再在 Manager 上排空匹配的 Nomad client。匹配依据是保存的 Nomad 节点 ID、meta.luma_node_name 或节点名。命令拒绝移除 Nomad server(Manager)。
连接 Cloudflare 并写入 providers.dns.zoneId:
luma cloudflare connect --zone example.com
修复或刷新出网网关:
luma egress setup
luma egress refresh
安装/登录 Tailscale:
luma tailscale connect
Manager 和已加入节点在初始化/更新时安装轻量 Tailscale 看门狗。Manager 检查 Tailscale 对端和 Nomad gossip/RPC TCP 可达性;节点检查 Manager Tailscale 与 Nomad server 端口。连续失败后重启本地 Tailscale,旨在恢复 tailnet TCP 卡顿,而不重启 Docker、Traefik、Nomad agent 或应用 job。
交互生成服务清单:
luma service new
校验并渲染:
luma validate examples/public-cn-service.yaml
luma render examples/public-cn-service.yaml
luma render examples/public-cn-service.yaml --engine nomad
luma render 在本地渲染;--engine nomad 强制使用 Nomad jobspec 渲染器,这也是当前集群默认值。
通过控制面部署:
luma deploy examples/public-cn-service.yaml
回滚或查看已部署服务版本:
luma history public-cn-service
luma rollback public-cn-service
luma rollback public-cn-service --to-version 3
luma history 列出 Nomad job 历史版本(GET /v1/job/<id>/versions)。luma rollback 回退上一版本,或 --to-version N 指定的版本(POST /v1/job/<id>/revert)。控制台 应用 → 版本提供相同操作。Jobspec 也渲染 update { auto_revert = true },新版本健康检查失败时自动回滚。
回滚仅改变运行中的 Nomad job,不改写 Git、不更新 Control 已保存清单、不回滚数据库或恢复卷。生产回滚应使用不可变镜像标签或 digest,避免 latest。
搜索保留的 Control 构建与部署尝试:
luma service history public-cn-service --kind deployment --status failed --limit 50 --format json
luma service history --source dashboard --since 2026-09-01T00:00:00+08:00 --format json
luma service history --id RECORD_ID --kind deployment --limit 50 --format json
luma build list --app public-cn-service --status failed --limit 50 --format json
luma build logs BUILD_ID --limit 50 --format json
获得构建 ID 后,CLI 遇到暂时断连会继续等待同一任务,直到原有 --timeout 截止;停止等待不会取消服务端构建。普通查询和只读 workflow 校验最多尝试 3 次,认证、证书及响应格式错误立即报错;构建和部署提交不会自动重发。新版 Control 返回日志位置后,等待过程只拉取新增事件,旧版 Control 仍使用完整分页。
service history [NAME] 搜索构建及部署记录。可按类型(build/deployment)、来源(build/cli/dashboard)、状态、应用、--since 和 --until 筛选。时间接受 Unix 秒或带时区的 RFC3339。默认每页 50,最多 100;保持其他筛选不变,把返回的 nextCursor 作为 --cursor。JSON 包含 limit、nextCursor、hasMore,文本模式将续页信息写到 stderr。分页读取更多已保留记录,不增加保留期。
service history --id ID --kind KIND 分页读取单条记录步骤,不能与列表筛选组合。build logs ID 也按从旧到新分页。这些是构建/部署执行事件,应用 stdout/stderr 属于 service logs。luma history NAME 仍是用于回滚的 Nomad job 版本列表,与 Control 尝试历史分开。旧状态导入无法恢复迁移前已裁剪记录。保留和备份边界见控制面存储。
操作前先检查服务:
luma service list --region cn --format json
luma service inspect public-cn-service --format json
luma service events public-cn-service --format json
luma service logs public-cn-service --tail 100
luma service logs public-cn-service --allocation ALLOCATION_ID --previous
luma service logs public-cn-service --follow --format ndjson
list --stack NAME 限定到一个 stack。日志限定所选部署,对比副本可用 --allocation。--tail 接受 1–500 行总预算,由所选来源共享。文本输出用 [allocation/task/stream] 标记来源,[partial] 表示未完片段,[continued] 表示续片,即使其他来源交错也保留标记。这是诊断视图,不是字节精确导出;JSON/NDJSON 可保留来源、游标和片段元数据。运行时仍保留旧实例时,--previous 可读取它。Follow 模式在正常 EOF、传输失败或临时 HTTP 失败后,从最近行或心跳字节游标恢复;重连从 0.5 到 15 秒指数退避,最多连续 8 次无进展重连。Ctrl-C 停止。认证、游标无效和协议错误立即失败;旧 Control 不提供恢复游标时直接失败,不会重放快照。没有 --since 参数,因为应用时间戳不保证可解析,CLI 不声称具备服务端时间筛选。
不重新部署,直接重启运行服务:
luma service restart public-cn-service
luma service restart my-stack --service web --mode task
--mode recreate 重新调度 allocation,--mode task 原地重启任务。省略模式时,整个 stack 默认 recreate,通过 --service 指定单任务时默认 task。运行时操作后,Control 协调已保存部署的路由/DNS,并探测公共 HTTP 服务;Compose 协调全部暴露服务。拒绝重启系统 stack traefik、egress、luma-control。详见运维操作。
删除已部署服务:
luma service remove public-cn-service
luma service remove public-cn-service --dry-run
检查认证、远程 Control 状态、DNS 配置就绪、节点 agent 和 Nomad 健康(不审计本地 Docker/操作系统环境):
luma doctor
luma doctor --deep
--deep 额外评估 Control 状态中的远程节点诊断(Docker 镜像/代理和 Nomad 配置)。DNS 就绪只表示配置存在,不能证明公网解析或应用可用。
服务清单#
name: app
image: ghcr.io/me/app:latest
region: cn
exposure: cn-edge
domain: app.example.com
port: 3000
replicas: 2
必填字段:
nameimageregion:cn、global、home或luma region create创建的自定义区域。exposure:cn-edge、tailscale-relay、tcp-relay、cloudflare-tunnel、external-edge或none。
公共服务还需要:
domainport
可选字段:
engine:nomad,选择服务编排后端,省略则继承集群默认值。node:luma node join --name的节点名,将服务固定到一个节点;渲染为${node.unique.name}(或meta.luma_node_name)约束,并保留区域约束。env/environmentcommandconstraintslabelsnetworksproxy:为true时运行流量走出网代理;Luma 附加代理和默认代理环境变量,调度仍按region。resources:渲染为 Nomad task 的资源块。CPU 使用reservations.cpus(默认 100 MHz)作为弹性调度份额;旧limits.cpus仅警告并忽略,不作为硬上限。内存预留映射到memory,限制映射到memory_max;只设限制时预留 min(256 MiB, limit)。注册此类 job 前,Control 自动启用 Nomad 内存超卖,使声明限制成为实际容器硬上限。stackPathroutePathdns.targetdns.typedns.proxiedpublishPortrelay.host:可选 tailscale-relay 上游覆盖,通常省略。relay.url:可选完整 tailscale-relay 上游 URL 覆盖,通常省略。tcp-relay根据publishPort或port自动推导 Traefik TCP 入口。tunnel.tokenEnv
需要 Luma 出网代理的工作服务示例:
name: ai-worker
image: ghcr.io/acme/ai-worker:1.0.0
region: cn
exposure: none
proxy: true
小型 Manager 上限制资源的服务示例:
name: api
image: ghcr.io/acme/api:1.0.0
region: cn
exposure: none
resources:
limits:
memory: 512M
reservations:
cpus: "0.10"
memory: 128M
部署顺序#
执行 luma deploy service.yaml 时,Luma 依次:
- 解析并校验服务清单。
- 如提供
--env <file>,在本地解析.env,只保留清单以${NAME}引用的变量。 - 从
~/.config/luma读取当前登录 context。 - 向 Manager Control API 提交清单与筛选后的应用作用域密钥。
- 按服务
name保存密钥,在渲染前解析${NAME}。 - 在 Manager 渲染
stacks/<region>/<service>/<service>.nomad.jsonjobspec。 - 为
tailscale-relay或tcp-relay渲染routes/<service>.yml。 - 创建或更新 Cloudflare DNS,除非明确跳过。
- 通过
PUT /v1/jobs创建或更新 Nomad job。 - 探测
cn-edge和external-edge服务的公共路由。
客户端在提交前、等待 Control 时及每个 Control 步骤中输出进度。Luma 验证生成的 Traefik 路由,在监视目录外暂存,再原子发布。公共路由探测报告 / 的 HTTP 状态:应用 404 表示路由可达但可能无根页面,Traefik 默认 404 page not found 则视为缺少 router 和路由失败。缺少 router 或短暂 502/503/504 时,Control 会重建一次 allocation 并重新探测,再判失败。单服务和 Compose job 给冷镜像获取 30 分钟、滚动进度 40 分钟;默认部署响应超时为 3000 秒,让 Control 等待超过有界 Nomad 窗口。可用 --timeout <seconds> 覆盖。
部署是 upsert。同名重复 luma deploy service.yaml 更新现有 Nomad job(ID 是服务 slug),不创建副本。当前渲染 jobspec 为更新依据,Nomad 保留上一版,可通过 luma rollback 或控制台 应用 → 版本回退。
项目已有部署环境文件时,用 luma deploy service.yaml --env .env。作用域密钥按服务名隔离,api/DATABASE_URL 与 worker/DATABASE_URL 是不同值。只有应用没有作用域密钥时,才使用旧全局 luma secret set NAME 的值。
源码到镜像部署的 luma import 使用同样的作用域密钥模型:
luma import https://github.com/acme/app --build-node builder --env .env
luma import acme/app --build-node builder --env .env # GitHub owner/repo shortcut
共享 Builder 较慢时,可在自己电脑构建当前检出,并将产物保留在同一个 Luma 项目:
cd app
luma build local . --env .env
luma build local 根据检出目录的 origin 推导项目身份(没有 origin 时用 --repo-url),在 Control 预留项目,通过本地 Docker Buildx 构建,推送到与 luma import 相同的 owner/repository 命名空间,再走正常部署。电脑必须能访问 build.registryHost,认证仓库需先 Docker 登录。支持单服务清单和 Compose sidecar,以及 --compose-sidecar、--platform、--context、--dockerfile。可用 --builder <name> 复用支持所需平台或仓库/镜像配置的本地 Buildx builder。--proxy <url> 为本地基础镜像和 Dockerfile 网络访问指定 HTTP 代理,内部仓库保留在 NO_PROXY。本地构建和 Builder 导入都根据目标节点或区域内就绪节点推导容器架构:Darwin/ARM 构建 linux/arm64,同时有 amd64 与 arm64 的区域构建多平台镜像。显式 --platform 必须覆盖全部已解析目标架构。
Control 声明 build-queue-v1 后,CLI 自动将仓库导入和 build retry 提交到每项目持久化 FIFO。本地构建使用 Control 分配的唯一标签,可并发构建上传;上传完成后,部署加入同一 FIFO。队列按提交顺序(本地构建为上传完成顺序),而非本地构建开始顺序。同一仓库项目一次只执行一个排队操作;其他项目可使用其他槽位,但仍受 Builder 容量和运行时部署锁约束。失败或取消不会丢弃后续任务。
等待时 CLI 显示构建 ID、队列位置及阻塞任务。--timeout 只限制客户端等待,服务端接受后关闭 CLI 不会取消任务。用 luma build logs <id> 查看,用 luma build cancel <id> 取消等待任务。队列可跨 Control 重启保留;被中断的活动任务明确标为失败,不自动重放部署副作用,重试前先检查运行时。未完成上传的本地构建仍依赖调用者电脑。每次尝试的环境值只在排队/执行期间存入私有 Control 状态,与其他尝试和公开构建历史隔离。
旧 Control 保留之前的活动构建冲突即失败限制,需同时升级 Control 和 CLI 才能排队。预构建镜像的 deploy 和 compose deploy 仍使用同步运行时锁。镜像超出预留项目仓库/标签范围的本地上传仍会被拒绝。
或使用保存的 Git 提供方账户:
luma import --provider-id gitea:lin --repository acme/app --ref main --build-node builder --env .env
Import 自动发现单服务清单(.luma.yml、luma.yml、嵌套 *.luma.yml)与 Compose sidecar(luma.compose.yml、.luma.compose.yml、*.luma.compose.yml、*.compose.luma.yml、docker-compose.luma.yml)。Compose 文件名不参与单服务匹配,因此 docker-compose.luma.yml 会按 Compose 处理。
仓库还没有部署文件时,可从 CLI 提供:
luma import --provider-id github:personal --repository acme/app \
--build-node builder \
--manifest deploy/app.luma.yml \
--env .env
与普通 luma deploy 不同,import 可能在 Builder 克隆后才发现最终清单。因此 CLI 将 .env 值发送给 Control,再由控制面仅保留最终清单或 Compose 引用的值,存入最终服务/stack 作用域。
对于 Compose 仓库,luma import 构建仍有 build: 的服务,并在部署前注入产出的 image:。普通 luma compose validate 和 luma compose deploy 不构建;本地检查该流程请用 import 模式校验:
luma compose validate --import-mode luma.compose.yml
仓库有多个部署 sidecar 时,请显式选择克隆仓库内的 Compose sidecar,不依赖自动发现:
luma import https://github.com/acme/platform.git \
--ref v1.4.0 \
--build-node builder \
--compose-sidecar deploy/staging.luma.compose.yml \
--env .env
--compose-sidecar 仅接受规范的 POSIX 仓库相对路径,不能与 --manifest 同用。CLI 构建前要求 Control 支持对应能力;Control 要求 Builder 回传同一路径;Builder 拒绝绝对路径、..、缺失/无效 YAML 和符号链接逃逸。显式选择不会回退到自动发现。任一侧缺少能力时先更新 Manager 和 Builder agent。
--dry-run 本地渲染,不提交部署。本地无法读取可选集群上下文(节点/存储元数据)时,JSON 包含 validationMode: "degraded" 和警告,文本输出 [warn]。--skip-dns 与 --skip-orchestrator 会传给 Control API。控制面部署模式已弃用 --commit、--push。
Luma 在外部操作前记录部署状态。成功标记为 active;若前面已改变 Manager,而后续 DNS、Nomad 提交、路由渲染或探测失败,则保留 status: failed_partial,供控制台和 luma service remove <name> 找到部分生效的 job。
luma service remove <name> 根据 Control 上次成功部署记录的清单,移除对应单服务或 Compose slug。此清单是依据,因此即使客户端没有 YAML,也能删除和清理网页创建的部署。默认删除 Luma 管理的 Cloudflare DNS,注销并清除 Nomad job,删除生成的 stacks/<region>/<service>/<service>.nomad.json 或 stacks/compose/<name>/<name>.nomad.json,以及 tailscale-relay/tcp-relay 路由文件。--dry-run 预览,--skip-dns 保留 DNS;只有有意仅删 Luma 文件而不停止 job 时,才用 --skip-orchestrator。默认保留存储数据;--delete-storage 删除记录中声明且可移除的存储。单服务清理 storage.<volume>.path 指向的托管路径与 data:/data 等 Docker 命名卷,跳过 bind mount;Compose 清理 sidecar 中的托管路径。--delete-storage 不能与 --skip-orchestrator 同用。cloudflare-tunnel 公共主机名仍由 Cloudflare Zero Trust 管理,Luma 会报告跳过该清理。
自动构建/部署流程检查#
Luma 在 Control 记录每个应用成功的 CLI 构建/部署流程,跨机器和 agent 共享,独立于检出目录及有界构建历史。已有应用无需回填。
在 luma import、luma build local、luma build retry、luma deploy 或 luma compose deploy 开始构建、预留上传或提交部署前:
- 无记录:正常继续,成功后创建记录。
- 匹配记录:正常继续并刷新成功记录。
- 流程不同:显示差异,确认后才能构建/部署。包括远程/本地/镜像/Compose 方式、显式 Git 仓库/ref、builder、平台、上下文/Dockerfile、sidecar、区域、入口/域名/端口、显式环境文件路径和网络选项。输出格式、超时、凭据和说明备注不触发变化。
交互文本终端询问 Confirm this workflow change and deploy? [y/N]。JSON/NDJSON、quiet 和非交互调用者非零退出。Agent 必须展示差异并获得用户批准,才能用 --accept-workflow-change 重试,不得自行添加该标志来消除错误。CI 也只能在流程变更获批后使用。
# Normal deployment: automatic check and recording; no extra flag needed.
luma import --provider-id github:me --repository acme/app --ref main --build-node builder
# Read the shared record, including the command and last recorded success.
luma workflow show app
luma workflow list --format json
# Add context to the record on the next successful deployment.
luma import acme/app --ref main --workflow-note 'Build on Builder; this project requires remote network access'
# Only after the user has approved the displayed differences:
luma build local . --platform linux/amd64 --accept-workflow-change
# Explicitly record/edit a workflow without executing it.
luma workflow record app --note 'Release from the main branch on Builder' -- \
import acme/app --ref main --build-node builder
# Execute the recorded command from a checkout, using current login credentials.
luma workflow run app --path /path/to/app
记录保留参数数组、方式、可选备注及最后成功配方/证据。手动编辑标为 manual;旧成功保留原配方,不能证明修改后的命令已执行。失败、中断流、dry-run 和 --skip-orchestrator 不覆盖成功记录。部署成功但保存流程失败时,CLI 报告成功并附 workflow.saved: false 和警告;不要为了修复记录错误盲目重新部署。并发编辑会保留。
清单标识服务/Compose 目标。Import 从仓库或 monorepo 中所选 sidecar 查找记录;匹配多个应用时用 --workflow-app APP 选择。不同应用名有独立记录。仓库相对路径可随检出移动;外部绝对配置/环境路径必须在下一台机器存在。配方不保存环境文件内容、管理令牌或 URL 凭据。自由文本备注由用户撰写,不要写入密钥。重试记录原构建参数和 build retry ID,重放要求原构建记录仍存在。检查比较的是 CLI 流程参数,不是源码变更、镜像标签或清单内容。
CLI 和 Control 都必须支持 deployment-workflow-v1,请先升级 Control。Control 不可达或太旧意味着检查不可用,不等于没有记录,因此部署会停止并说明原因。该流程是 CLI 协调机制;旧客户端及直接 API/控制台部署不参与这些 CLI 检查。