如果你已经把博客放在 Hugo + Congo 上,又不想在本地长期维护一整套构建环境,那么最省心的一条路,通常就是:
GitHub -> Vercel -> Cloudflare
这篇教程会把整条链路一次写完整:
- 本地仓库推到 GitHub
- Vercel 自动拉取并构建 Hugo + Congo
- 自定义域名接到 Cloudflare
apex + www + HTTPS一次配好
适用场景 #
这篇文章更适合下面这类情况:
- 你已经有一个 Hugo 博客
- 主题用了
Congo - 你希望以后只要
git push就自动部署 - 你的域名托管在
Cloudflare
前置准备 #
开始前先确认这些东西都已经有了:
- 一个 GitHub 账号
- 一个 Vercel 账号
- 一个 Cloudflare 账号和一个可用域名
- 一个已经能正常生成页面的
Hugo + Congo仓库 - 仓库根目录至少有
content/、config/_default/、go.mod、build.sh、vercel.json
如果你和我现在这套一样,把构建逻辑放进 build.sh,那么 vercel.json 可以保持成下面这样:
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"framework": null,
"buildCommand": "chmod a+x build.sh && ./build.sh",
"outputDirectory": "public"
}
按我在 2026-03-19 查的官方文档,Vercel 本身支持 Hugo,简单项目通常也能自动识别。
但像 Congo + Hugo Modules + 自定义 build.sh 这种组合,显式把构建命令和输出目录写清楚会更稳。
build.sh 里至少要负责这几件事:
- 安装本次构建需要的
Go和Hugo - 处理 shallow clone,避免模块拉取出问题
- 更新或拉取
Congo模块 - 最后执行
hugo --gc --minify
第一步:准备仓库并首次推送 #
先在 GitHub 创建一个空仓库,然后在本地仓库执行下面这几步:
git init
git add .
git commit -m "init blog"
git branch -M main
git remote add origin git@github.com:yourname/your-blog.git
git push -u origin main
这一步的重点不是命令本身,而是确认你的博客代码已经完整进入 GitHub,并且默认分支是 main。
推送完成后,建议回 GitHub 网页看一眼,至少确认这些文件和目录都在:
content/config/_default/go.modbuild.shvercel.json
第二步:在 Vercel 导入项目 #
打开 Vercel 后,按下面的顺序操作:
Add New -> Project- 选择刚才那个 GitHub 仓库
- Framework 选
Other - Build Command 填
chmod a+x build.sh && ./build.sh - Output Directory 填
public - 点
Deploy
如果你的 Hugo 项目完全走官方默认方式,Vercel 有时会直接识别出来。
但只要你用了自定义 build.sh,这里就尽量不要省,直接把构建参数写死。
第三步:验证首次部署 #
首次部署完成后,先不要急着去绑域名,先看这几件事:
.vercel.app地址能正常打开- 首页、文章页、分类页渲染都正常
- 重新 push 一次后会触发新部署
- 非
main分支能生成 Preview 链接
后续日常更新其实非常简单,流程基本就是:
git add .
git commit -m "publish new post"
git push origin main
推送完成之后:
main分支通常会更新生产环境- 其他分支会生成 Preview 链接
第四步:在 Vercel 里添加自定义域名 #
进入项目后打开:
Settings -> Domains
建议一次把这两个都加上:
example.comwww.example.com
如果这个域名之前在别的 Vercel 账号里用过,面板可能会要求你先做 TXT 验证。
这时候按面板提示加验证记录就行,而且如果有多个域名要验证,最好按 Vercel 的提示一条一条来。
这里还有一个取舍:
- 如果你没有强偏好,按 Vercel 官方当前建议,把
www设为主域名会更稳 - 如果你更喜欢裸域,也可以把
example.com设成主域名,只是这不是官方首选
第五步:到 Cloudflare 配 DNS #
回到 Cloudflare 的 DNS 页面,把 Vercel 面板要求的记录填进去。
比较常见的写法是:
Type Name Value
A @ 76.76.21.21
CNAME www cname.vercel-dns-0.com
TXT _vercel vc-domain-verify=...
这里有两个细节最重要:
TXT记录只在 Vercel 要求验证所有权时才需要加- 真正应该填什么值,以 Vercel 面板给你的推荐记录为准
按目前官方文档,76.76.21.21 和 cname.vercel-dns-0.com 是通用值。
但项目实际也可能给你一个专属的 CNAME 目标,例如 xxxx.vercel-dns-017.com。只要面板给的值不同,就优先听面板。
如果你开了 Cloudflare 代理,验证阶段一旦卡住,可以先临时切到 DNS only,等 Vercel 状态正常后再决定要不要开回去。
第六步:回到 Vercel 看验证和 HTTPS #
DNS 改完之后,回到 Vercel 的 Domains 页面刷新状态,正常会经历:
PendingVerifyingValid Configuration
当域名状态变成有效后,Vercel 会继续给你配 HTTPS。
只要一切正常,过一会儿就能直接用 https:// 打开了。
这一步顺手再检查三件事:
- 主域名是不是你想要的那个
- 另一个域名有没有正确跳转过去
- 证书状态是不是已经激活
如果你没特别需求,我会建议把 www 设为主域名,再让裸域跳转过去。
这是 Vercel 目前的官方推荐,因为 www 走 CNAME,弹性和容错会更好一些。
第七步:日常维护怎么做 #
前面这套跑通之后,后面的维护就很简单了:
- 写文章或改模板
- 提交到 Git
- push 到 GitHub
- 等 Vercel 自动构建
如果你想稳一点,我建议保留这几个习惯:
- 每次只提交一类改动,文章和模板尽量不要混在一个 commit 里
- 先看 Preview,再决定要不要合到
main - 新文章的
date不要写到未来 - 如果
build.sh里会自动更新Congo,就接受“上游更新后部署结果也可能变化”这件事
常见问题 #
Vercel 导入后直接构建失败 #
优先检查这些地方:
build.sh有没有执行权限,或者构建命令里有没有先chmod a+xgo.mod是否存在,Congo模块是不是能正常拉到- 仓库是不是 shallow clone,导致模块解析或 Git 信息不完整
Preview 链接能开,但绝对地址指到正式站 #
这种情况通常是 baseURL 处理得不对。
如果你在 build.sh 里手动传了 --baseURL,记得区分:
- 生产环境
- Preview 环境
不然 Preview 里的 canonical、RSS、跳转地址可能都会指回正式域名。
域名状态一直 Pending 或 Invalid #
先排查:
- 记录类型对不对
@、www、_vercel这些主机名有没有写错- Cloudflare 里有没有旧记录冲突
- 你填的是不是 Vercel 面板当前推荐值
证书迟迟不签发 #
常见排查顺序是:
- 先确认域名在 Vercel 里已经是
Valid Configuration - 检查是否有干扰签发的
CAA记录 - 如果验证过程不顺,先把 Cloudflare 代理临时切到
DNS only
小结 #
对个人博客来说,GitHub + Vercel + Cloudflare + Hugo + Congo 这套组合最大的优点不是“有多炫”,而是顺手:
- 写文章像写代码一样可追踪
git push就是部署- Preview 和生产环境分得很清楚
- 域名、HTTPS、后续扩展都比较省心
前面这套走通之后,你的博客就已经是一个比较完整的公开站点了。
后面如果还要继续折腾,再去补评论系统、统计脚本、邮件推送或者缓存规则,会轻松很多。
参考 #
- Hugo: https://gohugo.io/host-and-deploy/host-on-vercel/
- Vercel custom domain docs: https://vercel.com/docs/domains/set-up-custom-domain
- Vercel domain redirect docs: https://vercel.com/docs/domains/working-with-domains/deploying-and-redirecting