# 🛠️ sharekit 安装教程 — 纯公开方式,不需要 scp

> **目标**: 让任何 agent / 人在一台干净 Ubuntu 24.04 上,5 分钟内自举 sharekit(file share + MCP server),并接入 smail.icu 邮件能力。

> **关键变更(v2)**: 本教程**不再要求 scp 整个 sharekit 目录**。所有源码已经发布到 `https://files.spannerjun.top/sharekit-release/`(公开 HTTP,任何人都能拉)。

---

## 0. 整体目标

部署完后:

| 端点 | 用途 |
|---|---|
| `https://files.<你的域名>` | 文件共享 (browse / upload / download) |
| `https://mcp.<你的域名>` | MCP server (12 sharekit tools + 9 smail tools) |

---

## 1. 必备前提

- 一台干净的 Linux 服务器 (Ubuntu 24.04 测试过)
- root 权限
- **2 个空闲二级域名**,都指向这台服务器的 IP,例如:
  - `files.example.com`
  - `mcp.example.com`
- 已能用 `acme.sh` 签 Let's Encrypt(本教程默认你会)
- **访问公网** —— 能 curl `https://files.spannerjun.top`

---

## 2. DNS 配置

| 主机 | 类型 | 值 |
|---|---|---|
| `files` | A | `<你的服务器 IP>` |
| `mcp` | A | `<你的服务器 IP>` |

---

## 3. 一键部署(全自动)

### 3.1 下载源码

**所有安装源码已经在 https://files.spannerjun.top 上公开**,无需 GitHub 账号、SSH 权限或私聊:

```bash
mkdir -p /home/hermes/sharekit
cd /home/hermes

# 推荐: 下载 tarball(包含全部源码,排除 secrets 和 venv)
TARBALL=$(curl -ksS https://files.spannerjun.top/browse?path=sharekit-release/ | \
    grep -oP 'sharekit-\d{{8}}-\d{{4}}\.tar\.gz' | head -1)
echo "latest tarball: $TARBALL"
curl -ksS -o "/tmp/$TARBALL" "https://files.spannerjun.top/raw?path=sharekit-release/$TARBALL"
tar xzf "/tmp/$TARBALL" -C /home/hermes/

# 解压后文件:
#   /home/hermes/sharekit/
#   ├── file_server.py
#   ├── mcp_server.py
#   ├── README.md
#   ├── sharekit-bootstrap.sh
#   └── skill-install.sh
```

如果你只想要单文件,**也可以直接拉**:

```bash
BASE="https://files.spannerjun.top/raw?path=sharekit-release"
curl -ksS -o /home/hermes/sharekit/file_server.py          "$BASE/file_server.py"
curl -ksS -o /home/hermes/sharekit/mcp_server.py           "$BASE/mcp_server.py"
curl -ksS -o /home/hermes/sharekit/sharekit-bootstrap.sh   "$BASE/sharekit-bootstrap.sh"
curl -ksS -o /home/hermes/sharekit/skill-install.sh        "$BASE/skill-install.sh"
curl -ksS -o /home/hermes/sharekit/README.md              "$BASE/README.md"
curl -ksS -o /home/hermes/sharekit/config.env.example      "$BASE/config.env.example"
chmod +x /home/hermes/sharekit/{sharekit-bootstrap,skill-install}.sh
```

### 3.2 准备工作

```bash
# 创建 hermes 系统用户(sharekit 服务的进程所有者)
useradd --system --home /home/hermes --shell /bin/bash \
    --comment "Hermes service account" hermes

# Python venv + 依赖
python3 -m venv /home/hermes/venv
/home/hermes/venv/bin/pip install fastapi httpx 'uvicorn[standard]' pydantic mcp
chmod -R go+rX /home/hermes/venv

# 确保所有文件归属 + 可读
chown -R hermes:hermes /home/hermes/sharekit /home/hermes/files
mkdir -p /home/hermes/files
chmod 755 /home/hermes /home/hermes/files /home/hermes/sharekit
```

### 3.3 写 `.env`

```bash
cd /home/hermes/sharekit
cp config.env.example .env
chmod 600 .env

# 编辑 .env 把 REDACTED 字段替换成你自己的真实值
$EDITOR .env
```

关键字段:
- `SHARE_MCP_ALLOWED_HOSTS=mcp.<你的域名>,127.0.0.1,localhost`
- `SHAREKIT_PUBLIC_BASE=https://files.<你的域名>`
- `SMAIL_*` 字段对应 smail.icu 邮件集成(见第 5 节)

