feat: install nodes and the backend from a static compose file; remove dead code [CI]
ci/woodpecker/push/main-amd64-build Pipeline was successful
ci/woodpecker/push/main-amd64-build Pipeline was successful
Agent, Probe and Backend now start from one static compose.yaml plus a local
.env: the panel (or the release assets, for the very first Backend) provides
the file, the panel's command writes the public values into .env, checks the
file's SHA-256 and runs compose up. Updating is compose pull && compose up -d.
The image is chosen by the CI channel (:latest, or MOSHIRO_VERSION in .env),
not by the panel; the previous one-line script stays as a fallback.
- packaging/compose/{agent,probe,backend}/compose.yaml are the single source,
embedded in the Backend and served at /install/compose/{file}; the root
compose.yaml moved there. Releases also carry them and list them in the
signed SHA256SUMS.
- The container entrypoint defaults the node name to the host name.
- Join token creation returns a compose block (.env, url, hash, per-platform
commands); the admin dialog leads with it.
- Remove code with no references (HotLayer members, LiveHub.SubscriberCount,
QueryService.ParseParams, ReleaseService.Forget, a few constants) and reduce
the install-code lookup to the role it is for.
This commit is contained in:
1 parent
e014a19554
commit
12be44645f
31 files changed
+492
-176
No files matched your search
@@ -1,13 +1,21 @@
|
||||
import type { CreatedJoinTokenDto } from '@shared/api/types'
|
||||
import { fmtTime } from '@shared/format'
|
||||
import { CommandTabs, Dialog, Field, guessPlatform } from '@shared/ui'
|
||||
import { CommandTabs, CopyButton, Dialog, Field, guessPlatform, type CommandTab } from '@shared/ui'
|
||||
|
||||
/**
|
||||
* 加入令牌创建之后的对话框:Agent 和 Probe 共用同一份,一行命令装好。
|
||||
* 命令里只有一次性代码,角色由代码决定;节点名字默认取主机名。
|
||||
* 加入令牌创建之后的对话框:Agent 和 Probe 共用同一份。
|
||||
* 首选 compose:把面板给的 .env 存下来,下载 compose.yaml,`compose up -d`,以后更新就是 `compose pull && compose up -d`。
|
||||
* .env 里只有公开的值(面板地址、一次性码、信任根指纹和属主),没有任何私钥;脚本一行命令留作备用。
|
||||
*/
|
||||
export function JoinTokenCreated({ created, kind, onClose }: { created: CreatedJoinTokenDto; kind: 'Agent' | 'Probe'; onClose: () => void }) {
|
||||
const commands = created.install_commands
|
||||
const compose = created.compose
|
||||
const script = created.install_commands
|
||||
const composeTabs: CommandTab[] = [
|
||||
{ id: 'linux', label: 'Linux · Podman', command: compose.linux },
|
||||
...(compose.macos ? [{ id: 'macos', label: 'macOS · Docker', command: compose.macos }] : []),
|
||||
...(compose.windows ? [{ id: 'windows', label: 'Windows · Docker', command: compose.windows }] : []),
|
||||
]
|
||||
const initial = composeTabs.some((t) => t.id === guessPlatform()) ? guessPlatform() : 'linux'
|
||||
return (
|
||||
<Dialog
|
||||
title="加入令牌已创建"
|
||||
@@ -19,25 +27,53 @@ export function JoinTokenCreated({ created, kind, onClose }: { created: CreatedJ
|
||||
}
|
||||
>
|
||||
<div className="stack">
|
||||
<div className="notice warn">命令里的代码只显示这一次,请现在就复制。命令里只有公开的值(面板地址、一次性码、信任根指纹和属主),没有任何私钥。</div>
|
||||
<div className="notice warn">一次性码只显示这一次,请现在就复制。下面只有公开的值(面板地址、一次性码、信任根指纹和属主),没有任何私钥。</div>
|
||||
<Field
|
||||
label={`容器安装(推荐):在要加入的机器上运行(${kind})`}
|
||||
hint="需要 Docker 或 Podman。命令会先下载安装脚本并核对它的 SHA-256,不一致就不执行;节点名字默认取主机名;身份和配置存在命名卷里,重启、换新镜像重建容器都不用再给参数。名字想自己定,或者提示名字被占用,在命令里加上 MOSHIRO_NAME=名字(Linux 和 macOS 写在 bash 或 zsh 前面,Windows 先执行 $env:MOSHIRO_NAME='名字')。"
|
||||
hint="需要 podman compose 或 docker compose。命令建一个目录,把参数写进 .env(权限 600),下载 compose.yaml 并核对 SHA-256,一致才启动。节点名字默认取主机名,想自己定就改 .env 里的 MOSHIRO_NAME。"
|
||||
>
|
||||
<CommandTabs
|
||||
storageKey="moshiro.install_tab"
|
||||
initial={guessPlatform()}
|
||||
tabs={[
|
||||
{ id: 'linux', label: 'Linux · 容器', command: commands.linux },
|
||||
{ id: 'macos', label: 'macOS · 容器', command: commands.macos },
|
||||
{ id: 'windows', label: 'Windows · 容器', command: commands.windows },
|
||||
]}
|
||||
/>
|
||||
<CommandTabs storageKey="moshiro.compose_tab" initial={initial} tabs={composeTabs} />
|
||||
</Field>
|
||||
<details>
|
||||
<summary>分步做:.env 内容、compose 下载地址和哈希</summary>
|
||||
<div className="stack" style={{ marginTop: 8 }}>
|
||||
<Field label=".env(存成当前目录下的 .env)">
|
||||
<div className="row" style={{ alignItems: 'flex-start', gap: 8 }}>
|
||||
<pre className="code" style={{ flex: 1, whiteSpace: 'pre-wrap', wordBreak: 'break-all', margin: 0 }}>{compose.env}</pre>
|
||||
<CopyButton text={compose.env} />
|
||||
</div>
|
||||
</Field>
|
||||
<Field label="compose.yaml">
|
||||
<div className="stack">
|
||||
<div className="row" style={{ gap: 8 }}>
|
||||
<span className="mono" style={{ wordBreak: 'break-all' }}>{compose.url}</span>
|
||||
<CopyButton text={compose.url} />
|
||||
</div>
|
||||
<div className="muted mono" style={{ wordBreak: 'break-all' }}>SHA-256 {compose.sha256}</div>
|
||||
</div>
|
||||
</Field>
|
||||
</div>
|
||||
</details>
|
||||
<p className="muted">
|
||||
容器方式是首选:镜像按 CI 签名的清单固定到 digest,宿主机更新器能自己更新它,属主和信任根在注册时固定。{kind === 'Agent' ? (created.token.auto_approve ? '使用它注册的 Agent 会自动启用。' : '使用它注册的 Agent 需要你在列表里审批之后才会启用。') : ''}
|
||||
以后更新:<span className="mono">podman compose pull && podman compose up -d</span>(Docker 把 podman 换成 docker);身份和配置在命名卷里,不会动。
|
||||
想固定版本,在 .env 里写 <span className="mono">MOSHIRO_VERSION=版本号</span>。注册成功之后,可以把 .env 里的 <span className="mono">MOSHIRO_JOIN</span> 一行删掉。
|
||||
{kind === 'Agent' ? (created.token.auto_approve ? ' 使用它注册的 Agent 会自动启用。' : ' 使用它注册的 Agent 需要你在列表里审批之后才会启用。') : ''}
|
||||
可用 {created.token.max_uses} 次,{fmtTime(created.token.expires_at)} 过期。
|
||||
</p>
|
||||
<details>
|
||||
<summary>备用:一行安装脚本(先核对脚本哈希再执行,需要 Docker 或 Podman)</summary>
|
||||
<div style={{ marginTop: 8 }}>
|
||||
<CommandTabs
|
||||
storageKey="moshiro.install_tab"
|
||||
initial={guessPlatform()}
|
||||
tabs={[
|
||||
{ id: 'linux', label: 'Linux · 脚本', command: script.linux },
|
||||
{ id: 'macos', label: 'macOS · 脚本', command: script.macos },
|
||||
{ id: 'windows', label: 'Windows · 脚本', command: script.windows },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</Dialog>
|
||||
)
|
||||
|
||||
@@ -1178,6 +1178,23 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/install/compose/{file}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/** The static compose file of agent, probe or backend (agent.yaml, probe.yaml, backend.yaml; same bytes for everyone) */
|
||||
get: operations["install_compose"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/install.ps1": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -1407,6 +1424,14 @@ export interface components {
|
||||
[key: string]: null | number | string;
|
||||
};
|
||||
};
|
||||
ComposeInstallDto: {
|
||||
env: string;
|
||||
url: string;
|
||||
sha256: string;
|
||||
linux: string;
|
||||
macos: string;
|
||||
windows: string;
|
||||
};
|
||||
ConfirmBackendUpdateRequest: {
|
||||
/** Format: int64 */
|
||||
seq: number | string;
|
||||
@@ -1459,6 +1484,7 @@ export interface components {
|
||||
token: components["schemas"]["JoinTokenDto"];
|
||||
plaintext: string;
|
||||
install_commands: components["schemas"]["InstallCommandsDto"];
|
||||
compose: components["schemas"]["ComposeInstallDto"];
|
||||
};
|
||||
DimensionDto: {
|
||||
id: string;
|
||||
@@ -6179,6 +6205,35 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
install_compose: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
file: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
/** @description Not Found */
|
||||
404: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/problem+json": components["schemas"]["ProblemDto"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
install_ps1: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
@@ -40,6 +40,7 @@ export type ParamDto = Narrow<S['ParamDto']>
|
||||
export type MetricDto = Narrow<S['MetricDto']>
|
||||
export type JoinTokenDto = Narrow<S['JoinTokenDto']>
|
||||
export type CreatedJoinTokenDto = Narrow<S['CreatedJoinTokenDto']>
|
||||
export type ComposeInstallDto = Narrow<S['ComposeInstallDto']>
|
||||
export type ApiTokenDto = Narrow<S['ApiTokenDto']>
|
||||
export type CreatedApiTokenDto = Narrow<S['CreatedApiTokenDto']>
|
||||
export type CapabilityCatalogDto = Narrow<S['CapabilityCatalogDto']>
|
||||
|
||||
Reference in new issue
Block a user