
如果你还在用 FTP 手动上传网站代码,每次更新都要逐个文件比对、传错一个版本就可能让线上页面白屏半天。本文教你如何在一台 VPS(虚拟专用服务器)上部署 Gitea,把代码仓库握在自己手里,并通过 WebHook(网络钩子)实现代码推送后网站自动更新。整个过程不需要昂贵的代码托管服务,一台 2 核 4G 的服务器就够用,全文命令都可以直接复制执行。
我们会按照「安装 Gitea → 创建仓库 → 配置自动发布钩子 → 安全加固」的顺序展开,每个步骤都附带验证方法,你可以在 30 分钟内跑通第一条自动发布链路。
一、为什么选择 Gitea 自建 Git 服务器
Gitea 是一个用 Go 语言编写的轻量级 Git 托管服务,单个二进制文件加上一个 SQLite(嵌入式数据库)就能运行,对服务器配置的要求非常低。与大型托管平台相比,自建的核心价值有三点:
- 数据完全本地:仓库、提交历史、成员权限都在你自己的服务器上,不依赖第三方平台的存续政策。
- 定制发布流程:可以在仓库层面直接挂发布钩子,推送即上线,省去手动部署环节。
- 成本可控:一台入门级 VPS(虚拟专用服务器)年费通常在几十到一二百元区间,远低于按人头收费的商业托管方案。
当然它也有局限:没有全球化的 CDN(内容分发网络)加速克隆、官方支持有限。如果你只是个人站长或十几人以内的小团队,这些局限基本感知不到;如果是百人以上研发团队,建议再评估。
二、部署 Gitea:从下载到首次登录
1. 准备环境
以 Ubuntu 22.04 / Debian 12 为例,先安装 Git 和数据库。小规模使用 SQLite 就够了,团队协作建议 MySQL(关系型数据库):
sudo apt update && sudo apt install -y git
sudo adduser --system --shell /bin/bash --gecos 'Git Service' --group --disabled-password --home /home/git git
2. 下载并安装 Gitea
wget -O gitea https://dl.gitea.com/gitea/1.22/gitea-1.22-linux-amd64
chmod +x gitea
sudo mv gitea /usr/local/bin/gitea
gitea --version
看到版本号输出说明二进制可用。建议部署前到 Gitea 官网确认当前稳定版本号,把上面的 1.22 替换成最新稳定版。
3. 创建目录并注册 systemd 服务
sudo mkdir -p /etc/gitea /var/lib/gitea/{custom,data,log}
sudo chown -R git:git /var/lib/gitea /etc/gitea
sudo chmod 750 /var/lib/gitea
写入服务单元文件 /etc/systemd/system/gitea.service:
[Unit]
Description=Gitea
After=network.target
[Service]
User=git
Group=git
WorkingDirectory=/var/lib/gitea
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
Restart=always
[Install]
WantedBy=multi-user.target
启动并设置开机自启:
sudo systemctl enable --now gitea
sudo systemctl status gitea
4. 完成网页初始化
浏览器访问 http://服务器IP:3000,在安装向导中选择 SQLite,站点名称填你的品牌名,管理员账号密码务必使用强密码。安装完成后第一次登录,先到「站点管理 → 用户管理」关闭开放注册,避免陌生人占用你的服务器资源。
验证安装是否成功,可以在服务器上执行:
curl -I http://127.0.0.1:3000
返回 200 即为正常。为了安全,建议后续用 Nginx(反向代理服务器)把 3000 端口转发到 80/443,并配上 SSL(安全传输协议)证书,这一步网上教程很多,不再展开。
三、创建网站代码仓库
登录 Gitea 后点右上角「+」新建仓库,名称建议与网站目录同名(例如 my-site),可见性选「私有」。然后在本地开发机上:
git init
git remote add origin git@你的服务器IP:git/my-site.git
git add .
git commit -m "init site"
git push -u origin main
推送前记得先把本机的 SSH 公钥(用 ssh-keygen 生成)添加到 Gitea 的「设置 → SSH / GPG 密钥」里,否则推送会要求密码。
四、配置自动发布钩子:推送即上线
这是本文的核心部分。思路是:网站所在的同一台服务器(或内网另一台)上放一个检出目录,Gitea 在收到 push 时触发 WebHook,调用本地脚本执行 git pull。
1. 准备网站检出目录
sudo mkdir -p /var/www/my-site
cd /var/www/my-site
sudo git clone /var/lib/gitea/data/repositories/git/my-site.git .
sudo chown -R www-data:www-data /var/www/my-site
2. 编写发布脚本
新建 /var/www/deploy-my-site.sh:
#!/bin/bash
set -e
cd /var/www/my-site
sudo -u www-data git fetch origin main
sudo -u www-data git reset --hard origin/main
echo "$(date '+%F %T') deployed" >> /var/log/my-site-deploy.log
赋权并测试:
sudo chmod +x /var/www/deploy-my-site.sh
sudo /var/www/deploy-my-site.sh && tail -1 /var/log/my-site-deploy.log
日志里出现刚生成的时间戳,说明脚本本身可用。
3. 在 Gitea 中配置 WebHook
进入仓库「设置 → Web 钩子 → 添加 Web 钩子」,因为 Gitea 和网站在同一台服务器,最简单的方式是用 Gitea 自带的本地钩子:直接在服务器的仓库裸目录里放 post-receive 钩子:
sudo -u git tee /var/lib/gitea/data/repositories/git/my-site.git/hooks/post-receive <<'EOF'
#!/bin/bash
/var/www/deploy-my-site.sh
EOF
sudo chmod +x /var/lib/gitea/data/repositories/git/my-site.git/hooks/post-receive
如果网站和 Gitea 不在同一台机器,则用 Gitea 界面里的 WebHook(网络钩子)指向网站服务器上的一个接收接口,再由接口触发上面的发布脚本。
4. 验证自动发布
在本地改一个文件提交推送:
echo "" >> index.html
git commit -am "deploy test" && git push
几秒后刷新网站页面,如果新增的注释出现了,整条「提交 → 推送 → 自动上线」链路就跑通了。排查问题时先看 /var/log/my-site-deploy.log,再看 Gitea 仓库页面的「运行状态」。

