如何使用 Upptime 免费搭建自己的状态站点
把监控这件事整个儿搬进 GitHub 仓库——Actions 当探针、仓库当数据库、Pages 当 CDN、Issues 当事件簿。零服务器,零月费,愣是凑出一个能看能查能留痕的状态站。说是黑魔法也好,说是穷人的智慧也罢,反正它跑起来了。
背景
运维一个由十几个对外服务凑起来的小型产品矩阵时,"到底通不通"这事常常变成了口头禅。客户反馈说访问不了,你 ssh 上去curl一遍发现是好的;过几分钟它又挂了,可你这次没盯到。商业监控(Pingdom、UptimeRobot 的高级档、Datadog)当然能解决,只是要么按站点收费,要么按请求次数收费,对一个独立开发者来说,成本和心智负担都不太划算而已。
更关键的是,状态页本身也得让用户能查。理想的样子是:一个域名(比如status.hagicode.com),实时展示每个服务的可用率、响应时间曲线、历史事件,故障时还能自动留痕、自动通知。传统做法要凑齐四件套——跑 cron 的服务器、存历史数据的数据库、前端站点、CDN。这四样一摆开,运维成本立刻就盖过了被监控的服务本身,毕竟杀鸡用了牛刀,鸡还嫌挤。
为了解决这些痛点,我们做了一个决定:整个监控方案直接搬到 GitHub 上。这个决定带来的变化,可能比你想的还要大——稍后我再慢慢说。
关于 HagiCode
本文分享的方案,来自我们在 HagiCode 项目里摸爬滚打的经验。HagiCode 是个 AI 代码助手项目,对外吐出了网页、文档站、下载端点等十几个公共服务,背后由 HagiCode-org/site 这个主仓库驱动着。这些站点必须稳定可用,所以状态监控对我们不是可选项,而是刚需。下面这套 Upptime 方案,正是 HagiCode 实际生产环境在用的——不是我编的。
分析:Upptime 到底是怎么跑起来的
Upptime 的本质,其实是一份 GitHub 仓库模板,加上六个由模板生成的 workflow。理解它的关键,就是看清楚"谁在什么时候、调用谁、产出什么落到哪里"。把它拆开了看,也就不那么神秘了。
数据流:一个配置文件驱动一切
整个系统,就绕着.upptimerc.yml这一个声明式配置文件转。HagiCode 的实际配置结构,大概是这样:
owner:HagiCode-orgrepo:upptimesites:-name:HagiCode Websiteurl:https://hagicode.com-name:HagiCode Docsurl:https://docs.hagicode.com-name:Server Package Indexurl:https://index.hagicode.com/server/index.json# ... 共 14 个站点status-website:cname:status.hagicode.comlogoUrl:https://raw.githubusercontent.com/HagiCode-org/upptime/master/assets/upptime-icon.svgname:HagiCode StatusintroTitle:"**HagiCode Status**"introMessage:Real-time availability tracking for public HagiCode websites and download endpoints.navbar:-title:Statushref:/-title:GitHubhref:https://github.com/$OWNER/$REPO这里有两点值得拎出来说。第一,sites既能监控网页(返回 HTML),也能监控纯 JSON 端点(比如index.json),Upptime 只看 HTTP 状态码和响应时间,不做内容校验。第二,cname指向status.hagicode.com,这要求你得拥有该域名,并把 DNS 指向 GitHub Pages——毕竟白嫖归白嫖,域名还是要自己出的。
六个 workflow 的分工
.github/workflows/下所有文件顶部都有一行警告Do not edit this file directly!——它们由模板每周自动更新,你只改.upptimerc.yml就好。每个 workflow 用 cron 触发,调用同一个 actionupptime/uptime-monitor@v1.42.6的不同子命令,分工明确,倒也省心:
| Workflow | cron | 命令 | 作用 |
|---|---|---|---|
uptime.yml | */5 * * * * | update | 每 5 分钟探活,写history/*.yml |
response-time.yml | — | response-time | 计算响应时间统计 |
graphs.yml | — | graphs | 生成日/周/月/年 PNG 曲线 |
summary.yml | — | summary | 更新 README 里的状态表 |
site.yml | 0 1 * * * | site | 每日构建静态站,部署到 Pages |
update-template.yml | 0 0 * * * | — | 每周同步上游模板 |
uptime.yml的核心片段,展示了"探针"是怎么跑的:
on:schedule:-cron:"*/5 * * * *"jobs:release:runs-on:ubuntu-lateststeps:-uses:actions/checkout@v4with:token:${{secrets.GH_PAT||github.token}}-name:Check endpoint statususes:upptime/uptime-monitor@v1.42.6with:command:"update"env:GH_PAT:${{secrets.GH_PAT||github.token}}SECRETS_CONTEXT:${{toJson(secrets)}}site.yml则多了一步,用peaceiris/actions-gh-pages@v4把构建产物推到gh-pages分支:
-uses:peaceiris/actions-gh-pages@v4with:github_token:${{secrets.GH_PAT||github.token}}publish_dir:"site/status-page/__sapper__/export/"user_name:"Upptime Bot"user_email:"73812536+upptime-bot@users.noreply.github.com"数据落盘:文件即数据库
监控结果不存数据库,而是直接以文件形式 commit 回仓库。这听起来有点野,但用起来倒也踏实。每个站点有三类产物。
状态快照history/{slug}.yml,例如history/hagi-code-website.yml:
url:https://hagicode.comstatus:upcode:200responseTime:96lastUpdated:2026-06-17T00:22:34.485ZstartTime:2026-03-24T10:07:32.531Zshields.io 的 endpoint 徽章数据源api/{slug}/response-time.json、uptime.json:
{"schemaVersion":1,"label":"response time","message":"739 ms","color":"yellow"}以及响应时间曲线图graphs/{slug}/response-time-{day,week,month,year}.png。
这套"文件即数据库"的取舍,其实想得挺清楚:写多读少、规模可控(每个站点一天约 288 条采样,存增量而非全量)、天然带版本历史、零基础设施。代价嘛,就是仓库会持续长大,偶尔得回头关心一下它而已。
事件与通知:Issues 当事件簿
故障留痕靠 GitHub Issues,配合仓库自带的两个模板:.github/ISSUE_TEMPLATE/bug_report.md(用户报障)和maintainance-event.md(计划性维护)。维护模板用 frontmatter 表达时间窗:
<!-- start: 2021-08-24T13:00:00.220Z end: 2021-08-24T14:00:00.220Z expectedDown: google, hacker-news -->Upptime 会解析这些 Issue,把"正在维护"和"已发生事件"渲染到状态页和 README 上。通知则靠 Issue 自身的 watch 机制,外加可配置的 webhook、Slack、Telegram(在.upptimerc.yml顶部声明notifications,HagiCode 的示例仓库目前没启用,毕竟能少一样是一样)。
解决:五步复刻一套状态站
复刻一套 HagiCode 同款状态站,从零到上线,一共五步。说是五步,其实每步都不长,慢慢来就是。
第 1 步:从模板创建仓库
别git clone后改,直接用 GitHub 的 “Use this template” 创建仓库(例如your-org/upptime)。模板已经内置了全部 workflow、Issue 模板和静态站点骨架。clone 到本地后,唯一需要手改的就是.upptimerc.yml——其它的,留着别动就好。
第 2 步:编辑.upptimerc.yml
把owner/repo改成你的,sites列出要监控的地址,status-website配置站点。最小可用版本大概是这样:
owner:your-orgrepo:upptimesites:-name:Main Siteurl:https://example.com-name:API Healthurl:https://api.example.com/healthexpectedStatusCodes:-200status-website:cname:status.example.com# 没有域名可删掉,用默认的 your-org.github.io/upptimename:Example StatusintroTitle:"**Example Status**"introMessage:服务可用性实时监控navbar:-title:Statushref:/-title:GitHubhref:https://github.com/$OWNER/$REPO进阶项:expectedStatusCodes限定可接受的状态码(默认 200-399);headers自定义请求头(用于需要鉴权的端点);maxResponseTime标记慢响应。这些都看你需要,按需取用罢了。
第 3 步:配置 Secret 与权限
workflow 默认用${{ secrets.GH_PAT || github.token }}。github.token能跑通基本流程,但有两个限制会咬人:
- 默认 token 触发的 workflow 不会再触发下游 workflow(防止循环),导致"探活 → 建 Issue → 通知"这条链断在中间。
- 跨仓库操作(比如多组织)权限不足。
推荐新建一个 PAT(需要repo+workflow权限),存为仓库 SecretGH_PAT。update-template.yml里专门有一段检查:没有GH_PAT就跳过模板自动更新并打印 warning,所以这个 secret 不只是可选项,更是省心的关键。
第 4 步:开启 GitHub Pages
仓库 Settings → Pages → Source 选Deploy from a branch,分支选gh-pages、目录/root。site.yml每天凌晨 1 点会自动把构建产物推到这个分支。如果配了cname,再到你的 DNS 服务商加一条 CNAME 记录指向your-org.github.io。
第一次手动触发一下也好:Actions 页面找到 “Static Site CI” → Run workflow,不用傻等定时任务,毕竟能早一秒看到结果,心里就早一秒踏实。
第 5 步:验证与维护
push 配置后,去 Actions 看 “Uptime CI” 是否每 5 分钟跑一次、history/是否开始出现*.yml文件。状态页地址就是https://<your-org>.github.io/upptime/或你的自定义域名。后续加站点、改域名,只动.upptimerc.yml一个文件就行,workflow 全自动。HagiCode 这一年多就靠这套机制维护 14 个端点的可用性,基本没怎么操心过。
实践:踩过的坑都替你趟过了
下面这几条,是 HagiCode 实际运行中积累下来的经验,写出来也好让你少走点弯路。
实践 1:监控粒度选择
HagiCode 把网页(https://hagicode.com)和纯数据端点(https://index.hagicode.com/server/index.json)放在同一个sites列表里。对 JSON 端点,Upptime 会请求并解析 HTTP 状态码,但不校验内容结构。如果你需要"返回 200 但内容错误"这种深度检查,得用expectedStatusCodes加上外部探针来补,Upptime 本身只做黑盒 HTTP 检查——它只看脸色,不读心事。
实践 2:响应时间徽章的妙用
api/{slug}/response-time.json是 shields.io 的 endpoint 徽章 数据源。HagiCode 的 README 里大量引用这种 URL:
https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2FHagiCode-org%2Fupptime%2FHEAD%2Fapi%2Fhagi-code-website%2Fresponse-time.json这样一来,你就能在任何 Markdown(项目 README、博客、第三方页面)里嵌入实时响应时间徽章,颜色由message里的数值和color字段驱动。注意用HEAD而不是master/main引用 raw 文件,能避免分支改名后大面积失效——细节之处,藏着安稳。
实践 3:仓库体积控制
每 5 分钟一次采样,一年下来history/会累积出可观的体积。Upptime 用增量 YAML 而非全量日志,相对克制,但仍建议定期看一眼仓库大小。如果某个站点监控价值下降了,从sites移除即可,对应的历史文件也可以手动清理掉,毕竟舍不得删,仓库迟早会臃肿给你看。
实践 4:维护事件的真实用法
maintainance-event.md不是摆设。计划发版前,按模板开一个 Issue,填好start/end/expectedDown,Upptime 会把这段时间内的对应站点标记为"计划内维护",不计入可用率统计,避免一次正常发版把全年 SLA 拉低。HagiCode 的expectedDown支持逗号分隔的站点名列表,与sites[].name一一对应。
实践 5:模板更新与自定义的边界
所有.github/workflows/*.yml顶部的Do not edit this file directly!,不是吓唬人的。update-template.yml每周会用上游模板覆盖这些文件。需要自定义行为时,正确做法是在.upptimerc.yml里用官方支持的配置项(如skipTopics、customStatusWebsite、runnerSettings),而不是去改 workflow。实在要改 workflow,要么关掉update-template.yml,要么 fork 出来自己维护模板——后者会失去无痛升级,得失之间,自己掂量罢了。
实践 6:免费额度的现实约束
GitHub Actions 对公开仓库免费、不限时长,Upptime 设计上正是利用了这一点。私有仓库每月有 2000 分钟免费额度,而uptime.yml每 5 分钟跑一次、每次约 1 分钟,单这一项一个月就大概 8640 分钟,会超额。所以 Upptime 仓库必须是 public,这是"免费"两个字的前提——别图保密开成 private,然后收到账单,那就尴尬了。
总结
回到开头那个问题:监控一堆对外服务,到底有没有便宜的解法?HagiCode 的答案是——有,而且便宜得让你怀疑这是不是真的。Upptime 把监控拆成了四个 GitHub 原生组件:
- 探针 = GitHub Actions 的 cron
- 数据库 = 仓库里的 YAML/JSON 文件
- CDN = GitHub Pages
- 事件簿 = GitHub Issues
你得到的是:实时可用率、响应时间曲线、历史事件、可用率徽章、自定义域名、自动通知,全部零服务器、零月费。代价是要保持仓库公开,以及偶尔关心一下仓库体积。其实这点代价,比起手搓一套监控,已经轻得太多。
这套方案之所以能跑通,背后是 GitHub 生态对开源项目的诚意补贴。如果你也在维护一个多站点的小型产品矩阵,强烈建议花一个下午把它搭起来,比手搓监控省心太多。
参考资料
- Upptime 官方仓库
- shields.io endpoint 徽章文档
- GitHub Actions 定时任务文档
- HagiCode 状态站实例
总结
围绕“如何使用 Upptime 免费搭建自己的状态站点”,更稳妥的推进方式是先把关键配置、依赖边界和落地路径逐步跑通,再补齐优化细节。
当目标、步骤和验收点都明确之后,这类方案通常就能更顺畅地进入实际交付。
原文与版权说明
感谢您的阅读,如果您觉得本文有用,欢迎点赞、收藏和分享支持。
本内容采用人工智能辅助协作,最终内容由作者审核并确认。
- 本文作者: newbe36524
- 原文链接: https://docs.hagicode.com/go?platform=csdn&target=%2Fblog%2F2026-06-18-how-to-use-upptime-for-free-status-page%2F
- 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!