Healthchecks v4.4 Ubuntu 22.04 安装指南
在 Ubuntu 22.04 上从零源码安装 Healthchecks v4.4 心跳监控平台:Python 3.12 环境、PostgreSQL 16 建库、gunicorn 启动、systemd 托管、登录验证与卸载,全程命令实测。
Healthchecks v4.4 Ubuntu 22.04 安装指南
目标:在 Ubuntu 22.04 服务器上从零完成 Healthchecks v4.4 心跳监控平台的源码安装——Python 3.12 环境、PostgreSQL 16 建库、初始化数据、gunicorn 启动、systemd 托管、登录验证与卸载清理。已在 Ubuntu 22.04.5 LTS(x86_64)实测通过。
一、环境信息
本文所有命令在以下环境实测执行,回显均为真实输出:
- 操作系统:Ubuntu 22.04.5 LTS(Jammy Jellyfish),x86_64
- Healthchecks:v4.4(官方 GitHub tag
v4.4,2026-08-31 发布的最新 stable) - Python:3.12.15(deadsnakes PPA 安装,Ubuntu 22.04 自带 3.10 不满足要求)
- 数据库:PostgreSQL 16.15(PGDG 官方仓库安装;Ubuntu 22.04 仓库自带的 14.24 不被支持)
- 应用服务器:gunicorn 26.2.0
- 关键依赖:Django 6.1、psycopg 3.3.4、pycurl 7.47.0、whitenoise 6.12.0、aiosmtpd 1.4.6
- 安装路径:
/opt/healthchecks,虚拟环境:/opt/venv - 数据库:库名
hc、用户hc、密码q1w2e3r4、端口5433 - 管理账号:
admin@example.org/q1w2e3r4 - 服务监听:
0.0.0.0:8000,systemd 服务healthchecks-web、healthchecks-sendalerts
二、软件概览与工作原理
Healthchecks 是一个用 Python/Django 编写的开源心跳(heartbeat)监控服务:你的 cron 作业、备份脚本、定时任务在每次运行结束时向 Healthchecks 发一个 HTTP 请求(称为 ping);如果 Healthchecks 在约定时间内没有收到 ping,就判定任务失败,并通过邮件、Webhook、Slack、Telegram 等渠道发出告警。它监控的是"该来的信号没来",与 Nagios/Prometheus 那类"主动探测目标是否异常"的监控互补。
💡 技术拓展:定时任务监控常见有三类思路——
思路 原理 代表产品 适用场景 心跳/死信监控 任务主动上报"我跑完了",超时未上报则告警 Healthchecks、Cronitor、Dead Man's Snitch cron/备份/ETL 作业静默失败的兜底 主动探测 监控端周期性探测目标端口/URL Nagios、Uptime Kuma、Zabbix 服务可用性、网络连通性 日志匹配 分析任务日志关键字判断成败 ELK + ElastAlert、Grafana Loki 已有集中日志的场景 本文选用 Healthchecks(心跳思路),理由:cron 作业"跑失败了但没报错/直接没跑"这类静默故障只有心跳能兜住,且它单进程轻量、部署门槛低。
核心概念只有三个:
- Check(检查项):对应一个被监控的定时任务,有唯一 UUID 与 ping URL;
- Ping:任务向 ping URL 发的一次请求,可带成功(默认)/失败(
/fail)/开始(/start)语义; - Period 与 Grace Time:预期上报周期与宽限期,两者都超时后 Check 进入
down状态并触发告警。
三、前置条件与版本选型
3.1 版本选型说明
Healthchecks 不在 PyPI 发布官方包(PyPI 上的 hc 是同名无关项目),自托管有两种主流交付形态:源码安装(本文)与 Docker 官方镜像(见《Healthchecks v4.4 Docker Compose 部署指南》)。版本以 GitHub Releases 的最新 stable 为准,查询方式:
curl -s https://api.github.com/repos/healthchecks/healthchecks/releases?per_page=5 | grep -E '"tag_name"|"prerelease"'
实测输出(节选):
"tag_name": "v4.4",
"prerelease": false,
"tag_name": "v4.3",
"prerelease": false,
"tag_name": "v4.2",
"prerelease": false,
v4.4 与 Ubuntu 22.04 默认软件源的关键版本对照:
| 组件 | Healthchecks v4.4 要求 | Ubuntu 22.04 默认源 | 结论 |
|---|---|---|---|
| Python | Django 6.1 要求 ≥ 3.12 | 3.10.12 | 需 deadsnakes PPA 装 3.12 |
| PostgreSQL | ≥ 15(Django 6.1 硬性检查) | 14.24 | 需 PGDG 仓库装 16 |
| pip/venv | 标准即可 | 可用 | 直接使用 |
| 编译器 | gcc/make(编译 psycopg、pycurl) | gcc 11.4 | apt install build-essential |
关键差异在于:v4.4 的依赖 Django[argon2]==6.1 只支持 Python 3.12+,且 Django 6.1 连接数据库时会检查服务端版本(低于 15 直接抛 NotSupportedError)。这两项都绕不过,必须按上表升级。
3.2 前置条件
- 一台 Ubuntu 22.04 服务器,拥有 root 或 sudo 权限;
- 服务器可访问外网(apt、pip、GitHub 下载);
- 已放行 8000 端口(或反代端口)供浏览器访问。
四、方案 A:源码安装 + PostgreSQL 16(推荐)
本章是完整 0→1 主线:系统依赖 → Python 3.12 → 下载源码 → 虚拟环境装依赖 → 建库 → 初始化 → 建管理员 → 启动验证 → systemd 托管。
4.1 安装系统依赖
先更新索引并安装编译工具链、PostgreSQL 客户端头文件与 curl。libpq-dev 与 libcurl4-openssl-dev 分别是 psycopg、pycurl 编译必需的:
apt-get update
apt-get install -y build-essential libpq-dev libcurl4-openssl-dev libffi-dev pkg-config git curl
实测输出(节选):
Setting up build-essential (12.9ubuntu3) ...
Setting up libcurl4-openssl-dev (7.81.0-1ubuntu1.21) ...
Processing triggers for man-db (2.10.2-1) ...
验证编译环境:
gcc --version | head -1
gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
4.2 安装 PostgreSQL 16(PGDG 官方仓库)
⚠️ 不要直接 apt install postgresql:Ubuntu 22.04 源里是 PG 14,而 Healthchecks v4.4 要求 PG ≥ 15,启动 migrate 时会报错(详见八、FAQ Q1)。正确做法是先添加 PostgreSQL 官方 APT 仓库(PGDG):
install -d /usr/share/postgresql-common/pgdg
curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc
echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt jammy-pgdg main" > /etc/apt/sources.list.d/pgdg.list
apt-get update
apt-get install -y postgresql-16
实测输出(节选):
Setting up postgresql-16 (16.15-1.pgdg22.04+2) ...
debconf: falling back to frontend: Readline
invoke-rc.d: policy-rc.d denied execution of start.
查看集群状态并启动。注意:如果机器上已存在 PG 14 集群(占用了 5432),新装的 PG 16 集群会自动分配 5433 端口,这是 pg_createcluster 的真实行为:
pg_lsclusters
Ver Cluster Port Status Owner Data directory Log file
14 main 5432 online postgres /var/lib/postgresql/14/main /var/log/postgresql/postgresql-14-main.log
16 main 5433 online postgres /var/lib/postgresql/16/main /var/log/postgresql/postgresql-16-main.log
⚠️ 若上表只有 14 没有 16 行,说明安装时集群未初始化(部分最小化环境会出现),手动创建即可:
pg_createcluster 16 main --start。
确认版本并保证开机自启:
psql --version
systemctl enable --now postgresql
systemctl is-active postgresql
psql (PostgreSQL) 14.24 (Ubuntu 14.24-0ubuntu0.22.04.1)
active
💡 说明:
psql客户端默认指向系统的 PG 14(14.24),这不影响使用——客户端可连任意版本服务端。若想客户端命令也用 16,可apt install postgresql-client-16后用psql -p 5433指定端口。
4.3 安装 Python 3.12(deadsnakes PPA)
Ubuntu 22.04 自带 Python 3.10.12,不满足 Django 6.1 的要求。deadsnakes PPA 提供官方打包的各版本 Python:
apt-get install -y software-properties-common
add-apt-repository -y ppa:deadsnakes/ppa
apt-get install -y python3.12 python3.12-venv python3.12-dev
实测输出(节选):
Adding deb entry to /etc/apt/sources.list.d/deadsnakes-ubuntu-ppa-jammy.list
Adding key to /etc/apt/trusted.gpg.d/deadsnakes-ubuntu-ppa.gpg with fingerprint F23C5A6CF475977595C89F51BA6932366A755776
Setting up python3.12-dev (3.12.15-1+jammy1) ...
验证版本:
python3.12 -V
Python 3.12.15
4.4 下载源码并校验
从 GitHub 下载 v4.4 tag 的源码包,解压到 /opt/healthchecks:
cd /tmp
curl -LO https://github.com/healthchecks/healthchecks/archive/refs/tags/v4.4.tar.gz
ls -lh v4.4.tar.gz
sha256sum v4.4.tar.gz
实测输出:
-rw-r--r-- 1 root root 5.1M Oct 16 15:26 v4.4.tar.gz
413c050adba9843a75f7e2fb51a44f32fc907bdbbecdf60474f396802aa01e55 v4.4.tar.gz
tar xzf v4.4.tar.gz
mv healthchecks-4.4 /opt/healthchecks
ls /opt/healthchecks
CHANGELOG.md CONTRIBUTING.md LICENSE README.md SECURITY.md
docker hc manage.py mypy.ini requirements-dev.txt requirements.txt search.db static stuff templates
💡 说明:
hc/是 Django 项目目录(settings、各 app),templates/、static/是页面模板与前端静态资源,docker/目录供官方镜像构建流程使用(源码部署用不到)。
4.5 创建虚拟环境并安装依赖
用 Python 3.12 建独立虚拟环境(避免污染系统包),随后安装 requirements.txt 与 gunicorn:
python3.12 -m venv /opt/venv
/opt/venv/bin/pip install --upgrade pip
/opt/venv/bin/pip install -r /opt/healthchecks/requirements.txt gunicorn
实测输出(节选,编译 psycopg/pycurl/argon2 需数分钟):
Successfully installed Django-6.1 aiosmtpd-1.4.6 argon2-cffi-25.1.0 cronsim-2.7 django-compressor-4.6.0 fido2-2.2.1 gunicorn-26.2.0 oncalendar-1.1 psycopg-3.3.4 pycurl-7.47.0 pydantic-2.13.5 PyJWT-2.13.0 pyotp-2.10.0 segno-1.6.6 statsd-4.0.1 whitenoise-6.12.0
核对关键包版本:
/opt/venv/bin/pip list | grep -E "^(Django|gunicorn|psycopg|pycurl|whitenoise) "
Django 6.1
gunicorn 26.2.0
psycopg 3.3.4
pycurl 7.47.0
whitenoise 6.12.0
4.6 建库与建用户
在 PG 16 集群(端口 5433)上创建业务库 hc 与用户 hc。su postgres -c psql 是本地 socket 管理员入口:
echo "CREATE USER hc WITH PASSWORD 'q1w2e3r4';" | su postgres -c "psql -p 5433"
echo "CREATE DATABASE hc OWNER hc;" | su postgres -c "psql -p 5433"
echo "\l" | su postgres -c "psql -p 5433" | grep -E "hc|Name"
实测输出:
CREATE ROLE
CREATE DATABASE
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+---------+---------+-----------------------
hc | hc | UTF8 | C.UTF-8 | C.UTF-8 |
4.7 编写配置文件 local_settings.py
Healthchecks 读取配置的优先级是:环境变量 → hc/local_settings.py(存在则覆盖同名字段)。源码部署推荐把数据库、密钥等固定配置写进 hc/local_settings.py,环境变量留给 systemd 托管时注入。先生成一把随机 SECRET_KEY:
python3 -c "import secrets; print(secrets.token_urlsafe(40))"
实测输出:
S4YD-1n8D2pQmXJ7bKzvLw3hTgUeRcA9F0sVqWxZkOyE
将以下内容写入 /opt/healthchecks/hc/local_settings.py(SECRET_KEY 换成你自己的生成值):
# /opt/healthchecks/hc/local_settings.py
SECRET_KEY = "S4YD-1n8D2pQmXJ7bKzvLw3hTgUeRcA9F0sVqWxZkOyE"
DEBUG = False
ALLOWED_HOSTS = ["localhost", "127.0.0.1", "hc-server"]
SITE_ROOT = "http://localhost:8000"
SITE_NAME = "Mychecks"
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "hc",
"USER": "hc",
"PASSWORD": "q1w2e3r4",
"HOST": "127.0.0.1",
"PORT": "5433",
"TEST": {"CHARSET": "UTF8"},
}
}
逐项说明:
SECRET_KEY:Django 会话/Cookie 签名与 API Key 派生的根密钥,必须唯一且保密;更换后所有登录会话与已签发 API Key 失效(API Key 在库里以 HMAC 形式存储,依赖此密钥);DEBUG:生产必须False,否则报错页会泄露配置;ALLOWED_HOSTS:HTTP Host 头白名单,不在名单内直接 400(实测见 4.10);SITE_ROOT:对外访问的基础 URL,邮件里的链接、ping URL 都由它派生;DATABASES:显式指定 PG 16 的5433端口——这是本环境 PG 14/16 共存的结果;若服务器只装了 PG 16,端口写5432。
4.8 初始化数据库与静态资源
migrate 建表,collectstatic 汇集静态文件,compress 压缩合并 CSS/JS:
cd /opt/healthchecks
/opt/venv/bin/python manage.py migrate
实测输出(节选,首尾):
Operations to perform:
Apply all migrations: accounts, admin, api, auth, contenttypes, logs, payments, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
...
Applying payments.0009_alter_subscription_user... OK
Applying sessions.0001_initial... OK
/opt/venv/bin/python manage.py collectstatic --noinput
367 static files copied to '/opt/healthchecks/static-collected'.
/opt/venv/bin/python manage.py compress
Compressing... done
Compressed 27 block(s) from 152 template(s) for 1 context(s).
复查迁移已全部应用:
/opt/venv/bin/python manage.py migrate
No migrations to apply.
4.9 创建管理员账号
Healthchecks 自带定制版 createsuperuser 命令,用 --email + --password 非交互创建(登录时用邮箱,不是用户名):
cd /opt/healthchecks
/opt/venv/bin/python manage.py createsuperuser --email admin@example.org --password q1w2e3r4
实测输出:
System check identified some issues:
WARNINGS:
?: (hc.api.W002) No SMTP configuration, cannot send email
HINT: See https://github.com/healthchecks/healthchecks#sending-emails
Superuser created successfully.
💡 说明:
hc.api.W002警告表示尚未配置出站 SMTP(EMAIL_HOST),只影响发邮件,不影响 Web 登录与 ping 功能;配置方法见 4.12。同理,若 MAILERS 未配置还会出现mail.W001提示,属同类提醒。
查看落库后的账号形态(用户名是自动生成的 UUID,登录仍用邮箱):
/opt/venv/bin/python manage.py shell -c "from django.contrib.auth.models import User; [print(repr(u.username), u.email, u.is_superuser) for u in User.objects.all()]"
'e9918dec-5d7e-4dbd-b870-21bb14' admin@example.org True
4.10 启动验证(gunicorn + curl 登录)
先手动启动验证功能完整,再交给 systemd。启动 gunicorn 监听 8000:
cd /opt/healthchecks
nohup /opt/venv/bin/gunicorn hc.wsgi:application --bind 0.0.0.0:8000 --workers 2 --timeout 60 > /tmp/gunicorn.log 2>&1 &
验证登录页与根路径跳转:
curl -sI http://127.0.0.1:8000/accounts/login/ | head -3
curl -s http://127.0.0.1:8000/ -o /dev/null -w "GET / -> %{http_code}\n"
HTTP/1.1 200 OK
Server: gunicorn
Date: Fri, 16 Oct 2026 15:31:12 GMT
GET / -> 302
💡 说明:
/未登录时 302 跳转到登录页,属正常行为;登录页 200 即服务健康。
用 curl 完整走一遍登录(Django 表单登录需先取 CSRF Token,且 Healthchecks 登录表单要求附加隐藏字段 action=login,缺了它 POST 只会回到 200 的登录页而不报错,是常见踩坑点):
cd /tmp && rm -f hc.jar
# 1) 取登录页与 CSRF Token
curl -s -c hc.jar http://127.0.0.1:8000/accounts/login/ -o login.html
TOKEN=$(grep csrftoken hc.jar | awk '{print $7}')
echo "csrf_token: $TOKEN"
# 2) 带凭据与 Token 提交登录
curl -s -b hc.jar -c hc.jar \
--data-urlencode "action=login" \
--data-urlencode "email=admin@example.org" \
--data-urlencode "password=q1w2e3r4" \
--data-urlencode "csrfmiddlewaretoken=$TOKEN" \
-H "Referer: http://127.0.0.1:8000/accounts/login/" \
http://127.0.0.1:8000/accounts/login/ -o /dev/null \
-w "POST /accounts/login/ -> %{http_code} redirect=%{redirect_url}\n"
# 3) 携带会话访问项目 Check 列表页
curl -s -b hc.jar "http://127.0.0.1:8000/projects/bfe79acf-9a76-472b-8029-9828d9a4ffe2/checks/" -o checks.html -w "GET /projects/.../checks/ -> %{http_code}\n"
grep -o "<title>[^<]*</title>" checks.html
实测输出:
csrf_token: goxhjkC0SEXFoh49G7Z7deQBxosbnn9j
POST /accounts/login/ -> 302 redirect=http://127.0.0.1:8000/projects/bfe79acf-9a76-472b-8029-9828d9a4ffe2/checks/
GET /projects/.../checks/ -> 200
<title>Mychecks</title>
登录成功(302 跳到项目页,页面标题 200)。顺手验证 ALLOWED_HOSTS 白名单的拦截效果——伪造 Host 头应被 400 拒绝:
curl -s -H "Host: evil.example.com" http://127.0.0.1:8000/accounts/login/ -o /dev/null -w "Host=evil.example.com -> %{http_code}\n"
Host=evil.example.com -> 400
4.11 systemd 托管
创建专用系统用户并移交目录属主(服务降权运行):
useradd --system --home /opt/healthchecks --shell /usr/sbin/nologin hc
chown -R hc:hc /opt/healthchecks
id hc
uid=999(hc) gid=999(hc) groups=999(hc)
单元 1:Web 服务。写入 /etc/systemd/system/healthchecks-web.service:
[Unit]
Description=Healthchecks web (gunicorn)
After=network.target postgresql.service
Wants=postgresql.service
[Service]
Type=simple
User=hc
Group=hc
EnvironmentFile=/etc/healthchecks
WorkingDirectory=/opt/healthchecks
ExecStart=/opt/venv/bin/gunicorn hc.wsgi:application --bind 0.0.0.0:8000 --workers 2 --timeout 60
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
单元 2:告警派发器。manage.py sendalerts 在 v4.4 中是常驻循环进程(每 2 秒扫描一次到期 Check 并发告警),不是跑一次就退出的批处理,应作为 systemd 服务常驻,而不是老文档里说的 crontab 每分钟调用。写入 /etc/systemd/system/healthchecks-sendalerts.service:
[Unit]
Description=Healthchecks alert dispatcher (sendalerts)
After=network.target postgresql.service
Wants=postgresql.service
[Service]
Type=simple
User=hc
Group=hc
EnvironmentFile=/etc/healthchecks
WorkingDirectory=/opt/healthchecks
ExecStart=/opt/venv/bin/python manage.py sendalerts
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
两个单元都引用了环境文件 /etc/healthchecks(邮件等环境级配置统一放这里;暂无出站 SMTP 时可先留空或只写注释):
cat > /etc/healthchecks << 'EOF'
# Healthchecks 服务环境变量(web / sendalerts 共用)
# 配出站 SMTP 时取消注释并改成你的服务器:
# EMAIL_HOST=smtp.example.com
# EMAIL_PORT=587
# EMAIL_USE_TLS=True
# EMAIL_HOST_USER=alert@example.com
# EMAIL_HOST_PASSWORD=your-smtp-password
# DEFAULT_FROM_EMAIL=alert@example.com
EOF
chmod 600 /etc/healthchecks
先停掉手动起的 gunicorn,再加载并启用两个单元:
pkill -x gunicorn
systemctl daemon-reload
systemctl enable --now healthchecks-web
systemctl enable --now healthchecks-sendalerts
实测输出:
Created symlink /etc/systemd/system/multi-user.target.wants/healthchecks-web.service → /etc/systemd/system/healthchecks-web.service.
Created symlink /etc/systemd/system/multi-user.target.wants/healthchecks-sendalerts.service → /etc/systemd/system/healthchecks-sendalerts.service.
确认运行状态:
systemctl is-active healthchecks-web healthchecks-sendalerts
systemctl status healthchecks-web --no-pager | head -8
active
active
● healthchecks-web.service - Healthchecks web (gunicorn)
Loaded: loaded (/etc/systemd/system/healthchecks-web.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2026-10-16 15:35:22 UTC; 9s ago
Main PID: 12182 (gunicorn)
Tasks: 4 (limit: 7196)
Memory: 111.8M
💡 说明:
systemctl is-active后跟多个单元时逐个返回一行状态;常驻内存约 112 MB(2 个 worker),1C2G 的小机器即可承载。systemctl每次只操作一个单元的启停更稳妥,批量确认状态可以合并查询。
重启演练确认托管有效:
systemctl restart healthchecks-web && systemctl is-active healthchecks-web
journalctl -u healthchecks-web -n 3 --no-pager
active
Oct 16 15:35:32 hc-server gunicorn[12182]: [2026-10-16 15:35:32 +0000] [12182] [INFO] Shutting down: Master
Oct 16 15:35:32 hc-server systemd[1]: healthchecks-web.service: Deactivated successfully.
Oct 16 15:35:32 hc-server systemd[1]: Started Healthchecks web (gunicorn).
4.12 配置出站 SMTP(告警邮件必需)
不配 SMTP 时 Check 掉线只会记录状态,发不出告警邮件。编辑 /etc/healthchecks 写入 SMTP 参数(示例用局域网调试服务器,生产换成你的邮件服务商),然后重启服务:
cat > /etc/healthchecks << 'EOF'
EMAIL_HOST=127.0.0.1
EMAIL_PORT=2525
EMAIL_USE_TLS=False
EMAIL_USE_VERIFICATION=False
DEFAULT_FROM_EMAIL=healthchecks@localhost
EOF
systemctl restart healthchecks-web healthchecks-sendalerts
验证配置已被读取(重新执行 createsuperuser 时不再出现 W002 警告,或直接看下一章的告警邮件实测)。注意:EMAIL_HOST 一旦设置,settings.py 会据此生成 MAILERS 邮件通道;EMAIL_USE_VERIFICATION=False 表示添加邮件通知渠道时跳过验证邮件确认,便于内网快速上手,生产环境建议保持默认 True。
五、方案 B:源码安装 + SQLite(轻量)
不装 PostgreSQL,用 Healthchecks 默认的 SQLite 库也能跑,适合个人/小规模场景。前置(系统依赖、Python 3.12、源码、venv、依赖安装)与方案 A 的 4.1–4.5 完全一致,只是跳过 4.6/4.7 中的数据库部分,local_settings.py 不写 DATABASES(settings.py 默认走 SQLite)。
用环境变量 DB_NAME 把库文件指到数据目录(避免写在程序目录里):
mkdir -p /opt/healthchecks-data
export DB_NAME=/opt/healthchecks-data/hc.sqlite
cd /opt/healthchecks
/opt/venv/bin/python manage.py migrate
实测输出(节选):
Operations to perform:
Apply all migrations: accounts, admin, api, auth, contenttypes, logs, payments, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
确认库文件生成:
ls -lh /opt/healthchecks-data/hc.sqlite
-rw-r--r-- 1 root root 104K Oct 16 16:00 /opt/healthchecks-data/hc.sqlite
其余步骤(collectstatic/compress/createsuperuser/systemd)与方案 A 相同,只是 systemd 单元里的 EnvironmentFile=/etc/healthchecks 需要补一行 DB_NAME=/opt/healthchecks-data/hc.sqlite,让 web 与 sendalerts 都能找到库文件。SQLite 方案的取舍:零数据库运维、备份即拷文件,但写入并发弱、不支持多机部署,Check 数量多或 ping 频繁时仍建议 PostgreSQL。
六、方案对比与选择建议
| 维度 | 方案 A:源码 + PostgreSQL 16 | 方案 B:源码 + SQLite |
|---|---|---|
| 数据库 | PGDG 仓库独立安装、独立运维 | 零部署,单文件 |
| 建库 | CREATE USER/CREATE DATABASE | migrate 自动生成文件 |
| 监听端口 | PG 16 默认 5433(与 14 共存时) | 无 |
| 并发能力 | 多 worker 并发读写,ping 量大无压力 | 写入串行,量大时锁等待 |
| 备份 | pg_dump 在线备份 | 停写拷贝文件 |
| 升级扩展 | 可平滑迁到独立数据库服务器 | 迁移需 pg_dump 导入改造 |
| 适用 | 生产、团队、长期运行 | 个人试用、树莓派等小设备 |
选择建议:能装 PG 就选方案 A;只想快速体验或 Check 少于几十个的内网玩具场景选方案 B。如果连 Python 环境都不想碰,可改走官方镜像部署路线(见《Healthchecks v4.4 Docker Compose 部署指南》)。
七、配置说明
源码部署的可调配置分两层,加载顺序是环境变量优先,hc/local_settings.py 兜底覆盖:
/etc/healthchecks(systemdEnvironmentFile=):进程级环境变量,改完systemctl restart生效,适合EMAIL_HOST、EMAIL_PORT这类运行参数;/opt/healthchecks/hc/local_settings.py:Django 层配置,适合SECRET_KEY、DATABASES、ALLOWED_HOSTS、SITE_ROOT等。
常用键速查(均为实测可用项,完整清单见《Healthchecks v4.4 配置参数详解》):
| 键 | 默认值 | 说明 |
|---|---|---|
SECRET_KEY | "---"(不安全占位) | 必改;会话签名与 API Key 派生根 |
DEBUG | True | 生产必须改 False |
ALLOWED_HOSTS | 空 | Host 白名单,缺失或不含访问域名时 400 |
SITE_ROOT | http://localhost:8000 | 对外基础 URL,邮件链接/ping URL 派生源 |
EMAIL_HOST | 空 | 设置后启用出站 SMTP(生成 MAILERS) |
EMAIL_PORT | 587 | SMTP 端口,配 EMAIL_HOST 时生效 |
EMAIL_USE_TLS | True | STARTTLS 明文升级 |
DB_NAME(环境变量) | /opt/healthchecks/hc.sqlite | 未覆盖 DATABASES 时 SQLite 路径 |
PING_EMAIL_DOMAIN | localhost | 入站邮件 ping 的收件域名 |
修改配置后统一用 systemctl restart healthchecks-web healthchecks-sendalerts 应用(每条 restart 命令重启一个或多个单元均可,建议逐个执行并 is-active 确认)。
八、常见问题(FAQ)
Q1:migrate 报 PostgreSQL 15 or later is required (found 14.24) 怎么办?
现象:
django.db.utils.NotSupportedError: PostgreSQL 15 or later is required (found 14.24).
原因:Ubuntu 22.04 默认源装到的 PG 14 低于 Django 6.1 的服务端版本检查线。定位:pg_lsclusters 确认只有 14 集群。解决:按 4.2 添加 PGDG 仓库安装 postgresql-16,若已装了 PG 14 则新集群在 5433 端口,把 local_settings.py 的 PORT 改成 5433 再 migrate。更干净的做法是只保留 16:pg_dropcluster 14 main --stop 删除旧集群(会删数据,先确认)。
Q2:pip 安装依赖时报 pg_config executable not found 或 pycurl 编译失败?
现象(节选):
fatal error: libpq-fe.h: No such file or directory
原因:缺编译头文件。解决:apt-get install -y build-essential libpq-dev libcurl4-openssl-dev libffi-dev pkg-config(4.1 已包含),确认 pg_config --version 有输出后再重试 pip install -r requirements.txt。
Q3:python3.10 直接装依赖会怎样?
pip 解析 Django==6.1 时会跳过 3.12+ 的包(Django 6.1 的 python_requires=">=3.12"),要么报错找不到满足版本,要么降到旧版 Django 与 v4.4 代码不兼容。必须在 Python 3.12 的 venv 里安装(4.3/4.5)。
Q4:curl 登录一直返回 200,跳转不了?
登录 POST 返回 200 表示表单被重新渲染(登录未生效)。三个常见原因:① 缺 action=login 隐藏字段(Healthchecks 登录表单特有,见 4.10);② csrfmiddlewaretoken 未带或未带 Referer 头(Django CSRF 校验要求);③ Cookie Jar 未复用(-b/-c 要指向同一个文件)。逐项补齐即可 302。
Q5:管理页能开,但 Check 掉线后收不到邮件?
排查顺序:① systemctl is-active healthchecks-sendalerts 必须是 active,它是实际发告警的进程;② /etc/healthchecks 里是否配置了 EMAIL_HOST(没配置时 settings 会告警 hc.api.W002,Check 只记状态不发信);③ 直接运行 manage.py sendreports 这类命令报 AssertionError: No SMTP configuration 时,说明 shell 里没加载环境文件——手动执行管理命令要先 set -a; . /etc/healthchecks; set +a;④ 用日志核对:journalctl -u healthchecks-sendalerts -n 50 中可见每次通知的发送结果(成功/失败原因,例如 SMTP 拒收会打印 SMTPRecipientsRefused 与 5xx 响应码)。
Q6:如何升级到新版本?
源码部署的升级路径:下载新 tag 源码包 → 停服务 → 替换 /opt/healthchecks 中的程序文件(保留 hc/local_settings.py 与 static-collected/)→ pip install -r requirements.txt → manage.py migrate → 启动。跨版本升级务必先 pg_dump 备份(命令见《Healthchecks v4.4 进阶实战与运维》)。
九、卸载与清理
按依赖的反向顺序拆除,逐条执行并确认:
systemctl disable --now healthchecks-web
systemctl disable --now healthchecks-sendalerts
Removed "/etc/systemd/system/multi-user.target.wants/healthchecks-web.service".
Removed "/etc/systemd/system/multi-user.target.wants/healthchecks-sendalerts.service".
rm -f /etc/systemd/system/healthchecks-web.service /etc/systemd/system/healthchecks-sendalerts.service
systemctl daemon-reload
rm -rf /opt/healthchecks /opt/venv /etc/healthchecks
userdel hc
删除数据库与用户(端口按实际集群调整):
echo "DROP DATABASE IF EXISTS hc;" | su postgres -c "psql -p 5433"
echo "DROP USER IF EXISTS hc;" | su postgres -c "psql -p 5433"
DROP DATABASE
DROP ROLE
若整个 PostgreSQL 都不再需要:
apt-get purge -y postgresql-16
rm -f /etc/apt/sources.list.d/pgdg.list
apt-get autoremove -y
最后确认无残留进程与端口:
pgrep -a -f gunicorn || echo "无 gunicorn 残留"
curl -s -o /dev/null --max-time 2 http://127.0.0.1:8000/ -w "%{http_code}\n" || echo "8000 已无监听"
无 gunicorn 残留
8000 已无监听
十、参考链接
- 官网:https://healthchecks.io
- 自托管文档(官方):https://healthchecks.io/docs/self_hosted/
- 源码仓库:https://github.com/healthchecks/healthchecks
- v4.4 发布页:https://github.com/healthchecks/healthchecks/releases/tag/v4.4
- 配置参数官方说明:https://healthchecks.io/docs/self_hosted_configuration/
- 本系列其他篇:《Healthchecks v4.4 Docker Compose 部署指南》《Healthchecks v4.4 快速入门与集成示例》《Healthchecks v4.4 配置参数详解》《Healthchecks v4.4 进阶实战与运维》