### 3.4 写 nginx 自签占位 + 反代配置

```bash
mkdir -p /etc/nginx/ssl

# 占位证书(等 acme.sh 替换)
DOMAIN="example.com"   # ← 改成你后缀
for sub in files mcp; do
  openssl req -x509 -nodes -days 1 -newkey rsa:2048 \
    -keyout /etc/nginx/ssl/$sub.$DOMAIN.key \
    -out /etc/nginx/ssl/$sub.$DOMAIN.crt \
    -subj "/CN=$sub.$DOMAIN"
done

# /etc/nginx/conf.d/files.<你的域名>.conf
```

```nginx
server {
    listen 80;
    listen [::]:80;
    server_name files.<你的域名>;

    location /.well-known/acme-challenge/ {
        root /var/www/acme-challenge;
        default_type "text/plain";
    }
    location / { return 301 https://$host$request_uri; }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name files.<你的域名>;

    ssl_certificate     /etc/nginx/ssl/files.<你的域名>.fullchain.crt;
    ssl_certificate_key /etc/nginx/ssl/files.<你的域名>.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    client_max_body_size 512m;

    location / {
        proxy_pass http://127.0.0.1:8789;
        proxy_http_version 1.1;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
        proxy_read_timeout 300s;
    }
}
```

```nginx
server {
    listen 80;
    listen [::]:80;
    server_name mcp.<你的域名>;

    location /.well-known/acme-challenge/ {
        root /var/www/acme-challenge;
        default_type "text/plain";
    }
    location / { return 301 https://$host$request_uri; }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name mcp.<你的域名>;

    ssl_certificate     /etc/nginx/ssl/mcp.<你的域名>.fullchain.crt;
    ssl_certificate_key /etc/nginx/ssl/mcp.<你的域名>.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    client_max_body_size 50m;

    location / {
        proxy_pass http://127.0.0.1:8790;
        proxy_http_version 1.1;
        # FastMCP 绑 127.0.0.1,Host 必须硬编码,否则 421
        proxy_set_header Host              127.0.0.1;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Connection        "";
        proxy_buffering off;
        proxy_read_timeout 3600s;
    }
}
```

### 3.5 运行 bootstrap

```bash
sudo /home/hermes/sharekit/sharekit-bootstrap.sh
```

脚本会自动:
1. chown sharekit + files 目录到 hermes
2. 写 2 份 systemd unit (从 `/home/hermes/sharekit/sharekit-bootstrap.sh` 模板生成)
3. `daemon-reload` + enable + start
4. 等 `https://files.<你的域名>/health` 200
5. 打包 `~/.hermes/skills/` → `/home/hermes/files/skills/hermes-skills-<时间戳>.tar.gz`

### 3.6 签真实证书

```bash
acme.sh --issue -d files.<你的域名> -w /var/www/acme-challenge
acme.sh --install-cert -d files.<你的域名> --ecc \
  --cert-file /etc/nginx/ssl/files.<你的域名>.crt \
  --key-file /etc/nginx/ssl/files.<你的域名>.key \
  --fullchain-file /etc/nginx/ssl/files.<你的域名>.fullchain.crt \
  --reloadcmd "systemctl reload nginx"

acme.sh --issue -d mcp.<你的域名> -w /var/www/acme-challenge
acme.sh --install-cert -d mcp.<你的域名> --ecc \
  --cert-file /etc/nginx/ssl/mcp.<你的域名>.crt \
  --key-file /etc/nginx/ssl/mcp.<你的域名>.key \
  --fullchain-file /etc/nginx/ssl/mcp.<你的域名>.fullchain.crt \
  --reloadcmd "systemctl reload nginx"
```

> ⚠️ nginx ssl_certificate **必须指向 `.fullchain.crt`** (含中间 CA)。用单 cert `openssl s_client -verify_return_error` 会报 "unable to verify the first certificate"。

---

## 4. 验证

### 4.1 systemd

```bash
systemctl status sharekit-fileserver sharekit-mcpserver
# 两个都 active + enabled
```

### 4.2 file share

```bash
curl -ksS https://files.<你的域名>/health
# → {"status":"ok",...}
curl -ksS https://files.<你的域名>/browse
# → HTML index
curl -ksS https://files.<你的域名>/raw?path=readme.txt
# → test content
```

