feat: node updates by restart, auto by default; Podman Quadlet install from the panel alongside compose [CI]
ci/woodpecker/push/main-amd64-build Pipeline was successful
ci/woodpecker/push/main-amd64-build Pipeline was successful
This commit is contained in:
1 parent
88b1a0a9bb
commit
535bb3517d
32 files changed
+751
-152
No files matched your search
@@ -4,14 +4,16 @@ import { CommandTabs, CopyButton, Dialog, Field, guessPlatform, type CommandTab
|
||||
|
||||
/**
|
||||
* 加入令牌创建之后的对话框:Agent 和 Probe 共用同一份。
|
||||
* 首选 compose:把面板给的 .env 存下来,下载 compose.yaml,`compose up -d`,以后更新就是 `compose pull && compose up -d`。
|
||||
* .env 里只有公开的值(面板地址、一次性码、信任根指纹和属主),没有任何私钥;脚本一行命令留作备用。
|
||||
* Podman 系(Linux)首选 Quadlet(Podman 4.6+):env、单元文件(核对哈希)、启动用户服务;单元 Pull=always,节点发现新版本后自己退出重启,所以默认自动更新。
|
||||
* Docker(Linux、macOS、Windows)用 compose:把面板给的 .env 存下来,下载 compose.yaml,`compose up -d`;compose 不会自动更新,手动 `compose pull && compose up -d`。
|
||||
* env/.env 里只有公开的值(面板地址、一次性码、信任根指纹和属主),没有任何私钥;一行安装脚本留作备用。
|
||||
*/
|
||||
export function JoinTokenCreated({ created, kind, onClose }: { created: CreatedJoinTokenDto; kind: 'Agent' | 'Probe'; onClose: () => void }) {
|
||||
const quadlet = created.quadlet
|
||||
const compose = created.compose
|
||||
const script = created.install_commands
|
||||
const composeTabs: CommandTab[] = [
|
||||
{ id: 'linux', label: 'Linux · Podman', command: compose.linux },
|
||||
{ id: 'linux', label: 'Linux · compose', command: compose.linux },
|
||||
...(compose.macos ? [{ id: 'macos', label: 'macOS · Docker', command: compose.macos }] : []),
|
||||
...(compose.windows ? [{ id: 'windows', label: 'Windows · Docker', command: compose.windows }] : []),
|
||||
]
|
||||
@@ -29,15 +31,40 @@ export function JoinTokenCreated({ created, kind, onClose }: { created: CreatedJ
|
||||
<div className="stack">
|
||||
<div className="notice warn">一次性码只显示这一次,请现在就复制。下面只有公开的值(面板地址、一次性码、信任根指纹和属主),没有任何私钥。</div>
|
||||
<Field
|
||||
label={`容器安装(推荐):在要加入的机器上运行(${kind})`}
|
||||
hint="需要 podman compose 或 docker compose。命令建一个目录,把参数写进 .env(权限 600),下载 compose.yaml 并核对 SHA-256,一致才启动。节点名字默认取主机名;想自己定,在 .env 里加一行 MOSHIRO_NAME=名字(1–64 个字母、数字、点、下划线、横线)。"
|
||||
label={`Podman(推荐,自动更新):在要加入的机器上运行(${kind})`}
|
||||
hint="Linux,Podman 4.6 及以上,用普通用户运行(rootless,不用 sudo)。命令把参数写进 ~/.config/moshiro/(权限 600),下载 Quadlet 单元并核对 SHA-256,一致才启动。退出登录后继续运行需要管理员执行一次 loginctl enable-linger 用户名。节点名字默认取主机名;想自己定,在 env 里加一行 MOSHIRO_NAME=名字(1–64 个字母、数字、点、下划线、横线)。"
|
||||
>
|
||||
<CommandTabs storageKey="moshiro.quadlet_tab" initial="linux" tabs={[{ id: 'linux', label: 'Linux · Podman Quadlet', command: quadlet.command }]} />
|
||||
</Field>
|
||||
<p className="muted">
|
||||
自动更新默认开:面板发现新版本后,节点运行满 10 分钟就自己退出,Podman 重新启动时先拉最新镜像(<span className="mono">Pull=always</span>)。
|
||||
想改成在管理端点「更新」才更新,把 env 里 <span className="mono"># MOSHIRO_UPDATE_POLICY=manual</span> 的 # 去掉。固定版本:把单元里的 <span className="mono">:latest</span> 换成版本号。
|
||||
</p>
|
||||
<Field
|
||||
label="Docker(Linux、macOS、Windows):compose"
|
||||
hint="需要 docker compose(或 podman compose)。命令建一个目录,把参数写进 .env(权限 600),下载 compose.yaml 并核对 SHA-256,一致才启动。compose 不会自动更新(容器自己没法重新拉取):手动 compose pull && compose up -d。"
|
||||
>
|
||||
<CommandTabs storageKey="moshiro.compose_tab" initial={initial} tabs={composeTabs} />
|
||||
</Field>
|
||||
<details>
|
||||
<summary>分步做:.env 内容、compose 下载地址和哈希</summary>
|
||||
<summary>分步做:Quadlet 的 env 和单元,compose 的 .env 和 compose.yaml</summary>
|
||||
<div className="stack" style={{ marginTop: 8 }}>
|
||||
<Field label=".env(存成当前目录下的 .env)">
|
||||
<Field label="Quadlet env(存成 ~/.config/moshiro/ 下的 agent.env 或 probe.env)">
|
||||
<div className="row" style={{ alignItems: 'flex-start', gap: 8 }}>
|
||||
<pre className="code" style={{ flex: 1, whiteSpace: 'pre-wrap', wordBreak: 'break-all', margin: 0 }}>{quadlet.env}</pre>
|
||||
<CopyButton text={quadlet.env} />
|
||||
</div>
|
||||
</Field>
|
||||
<Field label="Quadlet 单元(放进 ~/.config/containers/systemd/)">
|
||||
<div className="stack">
|
||||
<div className="row" style={{ gap: 8 }}>
|
||||
<span className="mono" style={{ wordBreak: 'break-all' }}>{quadlet.url}</span>
|
||||
<CopyButton text={quadlet.url} />
|
||||
</div>
|
||||
<div className="muted mono" style={{ wordBreak: 'break-all' }}>SHA-256 {quadlet.sha256}</div>
|
||||
</div>
|
||||
</Field>
|
||||
<Field label=".env(compose:存成当前目录下的 .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} />
|
||||
@@ -55,8 +82,8 @@ export function JoinTokenCreated({ created, kind, onClose }: { created: CreatedJ
|
||||
</div>
|
||||
</details>
|
||||
<p className="muted">
|
||||
以后更新:<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> 一行删掉。
|
||||
compose 更新:<span className="mono">podman compose pull && podman compose up -d</span>(Docker 把 podman 换成 docker);身份和配置在命名卷里,不会动。
|
||||
注册成功之后,可以把 env 或 .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>
|
||||
|
||||
@@ -323,7 +323,7 @@ function Versions() {
|
||||
{nodes.length === 0 && !info.loading ? <Empty>还没有节点上报过版本</Empty> : null}
|
||||
<p className="muted" style={{ marginTop: 12 }}>
|
||||
版本、tag 和构建时间是各个程序自己上报的。设置里打开「site.show_build」之后,展示页底部和节点卡片上才会给访客显示(提交号只在这里显示)。
|
||||
「更新」一列来自节点宿主机上的更新器:清单是 CI 签名的,面板只负责通知和请求,验签和拉取都在节点上完成;没装更新器的节点这一列是「—」。
|
||||
「更新」一列来自节点:Podman Quadlet 节点(MOSHIRO_UPDATE=restart)点更新就是有序退出、由 systemd 重新拉取最新镜像;宿主机更新器节点由更新器验签和拉取:清单是 CI 签名的,面板只负责通知和请求,验签和拉取都在节点上完成;没装更新器的节点这一列是「—」。
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user