五、安全加固与运维建议
自动发布意味着「能推代码的人都能改线上网站」,权限收敛比功能本身更重要。落地时建议把握这几条:
- 最小权限:Gitea 服务用独立的
git系统账号运行,网站目录归www-data,发布脚本里用sudo -u明确切换身份,不混用 root。 - SSH 密钥管理:给每个开发者单独发账号和密钥,人员离职当天在 Gitea 后台移除其密钥,而不是共用一把钥匙。
- 备份策略:每天备份
/var/lib/gitea/data和数据库文件到异地或另一块磁盘。Git 仓库本身有完整历史,恢复点越新,误操作损失越小。 - 钩子日志:发布脚本所有输出写入日志文件并保留 30 天,出了问题能回放每次发布改了什么。
服务器本身的稳定性也直接影响这条发布链路。如果你不想把时间花在系统运维上, Hostease 的 VPS 主机 提供 NVMe 磁盘和独立资源保障,跑 Gitea 这类自建服务有比较从容的性能余量;需要了解服务器日常维护,也可以参考站内的服务器栏目文章。

六、常见问题排查
推送后网站没更新怎么办
按顺序检查三层:先看 /var/log/my-site-deploy.log 有没有新记录——没有说明钩子没触发,检查 post-receive 文件是否有执行权限;有记录但页面没变,说明是检出目录或缓存问题,手动执行一次发布脚本并清理页面缓存(如果你用了 WordPress 或其他带缓存的建站程序)。
钩子执行报权限错误
最常见的错误是 fatal: unable to access ... Permission denied。原因是钩子以 git 用户运行,但网站目录归 www-data。解决办法是给 git 用户添加免密 sudo 规则,只允许执行这一个发布脚本:
sudo visudo -f /etc/sudoers.d/gitea-deploy
# 写入:git ALL=(www-data) NOPASSWD: /var/www/deploy-my-site.sh
只放行一条脚本,不要给 git 用户开放全部 sudo 权限。
如何回滚一次失败的发布
Git 的优势在这里体现:在线上检出目录执行 git log --oneline -5 找到上一个正常版本,然后 sudo -u www-data git reset --hard 那个版本号,页面立刻回到发布前状态。事后在本地修正代码再正常推送即可。这也是我们建议每次发布都写日志的原因——你能精确知道要回到哪个时间点。
总结
回顾整条链路:Gitea 负责存代码和管权限,post-receive 钩子负责触发发布脚本,脚本用 git 拉取最新版本并切换身份部署——三步之后,你发布一个页面更新只需要 git push 一条命令。总结下来,关键在于三件事:权限分离(git 与 www-data 各司其职)、每日备份、钩子日志留痕。
如果你正在挑选适合跑 Gitea 的服务器,可以考虑先从 Hostease VPS 主机起步,按需升级配置;想进一步了解网站性能与部署相关的实践,也可以阅读站内网站优化栏目的延伸内容。把发布流程自动化之后,你省下来的每一次手动上传,都是留给业务的时间。