共计 5912 个字符,预计需要花费 15 分钟才能阅读完成。
之前白嫖了 Hugging Face 的 2 核 16g 服务器 ,已经 部署了 n8n;
这次继续用它来整点活,部署一个监控工具 Uptime Kuma!
准备工作
私有部署 Uptime Kuma 要用到的服务:
- Hugging Face: https://huggingface.co/
- Uptime Kuma: https:///github.com/louislam/uptime-kuma
- Webdav(infiniCloud): https://infini-cloud.net/
- Cloudflare(可选): https://cloudflare.com
Hugging Face 上文已经介绍过了,不了解朋友的可以看:免费白嫖 16G+2vCPU 的服务器!超简单教程,有手就会
Uptime Kuma 是什么?
Uptime Kuma 是一款易于使用的自托管监控工具。
- 监控 HTTP(s) / TCP / HTTP(s) 关键字 / HTTP(s) Json 查询 / Ping / DNS 记录 / 推送 / Steam 游戏服务器 / Docker 容器的正常运行时间
- 精美、反应灵敏、快速的 UI/UX
- 通过 Telegram、Discord、Gotify、Slack、Pushover、电子邮件 (SMTP) 和 90 多种通知服务发送通知
最简单的用例可以用来监测网站是否可正常访问。

一、注册免费的 WebDAV 服务
Webdav 是什么?
百度百科 :WebDAV(Web-based Distributed Authoring and Versioning)一种基于 HTTP 1.1 协议的通信协议。它扩展了 HTTP 1.1,在 GET、POST、HEAD 等几个 HTTP 标准方法以外添加了一些新的方法,使应用程序可对 Web Server 直接读写,并支持写文件锁定(Locking) 及解锁(Unlock),还可以支持文件的版本控制。
维基百科:基于 Web 的分布式编写和版本控制(英语:Web-based Distributed Authoring and Versioning,缩写:WebDAV)是超文本传输协议(HTTP)的扩展,有利于用户间协同编辑和管理存储在万维网服务器文档。WebDAV 由互联网工程任务组的工作组在 RFC 4918 中定义。
今天我们使用一款免费 20GB 空间的在线 WebDAV 服务 InfiniCLOUD:

自主管理的一体化云存储,保障您的数据安全。将您的文件和文档备份到 InfiniCLOUD,随时随地访问,无需担心存储空间限制。
1、登录 或注册 InfiniCLOUD
这里具体过程不缀叙,可以用邮箱注册或 登陆。


2、创建文件夹


3、开启传输权限
此处可以使用博主的推荐码: 7WSNH

保存传输参数:
WEBDAV_URL: https://soya.infini-cloud.net/dav/ # 链接地址
WEBDAV_BACKUP_PATH: uptime # 备份文件夹名,第 2 步获取到的
WEBDAV_USERNAME: xxx # 注册的用户名,第 1 步获取到的
WEBDAV_PASSWORD: *** # 连接密码,第 1 步获取到的
SYNC_INTERVAL: 600 # 同步时间, 默认
二、创建 huggingface 空间


1. 进入 settings 添加 Secrets 环境变量
变量来自于上一步从 infini-cloud 获得的参数,完成后效果如下

然后进入 Space -> Files -> Contribute -> Creat a new file,按下方步骤添加对应的文件