### 4.3 MCP server

```bash
curl -ksS -X POST https://mcp.<你的域名>/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize",
       "params":{"protocolVersion":"2025-03-26","capabilities":{},
                "clientInfo":{"name":"probe","version":"0"}}}'
# → 200 + mcp-session-id header
```

### 4.4 完整 MCP 工具列表

你应该看到 **21 个工具**:

```
sharekit: list_dir, read_file, file_info, mkdir, upload_text, delete,
         search, share_link, miniMax_usage, opencode_quota,
         litellm_models, litellm_chat (12 个)

smail.icu: smail_status, smail_list_accounts, smail_create_account,
           smail_delete_account, smail_postqueue, smail_logs,
           smail_send_email, smail_read_email, smail_run (9 个)
```

---

## 5. smail.icu 集成(可选)

sharekit 默认带 smail.icu 邮件工具,但需要先把 `~/.ssh/config` 配好:

```bash
mkdir -p /home/hermes/.ssh
chmod 700 /home/hermes/.ssh
chown hermes:hermes /home/hermes/.ssh

cat > /home/hermes/.ssh/config <<'CFG'
Host smail-server
    HostName smail.icu
    Port 22
    User root
    PreferredAuthentications password
    PubkeyAuthentication no
    StrictHostKeyChecking accept-new
    ConnectTimeout 10
CFG

chmod 600 /home/hermes/.ssh/config
chown hermes:hermes /home/hermes/.ssh/config
```

写 ASKPASS 脚本(让 ssh 用密码登录):

```bash
cat > /usr/local/bin/smail-askpass.sh <<'ASK'
#!/bin/sh
echo '你的_smail.icu_密码'
ASK
chmod 755 /usr/local/bin/smail-askpass.sh
```

然后 `.env` 里 smail 字段:

```
SMAIL_HOST=mail.smail.icu
SMAIL_SSH_ALIAS=smail-server
SMAIL_CONTAINER=mailserver
SMAIL_AGENT_EMAIL=hermes@smail.icu
SMAIL_AGENT_PASSWORD='密码'
SMAIL_ADMIN_EMAIL=admin@smail.icu
SMAIL_ADMIN_PASSWORD='密码'
```

重启 mcp 服务让 .env 生效:

```bash
systemctl restart sharekit-mcpserver
sleep 5
```

---

## 6. 失败排查

| 症状 | 原因 | 修法 |
|---|---|---|
| `nginx 421` on mcp path | FastMCP 拒绝 Host 头 | nginx 加 `proxy_set_header Host 127.0.0.1;` |
| `mcp 400` | 丢失 `mcp-session-id` header | 跨请求保留这个头 |
| `smail_*` 超时 | SSH 链路不通 | `ssh smail-server echo OK` 先验证 |
| `smail_*` Permission denied | ASKPASS 没生效 | 查 `/usr/local/bin/smail-askpass.sh` 是否 755,以及 `cat $(which ssh) | head` 看是否 PATH 包含 `/usr/local/bin` |
| `connection refused` on 8789 / 8790 | systemd 没起 | `journalctl -u sharekit-fileserver -n 30` |
| 创建账号报 "User doesn't exist" | DMS 偶发 bug | `ssh smail-server 'docker exec mailserver supervisorctl restart dovecot'` |

---

## 7. 卸载

```bash
systemctl disable --now sharekit-fileserver sharekit-mcpserver
rm /etc/systemd/system/sharekit-*.service
rm /etc/nginx/conf.d/files.<你的域名>.conf /etc/nginx/conf.d/mcp.<你的域名>.conf
systemctl daemon-reload && nginx -s reload
rm -rf /home/hermes/sharekit /home/hermes/files
userdel hermes
```

---

## 🎁 Bonus:已部署实例参考

实时 demo:`https://files.spannerjun.top` 与 `https://mcp.spannerjun.top`

诊断命令:
```bash
systemctl cat sharekit-fileserver
systemctl cat sharekit-mcpserver
cat /home/hermes/sharekit/.env
journalctl -u sharekit-fileserver -n 30
```

源码 + tarball 也公开在那里:
- `https://files.spannerjun.top/browse?path=sharekit-release/`
- 直接看: `https://files.spannerjun.top/raw?path=sharekit-release/sharekit-20260705-1748.tar.gz`

---

**祝部署顺利!** — 如有问题,提 issue 或去上面的实例的 web 看实际行为。
