# 部署文档(JessieGem.zeotaki.com / backend:2088 / frontend:2099) 本文档假设目标服务器为 Linux(Ubuntu/Debian 系)。部署目标: - 后端 Go 服务监听 `127.0.0.1:2088` - 前端 Vite 预览服务监听 `127.0.0.1:2099` - Nginx 对外提供 `https://JessieGem.zeotaki.com`,并转发: - `/` -> 前端 `2099` - `/api/` -> 后端 `2088` > 这样前端请求 `/api/*` 仍然同域,不需要浏览器跨域。 --- ## 0. 服务器前置 ### 0.1 依赖软件 在服务器安装: - Nginx - MySQL(或可访问的 MySQL 实例) - Go 1.22+ - Node.js 20+(用于构建与运行 `vite preview`) Ubuntu 示例: ```bash sudo apt update sudo apt install -y nginx git ``` Go/Node 的安装方式你可按服务器习惯来(官方包、nvm、asdf 都可),但要满足版本要求: - Go:`go version` >= 1.22 - Node:`node -v` >= 20 ### 0.2 端口规划与防火墙 - 对公网开放:80/443 - 仅本机监听:2088/2099(不要直接暴露公网) 如使用 UFW: ```bash sudo ufw allow 80 sudo ufw allow 443 sudo ufw enable ``` --- ## 1. 后端部署(Go / 2088) ### 1.1 创建运行用户与目录 ```bash sudo useradd -r -s /usr/sbin/nologin cockpit || true sudo mkdir -p /opt/jessiegem-cockpit/backend sudo mkdir -p /etc/jessiegem-cockpit sudo chown -R cockpit:cockpit /opt/jessiegem-cockpit ``` ### 1.2 准备后端配置 后端读取 `backend/configs/config.yaml`(相对工作目录 `./configs`),同时也支持环境变量覆盖(`COCKPIT_` 前缀)。 推荐在服务器用独立配置目录 `/etc/jessiegem-cockpit/config.yaml`,然后 systemd 的 `WorkingDirectory` 指向 `/opt/jessiegem-cockpit/backend`,并把配置复制到 `./configs/config.yaml`。 创建配置: ```bash sudo mkdir -p /opt/jessiegem-cockpit/backend/configs sudo tee /opt/jessiegem-cockpit/backend/configs/config.yaml >/dev/null <<'YAML' server: addr: "127.0.0.1:2088" db: driver: "mysql" # 按你的服务器实际 MySQL 修改 dsn: "root:root@tcp(127.0.0.1:3306)/cockpit?charset=utf8mb4&parseTime=True&loc=Local" auth: # 必须替换为强随机串 accessTokenSecret: "REPLACE_ME_ACCESS" refreshTokenSecret: "REPLACE_ME_REFRESH" accessTokenTtl: "15m" refreshTokenTtl: "720h" cors: allowOrigins: - "https://JessieGem.zeotaki.com" YAML sudo chown -R cockpit:cockpit /opt/jessiegem-cockpit/backend sudo chmod 600 /opt/jessiegem-cockpit/backend/configs/config.yaml ``` > 注意:后端启动会自动 AutoMigrate + Seed(包含默认管理员 `admin/admin123`)。生产环境建议你首次登录后立即改密码。 ### 1.3 systemd 服务(backend) 创建 `/etc/systemd/system/cockpit-backend.service`: ```bash sudo tee /etc/systemd/system/cockpit-backend.service >/dev/null <<'UNIT' [Unit] Description=Cockpit Backend (Go) After=network.target [Service] User=cockpit Group=cockpit WorkingDirectory=/opt/jessiegem-cockpit/backend ExecStart=/opt/jessiegem-cockpit/backend/cockpit-server Restart=always RestartSec=2 Environment=GIN_MODE=release [Install] WantedBy=multi-user.target UNIT ``` 启动: ```bash sudo systemctl daemon-reload sudo systemctl enable --now cockpit-backend sudo systemctl status cockpit-backend --no-pager ``` 日志查看: ```bash journalctl -u cockpit-backend -f ``` --- ## 2. 前端部署(Vite preview / 2099) 前端推荐构建后用 `vite preview` 在本机端口提供服务,再由 Nginx 反代。这样部署简单,但注意 Node 进程稳定性要交给 systemd 管理。 ### 2.1 构建环境变量(非常重要) 前端生产构建时需要 `VITE_API_BASE` 指向站点域名(同域走 Nginx `/api` 反代): ```bash export VITE_API_BASE="https://JessieGem.zeotaki.com" ``` ### 2.2 systemd 服务(frontend) 创建目录: ```bash sudo mkdir -p /opt/jessiegem-cockpit/frontend sudo chown -R cockpit:cockpit /opt/jessiegem-cockpit/frontend ``` 创建 `/etc/systemd/system/cockpit-frontend.service`: ```bash sudo tee /etc/systemd/system/cockpit-frontend.service >/dev/null <<'UNIT' [Unit] Description=Cockpit Frontend (Vite preview) After=network.target [Service] User=cockpit Group=cockpit WorkingDirectory=/opt/jessiegem-cockpit/frontend Environment=NODE_ENV=production Environment=HOST=127.0.0.1 Environment=PORT=2099 ExecStart=/usr/bin/npm run preview -- --host 127.0.0.1 --port 2099 --strictPort Restart=always RestartSec=2 [Install] WantedBy=multi-user.target UNIT ``` 启动: ```bash sudo systemctl daemon-reload sudo systemctl enable --now cockpit-frontend sudo systemctl status cockpit-frontend --no-pager ``` --- ## 3. Nginx 配置(JessieGem.zeotaki.com) 目标: - `/` -> `http://127.0.0.1:2099` - `/api/` -> `http://127.0.0.1:2088` 创建站点配置: ```bash sudo tee /etc/nginx/sites-available/jessiegem-cockpit.conf >/dev/null <<'NGINX' server { listen 80; server_name JessieGem.zeotaki.com; # 如果你使用 certbot,建议这里仅用于 http->https 跳转 location / { return 301 https://$host$request_uri; } } server { listen 443 ssl http2; server_name JessieGem.zeotaki.com; # 证书路径按你服务器实际情况填写(certbot 默认示例) ssl_certificate /etc/letsencrypt/live/JessieGem.zeotaki.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/JessieGem.zeotaki.com/privkey.pem; client_max_body_size 50m; # 前端 location / { proxy_pass http://127.0.0.1:2099; 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; } # 后端 API location /api/ { proxy_pass http://127.0.0.1:2088; 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; } } NGINX ``` 启用并检查: ```bash sudo ln -sf /etc/nginx/sites-available/jessiegem-cockpit.conf /etc/nginx/sites-enabled/jessiegem-cockpit.conf sudo nginx -t sudo systemctl reload nginx ``` 证书(如未配置): ```bash sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d JessieGem.zeotaki.com ``` --- ## 4. 手工发布流程(不使用 Jenkins) ### 4.1 拉取代码 在服务器上: ```bash cd /opt/jessiegem-cockpit sudo -u cockpit git clone <你的-gitea-仓库-url> repo ``` 后续更新: ```bash cd /opt/jessiegem-cockpit/repo sudo -u cockpit git pull ``` ### 4.2 构建并发布后端 ```bash cd /opt/jessiegem-cockpit/repo/backend sudo -u cockpit go build -o /opt/jessiegem-cockpit/backend/cockpit-server ./cmd/server sudo systemctl restart cockpit-backend ``` ### 4.3 构建并发布前端 ```bash cd /opt/jessiegem-cockpit/repo/frontend sudo -u cockpit npm ci sudo -u cockpit VITE_API_BASE="https://JessieGem.zeotaki.com" npm run build # vite preview 需要 dist,所以把 dist 与 package 相关文件同步到运行目录 sudo -u cockpit rsync -a --delete dist/ /opt/jessiegem-cockpit/frontend/dist/ sudo -u cockpit rsync -a package.json package-lock.json vite.config.ts /opt/jessiegem-cockpit/frontend/ cd /opt/jessiegem-cockpit/frontend sudo -u cockpit npm ci sudo systemctl restart cockpit-frontend ``` --- ## 5. Jenkins + Gitea 自动部署(推荐) ### 5.1 Jenkins 准备 在 Jenkins 配置以下内容: - 凭据 1:Gitea 访问令牌/账号(用于拉取仓库) - 凭据 2:SSH 私钥(用于从 Jenkins 服务器 SSH 到部署服务器) - 在 Gitea 仓库配置 Webhook -> Jenkins(push 触发构建) ### 5.2 服务器准备(用于 Jenkins 部署) 保证 Jenkins 可以 SSH 到服务器,并且服务器上已创建: - `/opt/jessiegem-cockpit/backend` - `/opt/jessiegem-cockpit/frontend` - systemd 服务:`cockpit-backend`、`cockpit-frontend` ### 5.3 Jenkinsfile 示例(Pipeline) 把下面内容保存为仓库根目录 `Jenkinsfile`(或在 Jenkins Pipeline 脚本里粘贴): ```groovy pipeline { agent any environment { DEPLOY_HOST = '你的服务器IP或域名' DEPLOY_USER = 'root' // 或具备 sudo 权限的用户 VITE_API_BASE = 'https://JessieGem.zeotaki.com' } stages { stage('Checkout') { steps { checkout scm } } stage('Build Backend') { steps { dir('backend') { sh 'go version' sh 'go build -o cockpit-server ./cmd/server' } } } stage('Build Frontend') { steps { dir('frontend') { sh 'node -v && npm -v' sh 'npm ci' sh "VITE_API_BASE=${VITE_API_BASE} npm run build" } } } stage('Deploy') { steps { sshagent(credentials: ['你的-jenkins-ssh-credential-id']) { sh ''' set -e rsync -avz --delete backend/cockpit-server ${DEPLOY_USER}@${DEPLOY_HOST}:/opt/jessiegem-cockpit/backend/cockpit-server rsync -avz --delete frontend/dist/ ${DEPLOY_USER}@${DEPLOY_HOST}:/opt/jessiegem-cockpit/frontend/dist/ rsync -avz frontend/package.json frontend/package-lock.json ${DEPLOY_USER}@${DEPLOY_HOST}:/opt/jessiegem-cockpit/frontend/ ssh ${DEPLOY_USER}@${DEPLOY_HOST} "cd /opt/jessiegem-cockpit/frontend && npm ci && sudo systemctl restart cockpit-frontend" ssh ${DEPLOY_USER}@${DEPLOY_HOST} "sudo systemctl restart cockpit-backend" ''' } } } } } ``` > 如果 Jenkins 机器不是 Linux(例如 Windows),上面 `sh` 需要改成对应的 `bat/powershell`,或者让 Jenkins agent 跑在 Linux 节点上。 --- ## 6. 验收清单 ### 6.1 服务状态 ```bash sudo systemctl status cockpit-backend --no-pager sudo systemctl status cockpit-frontend --no-pager ``` ### 6.2 端口监听(应仅 127.0.0.1) ```bash sudo ss -lntp | egrep '2088|2099' ``` ### 6.3 站点验证 - 打开:`https://JessieGem.zeotaki.com` - 登录:`admin / admin123` - Network 面板确认 API 请求是:`https://JessieGem.zeotaki.com/api/...`(同域)