2. 编辑 README.md 文件
末尾添加
app_port: 3001
3. 创建 sync_data.sh 文件
#!/bin/sh
# 检查环境变量
if [ -z "$WEBDAV_URL" ] || [ -z "$WEBDAV_USERNAME" ] || [ -z "$WEBDAV_PASSWORD" ]; then
echo "Starting without backup functionality - missing WEBDAV_URL, WEBDAV_USERNAME, or WEBDAV_PASSWORD"
exec node server/server.js
exit 0
fi
# 设置备份路径
WEBDAV_BACKUP_PATH=${WEBDAV_BACKUP_PATH:-""}
FULL_WEBDAV_URL="${WEBDAV_URL}"
if [ -n "$WEBDAV_BACKUP_PATH" ]; then
FULL_WEBDAV_URL="${WEBDAV_URL}/${WEBDAV_BACKUP_PATH}"
fi
# 下载最新备份并恢复
restore_backup() {
echo "开始从 WebDAV 下载最新备份..."
python3 -c "
import sys
import os
import tarfile
import requests
import shutil
from webdav3.client import Client
options = {
'webdav_hostname': '$FULL_WEBDAV_URL',
'webdav_login': '$WEBDAV_USERNAME',
'webdav_password': '$WEBDAV_PASSWORD'
}
client = Client(options)
backups = [file for file in client.list() if file.endswith('.tar.gz') and file.startswith('uptime_kuma_backup_')]
if not backups:
print('没有找到备份文件')
sys.exit()
latest_backup = sorted(backups)[-1]
print(f'最新备份文件:{latest_backup}')
with requests.get(f'$FULL_WEBDAV_URL/{latest_backup}', auth=('$WEBDAV_USERNAME', '$WEBDAV_PASSWORD'), stream=True) as r:
if r.status_code == 200:
with open(f'/tmp/{latest_backup}', 'wb') as f:
for chunk in r.iter_content(chunk_size=8192):
f.write(chunk)
print(f'成功下载备份文件到 /tmp/{latest_backup}')
if os.path.exists(f'/tmp/{latest_backup}'):
# 如果 data 目录已存在,先删除它
if os.path.exists('/home/app/uptime-kuma/data'):
print('删除现有的 data 目录')
shutil.rmtree('/home/app/uptime-kuma/data')
# 解压备份文件
with tarfile.open(f'/tmp/{latest_backup}', 'r:gz') as tar:
tar.extractall('/home/app/uptime-kuma/')
print(f'成功从 {latest_backup} 恢复备份')
else:
print('下载的备份文件不存在')
else:
print(f'下载备份失败:{r.status_code}')
"
}
# 首次启动时下载最新备份
echo "Downloading latest backup from WebDAV..."
restore_backup
# 同步函数
sync_data() {
while true; do
echo "Starting sync process at $(date)"
if [ -d "/home/app/uptime-kuma/data" ]; then
timestamp=$(date +%Y%m%d_%H%M%S)
backup_file="uptime_kuma_backup_${timestamp}.tar.gz"
# 备份整个 data 目录
cd /home/app/uptime-kuma
tar -czf "/tmp/${backup_file}" data
# 上传新备份到 WebDAV
curl -u "$WEBDAV_USERNAME:$WEBDAV_PASSWORD" -T "/tmp/${backup_file}" "$FULL_WEBDAV_URL/${backup_file}"
if [ $? -eq 0 ]; then
echo "Successfully uploaded ${backup_file} to WebDAV"
else
echo "Failed to upload ${backup_file} to WebDAV"
fi
# 清理旧备份文件
python3 -c "
import sys
from webdav3.client import Client
options = {
'webdav_hostname': '$FULL_WEBDAV_URL',
'webdav_login': '$WEBDAV_USERNAME',
'webdav_password': '$WEBDAV_PASSWORD'
}
client = Client(options)
backups = [file for file in client.list() if file.endswith('.tar.gz') and file.startswith('uptime_kuma_backup_')]
backups.sort()
if len(backups) > 5:
to_delete = len(backups) - 5
for file in backups[:to_delete]:
client.clean(file)
print(f'Successfully deleted {file}.')
else:
print('Only {} backups found, no need to clean.'.format(len(backups)))
" 2>&1
rm -f "/tmp/${backup_file}"
else
echo "/home/app/uptime-kuma/data directory does not exist, waiting for next sync..."
fi
SYNC_INTERVAL=${SYNC_INTERVAL:-600}
echo "Next sync in ${SYNC_INTERVAL} seconds..."
sleep $SYNC_INTERVAL
done
}
# 启动同步进程
sync_data &
# 启动主应用
sleep 30
exec node server/server.js
4. 创建 Dockerfile
FROM alpine AS builder
RUN apk add --no-cache nodejs npm git curl jq python3 python3-dev py3-pip
RUN adduser -D app
USER app
WORKDIR /home/app
RUN git clone https://github.com/louislam/uptime-kuma.git
WORKDIR /home/app/uptime-kuma
RUN npm run setup
ENV VIRTUAL_ENV=/home/app/venv
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
RUN pip install --no-cache-dir requests webdavclient3
COPY --chown=app:app sync_data.sh /home/app/uptime-kuma/
RUN chmod +x /home/app/uptime-kuma/sync_data.sh
EXPOSE 3001
CMD ["/bin/sh", "-c", "./sync_data.sh & sleep 30 && node server/server.js"]
提交 Dockerfile 文件后 huggingface 会自动构建,完成后获取到空间地址


三、在 cloudflare 进行反代(非必须)
1. 新建 Workers

2. 输入反代内容并部署
以下是简单版
export default {async fetch(request, env) {const url = new URL(request.url);
url.host = '你的地址';
return fetch(new Request(url, request))
}
}
以下是进阶版,可以隐藏默认地址 dashboard,直接访问状态页面
export default {async fetch(request, env) {const _url = new URL(request.url);
const hostname = _url.hostname;
_url.hostname = "xxx.hf.space";
const req = new Request(_url, request);
req.headers.set('origin', 'https://xxx.hf.space');
const res = await fetch(req);
let newres = new Response(res.body, res);
let location = newres.headers.get('location');
if (location !== null && location !== "") {
// 可选 - >
// 去除原始路径中的 /dashboard
location = location.replace('/dashboard', '');
// 添加 /status/web 路径
location = location + '/status/web';
// <- 可选
location = location.replace('://xxx', '://'+hostname);
newres.headers.set('location', location);
}
return newres;
},
};


3. 添加自定义域名
完成上一步部署后,进入当前 Workers -> 设置 -> 域和路由 -> 添加 -> 自定义域,添加子域名或主域名



完成效果如下

四、登录 Uptime Kuma
1. 打开上一步设置的自定义域、或 workers 的地址、或 space 的地址
首次访问需要设置管理员账户密码

接下来,就可以尽情体验 Uptime Kuma 的功能了

延伸资源
参考链接:

