从零部署自己的中心

这是 Linux x86_64 + systemd 的独立部署示例,供安装者明确选择“部署自己的中心”后由 AI 按实际环境执行。域名、端口、目录和服务账号必须先确认;现有同名服务/目录存在时走更新流程,不能覆盖。Windows 电脑可以作为连接器;本页不宣称提供 Windows 服务管理器安装方案。

1. 准备程序、账号与空目录

在安装者授权的目标服务器解压并校验公开包。先确认 18081 端口空闲,/opt/sshmcp-center、/var/lib/sshmcp-center、/etc/sshmcp-center 和 sshmcp-center.service 没有被其他部署使用,再从包根目录执行:

sudo useradd --system --user-group --home-dir /var/lib/sshmcp-center --shell /usr/sbin/nologin sshmcp-center
sudo install -d -m 755 /opt/sshmcp-center/bin /opt/sshmcp-center/libexec
sudo install -m 755 linux-x86_64/mcp-ssh-manager /opt/sshmcp-center/bin/mcp-ssh-manager
sudo install -m 755 linux-x86_64/sshmcp-file-agent /opt/sshmcp-center/libexec/sshmcp-file-agent
sudo install -m 755 linux-x86_64/sshmcp-node-linux linux-x86_64/sshmcp-node-windows.exe linux-x86_64/sshmcp-file-agent-windows.exe /opt/sshmcp-center/bin/
sudo install -d -m 700 -o sshmcp-center -g sshmcp-center /var/lib/sshmcp-center
sudo install -d -m 700 -o sshmcp-center -g sshmcp-center /var/lib/sshmcp-center/config /var/lib/sshmcp-center/credentials /var/lib/sshmcp-center/.ssh
sudo install -m 600 -o sshmcp-center -g sshmcp-center config/ssh-config.empty.toml /var/lib/sshmcp-center/config/ssh-config.toml
sudo install -d -m 700 /etc/sshmcp-center

账号已经存在时先核对归属,不重复创建;发行版没有 useradd/systemd 时按本机服务管理器适配,不机械执行。本例开始时没有任何真实服务器或私钥。

2. 生成自己的接入 Key,不回显

把下面域名替换成你自己的 HTTPS 中心域名。Python 只用标准库;以独占创建写文件,已存在文件会停止,不轮换旧 Key。

sudo python3 - https://sshmcp.example.com <<'PY'
import json, os, secrets, sys
from pathlib import Path
os.umask(0o077)
root = Path('/etc/sshmcp-center')
names = ['service.env', 'API_KEY', 'ENDPOINT', 'connection.json']
if any((root / name).exists() for name in names):
    raise SystemExit('Existing enrollment data: preserve it and use the update workflow.')
key = secrets.token_urlsafe(32)
endpoint = sys.argv[1]
values = {
    'service.env': 'MCP_HTTP_BEARER_TOKEN=' + key + '\nMCP_CATALOG_EXPORT=true\nSSH_CONFIG_PATH=/var/lib/sshmcp-center/config/ssh-config.toml\nSSH_ENV_PATH=/var/lib/sshmcp-center/config/standalone.env\nMCP_SSH_MANAGER_FILE_AGENT_BINARY=/opt/sshmcp-center/libexec/sshmcp-file-agent\n',
    'API_KEY': key + '\n',
    'ENDPOINT': endpoint + '\n',
    'connection.json': json.dumps({'endpoint': endpoint, 'api_key': key}) + '\n'
}
for name, value in values.items():
    with (root / name).open('x') as file:
        file.write(value)
print('Private center enrollment files created; no key was printed.')
PY

这些文件是中心所有者的私密资料。不要把 service.env、API_KEY 或 connection.json 放到网页目录、日志或公开包。中心权威 TOML 与其引用的 SSH 私钥按设计保存在服务器磁盘,权限受限;只有连接器收到的 SSH 身份采用仅内存策略。

3. 安装并启动服务

将以下内容保存为新的 /etc/systemd/system/sshmcp-center.service;现有同名 unit 必须先审查,不能覆盖:

[Unit]
Description=Private SSHMCP center
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=sshmcp-center
Group=sshmcp-center
WorkingDirectory=/var/lib/sshmcp-center
Environment=HOME=/var/lib/sshmcp-center
EnvironmentFile=/etc/sshmcp-center/service.env
ExecStart=/opt/sshmcp-center/bin/mcp-ssh-manager --http --bind 127.0.0.1:18081
Restart=on-failure
RestartSec=3
UMask=0077
NoNewPrivileges=yes
ProtectHome=yes
ProtectSystem=strict
ReadWritePaths=/var/lib/sshmcp-center
PrivateTmp=yes

[Install]
WantedBy=multi-user.target
sudo systemd-analyze verify /etc/systemd/system/sshmcp-center.service
sudo systemctl daemon-reload
sudo systemctl enable --now sshmcp-center.service
curl --fail http://127.0.0.1:18081/healthz
sudo systemctl show sshmcp-center.service -p ActiveState -p NRestarts

Type=simple 的启动返回早于端口就绪时,在最多 10 秒内重试只读 health,再做后续验证。不要把不带 Key 的 health 成功当作鉴权成功。

4. 配置自己的 HTTPS 入口

把域名 DNS 指向自己的服务器,按已有网络规则开放对应 HTTPS 入口,使用已有反向代理或依其官方安装文档安装。不要覆盖其他站点。以 Caddy 为例,追加独立站点块,域名替换为自己的:

sshmcp.example.com {
    @foreign_origin {
        header Origin *
        not header Origin https://sshmcp.example.com
    }
    respond @foreign_origin "Forbidden" 403

    @api path /mcp /mcp/* /v1/catalog /v1/catalog/control /v1/network/control /v1/releases/current
    handle @api {
        header Cache-Control "no-store"
        reverse_proxy 127.0.0.1:18081 {
            header_up Host 127.0.0.1:18081
            # Origin was checked at this edge; the upstream has a loopback host.
            header_up -Origin
        }
    }
    handle {
        respond "Not found" 404
    }
}

模板采用 Caddy 官方的请求匹配和反向代理头处理。对实际配置执行 caddy validate 成功后才 reload,保留证书申请/续期所需网络;如果前面还有 CDN,私有 API 必须绕过缓存并保留鉴权。此示例不自动配置 CDN、DNS 或其他站点。

5. 验证并接入电脑

先验证缺失和错误 Key 被拒绝、合法 Key 返回 sshmcp-device-catalog-v1、Cache-Control 为 no-store、非法 Origin 为 403。认证请求由 AI 使用受限文件读 Key 放入 HTTP Authorization,不能把它写进命令行值或输出目录正文。

通过自己的私密文件传输方式,将 /etc/sshmcp-center/API_KEY 与 ENDPOINT(或 connection.json)送到自己可信电脑的私有目录。然后用 CENTER.md 的原生 install 命令,把 --key-file 指向这份私密 API_KEY,并仅选择安装者已选客户端。不要把服务器环境文件当安装包公开分发。

本机安装收据通过并重载后,用 ssh_server_manage 添加自己的目标。中心上被引用的 SSH 私钥应归服务账号可读,放在 /var/lib/sshmcp-center/credentials/ 等稳定私密目录;目录不能引用将被删除的测试路径。目标地址/原跳板必须从接入电脑可用。

完成一个目标的只读登录、两连接器唯一条目同步,以及本机文件传输后,再按 PRIVATE_BUNDLES.md 从自己保存的 connection.json 制作免输入私人包。备份/更新/迁移/撤销流程统一见 WORKFLOWS.md。

客户端自动更新的静态文件路径、清单发布与实机验收见 UPDATES.md。