# Gitea Actions 自动部署指南

> 目标：推送到 `main`/`master` 分支后，Gitea Actions 自动构建并部署到服务器 `8.153.107.96`。
>
> 方案：Gitea Actions + 自托管 Runner（host 模式）+ Docker Compose + Gitea Secrets

## 架构

```
开发者 push → Gitea (http://8.153.107.96/gitea) → Actions 触发
   ↓
Runner (同机 host 模式) 执行 workflow
   ↓
1. checkout 代码
2. rsync 同步到 /opt/agentkit/repo
3. 从 Secrets 写入 .env
4. docker compose build & up -d
5. 健康检查 http://localhost:8001/api/v1/health
```

## 前置条件

服务器 `8.153.107.96` 上需具备：

- [x] Gitea >= 1.21（已部署在 `http://8.153.107.96/gitea`）
- [x] Docker Engine >= 20.10
- [x] Docker Compose v2（`docker compose` 命令）
- [x] sudo 权限的用户（用于安装 Runner、创建 /opt/agentkit）

## 步骤一：启用 Gitea Actions

SSH 登录服务器，编辑 Gitea 配置文件（通常在 `/etc/gitea/app.ini` 或 Gitea 容器内的 `/data/gitea/conf/app.ini`）：

```ini
[actions]
ENABLED = true
DEFAULT_ACTIONS_URL = https://gitea.com
```

重启 Gitea：

```bash
# 若 Gitea 以 systemd 运行
sudo systemctl restart gitea

# 若 Gitea 以 docker 运行
docker restart gitea
```

## 步骤二：安装 Gitea Runner（host 模式）

> host 模式直接在宿主机执行 shell 命令，可操作 `/opt/agentkit` 和 Docker，无需挂载 socket。

```bash
# 1. 下载 runner 二进制（Linux x86_64 示例）
# 最新版本见 https://gitea.com/gitea/actions-runner/releases
RUNNER_VERSION=0.2.6
curl -L -o /usr/local/bin/gitea-runner \
  "https://gitea.com/gitea/actions-runner/releases/download/v${RUNNER_VERSION}/gitea-runner-${RUNNER_VERSION}-linux-amd64"
chmod +x /usr/local/bin/gitea-runner

# 2. 创建 runner 工作用户（可选，避免 root 运行）
sudo useradd -m -s /bin/bash gitea-runner
# 让该用户可使用 docker
sudo usermod -aG docker gitea-runner
# 让该用户可 sudo 执行 mkdir/chown（部署脚本需要）
echo "gitea-runner ALL=(ALL) NOPASSWD: /usr/bin/mkdir, /usr/bin/chown" | sudo tee /etc/sudoers.d/gitea-runner

# 3. 切换到 runner 用户
sudo su - gitea-runner

# 4. 注册 runner
gitea-runner register \
  --instance http://8.153.107.96/gitea \
  --token <YOUR_REGISTRATION_TOKEN> \
  --name self-hosted \
  --labels self-hosted,linux \
  --no-interactive

# 注册 token 获取路径：
# Gitea Web → 站点管理 → Actions → Runners → 创建 Runner token
# 或仓库级：仓库 → Settings → Actions → Runners → 创建 token
```

创建 systemd 服务（推荐，开机自启）：

```bash
sudo tee /etc/systemd/system/gitea-runner.service > /dev/null <<'EOF'
[Unit]
Description=Gitea Actions Runner
After=network.target docker.service

[Service]
User=gitea-runner
Group=gitea-runner
WorkingDirectory=/home/gitea-runner
ExecStart=/usr/local/bin/gitea-runner daemon
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now gitea-runner
sudo systemctl status gitea-runner
```

验证 runner 已注册：Gitea Web → 站点管理 → Actions → Runners，应看到 `self-hosted` 状态为 `idle`。

## 步骤三：配置 Gitea Secrets

进入仓库 → **Settings → Actions → Secrets**，添加以下 secrets（参考 `.env.example`）：

| Secret 名 | 说明 | 是否必填 |
|-----------|------|---------|
| `POSTGRES_PASSWORD` | PostgreSQL 密码 | **必填** |
| `REDIS_PASSWORD` | Redis 密码 | **必填** |
| `AGENTKIT_API_KEY` | 外部系统调用 API 的密钥 | **必填** |

> **LLM API Key 不在此配置**。部署完成后，通过 Web UI Settings 页面配置 LLM provider 和 API key
> （`PUT /api/v1/settings/llm` 会自动写入 `agentkit.yaml` 和 `.env`）。

## 步骤四：首次部署准备

```bash
# 1. 创建部署目录
sudo mkdir -p /opt/agentkit
sudo chown -R gitea-runner:gitea-runner /opt/agentkit

# 2. 确认 Docker 已就绪
docker version
docker compose version
```

## 步骤五：触发部署

```bash
# 本地推送主干分支
git push origin main
```

推送后访问：Gitea Web → 仓库 → **Actions**，查看 `Deploy to Production` workflow 执行情况。

## 验证

```bash
# 1. 服务状态
ssh user@8.153.107.96
cd /opt/agentkit/repo
docker compose -f docker-compose.deploy.yaml ps

# 2. 健康检查
curl http://localhost:8001/api/v1/health

# 3. 公网访问
curl http://8.153.107.96:8001/api/v1/health

# 4. 查看日志
docker compose -f docker-compose.deploy.yaml logs -f --tail=100
```

## 首次使用：配置 LLM API Key

部署成功后，服务可访问但尚未配置 LLM provider（聊天功能不可用）。通过 Web UI 完成 onboarding：

1. 浏览器访问 `http://8.153.107.96:8001`
2. 进入 **Settings → LLM** 页面
3. 添加 LLM provider（支持 OpenAI / Anthropic / Gemini / DeepSeek / 通义千问 / 豆包 等）
4. 填入 API key 并选择默认模型
5. 保存后配置自动写入 `agentkit.yaml` 和 `.env`，无需重启服务

也可通过 API 直接配置：

```bash
curl -X PUT http://8.153.107.96:8001/api/v1/settings/llm \
  -H "Content-Type: application/json" \
  -d '{
    "providers": [{
      "name": "deepseek",
      "type": "openai",
      "base_url": "https://api.deepseek.com/v1",
      "api_key": "sk-your-key-here",
      "models": {"deepseek-chat": {"alias": "default"}}
    }]
  }'
```

## 文件清单

| 文件 | 用途 |
|------|------|
| `.gitea/workflows/deploy.yml` | Gitea Actions 工作流定义 |
| `scripts/deploy.sh` | 服务器侧部署脚本（build + up） |
| `docker-compose.deploy.yaml` | 生产部署专用 Compose（不暴露 DB 端口） |
| `.env.example` | Secrets 配置清单参考 |

## 故障排查

### Runner 不执行任务

- 确认 runner 标签包含 `self-hosted`（workflow 中 `runs-on: self-hosted`）
- 确认 runner 状态为 `idle` 而非 `offline`
- `sudo journalctl -u gitea-runner -f` 查看 runner 日志

### docker compose 命令找不到

- 确认安装 Docker Compose v2：`docker compose version`
- 若仅有 v1（`docker-compose`），需安装 `docker-compose-plugin`

### 健康检查失败

```bash
# 查看容器日志
docker compose -f /opt/agentkit/repo/docker-compose.deploy.yaml logs agentkit

# 进入容器排查
docker compose -f /opt/agentkit/repo/docker-compose.deploy.yaml exec agentkit bash
```

### .env 未生成或内容缺失

- 确认所有必填 Secrets 已配置（POSTGRES_PASSWORD、REDIS_PASSWORD、AGENTKIT_API_KEY）
- workflow 中 `cat > "$REPO_DIR/.env"` 步骤需成功执行，查看 Actions 日志

### 首次部署数据库初始化

首次启动时 PostgreSQL 会自动初始化。如需重置（**会丢数据**）：

```bash
cd /opt/agentkit/repo
docker compose -f docker-compose.deploy.yaml down -v
docker compose -f docker-compose.deploy.yaml up -d
```

## 安全建议

1. **不要**将 `.env` 提交到仓库（已在 `.gitignore` 中）
2. 服务器防火墙仅放行 `8001`（API）、`22`（SSH）、`80/443`（Gitea），**不要**暴露 `5432`/`6379` 到公网
3. 定期备份 `/opt/agentkit/repo/.env` 和 Docker 卷（`pgdata`、`redisdata`）
4. Runner 用户 `gitea-runner` 仅授予最小 sudo 权限（已通过 sudoers 限制）
5. 生产 POSTGRES_PASSWORD / REDIS_PASSWORD 应为强随机字符串
