网站监控系统

Naseele 技术工坊 82 次阅读 4340 字 预计阅读时间: 20 分钟 发布于 2025-12-02 最后更新于 2025-12-08


AI 摘要

嘿,小伙伴们!还在手动检查网站是否在线吗?这篇文章教你搭建一个“网站健康管家”——Uptime Kuma监控系统!它就像个24小时值班的哨兵,一旦网站“打瞌睡”,就会立刻通过邮件通知你。文章还手把手教你配置酷炫的通知邮件,并把状态页面嵌入博客,让你的站点更专业。跟着步骤走,轻松拥有自己的监控中心!✨

之前我们部署了不少服务,但是我们可能很难每天都去看看他们是不是运行良好,尤其是博客。这时候我们需要一个监控系统,来实时监测网站的有效性,并在发现网站掉线的时候给我们发送警告。

另外,我们的博客界面如果能内嵌一个美观的状态页面,也更有吸引力。

本节我们就来讲讲如何部署监控系统,并将状态页面集成到我们的博客上。

1.监控系统部署

1.1 创建项目路径

我们在/home/naseele/下创建文件夹UptimeKuma

1.2 创建docker-compose.yml

nano docker-compose.yml

写入:

services:
  uptime-kuma:
    image: louislam/uptime-kuma:2
    container_name: uptime-kuma
    restart: always
    dns:
      - 223.5.5.5       # 阿里云 DNS
      - 114.114.114.114 # 114 DNS
    volumes:
      - ./data:/app/data
    networks:
      - caddy_net

networks:
  caddy_net:
    external: true

如果你服务器原来没有caddy,换成这样写:

services:
  uptime-kuma:
    image: louislam/uptime-kuma:2
    container_name: uptime-kuma
    restart: always
    dns:
      - 223.5.5.5       # 阿里云 DNS
      - 114.114.114.114 # 114 DNS
    volumes:
      - ./data:/app/data
    networks:
      - caddy_net
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: always
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"  # HTTP/3 
    environment:
      TZ: Asia/Shanghai
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./caddy_data:/data
      - ./caddy_config:/config
      - ./caddy_certs:/etc/caddy/certs
    networks:
      - caddy_net

networks:
  caddy_net:
    external: true

1.3 新建Caddyfile配置

在你之前的Caddyfile配置文件末尾追加这一段。如果服务器原来没有caddy,在docker-compose.yml同级目录新建Caddyfile并写入:

{
    # ===直接关闭ocsp封套,阻止caddy每次启动时检查证书有效性(因为服务器连不上 DigiCert) ===
    ocsp_stapling off
}
你的域名 {
    encode gzip
    
    # 这里的 uptime-kuma 对应上面新 docker-compose.yml 里的 container_name
    reverse_proxy uptime-kuma:3001 {
        header_up Connection {http.request.header.Connection}
        header_up Upgrade {http.request.header.Upgrade}
    }

    # === 请修改为你的新证书文件名 ===
    # 指向docker-compose.yml映射的 /etc/caddy/certs/ 目录下的证书文件
    tls /etc/caddy/certs/status.pem /etc/caddy/certs/status.key
    
    log {
        output file /data/access_status.log
    }
}

保存退出,然后新建文件夹:

mkdir caddy_certs

去把你的域名证书(nginx格式(即pem/key))上传到这个文件夹里面,并重命名为status.pem和status.key。

启动容器:

docker compose up -d

等待镜像拉取完成,容器启动。

2. 配置Uptime Kuma

1. 基础配置

浏览器访问你的域名,进行基础配置,Uptime Kuma的界面很清晰简约,我就不多赘述了。

这里建议把 证书到期时通知 给打开

2. 通知配置

2.1 SMTP服务

关于SMTP(邮箱)的配置,我们之前讲过类似的,这里我们简单说说。

步骤跟以前一样,先去邮箱提供商那边申请授权码,然后来这边配置,我以QQ邮箱的配置为例:

通知类型、主机名、端口、安全性看SMTP服务商的文档,用户名就是你的邮件地址,密码是你的授权码,收信人是接收通知的人。

注意,修改QQ密码会清空你创建的授权码。

下面还有邮件主题和自定义正文,这两部分是我们收到的邮件会显示的,可以留空,也可以自定义配置一下,这里展示一下我的配置:

邮件主题:

{% if status == "up" %}✨ 好消息!{{ name }} 恢复正常啦 (ノ◕ヮ◕)ノ*:・゚✧
{% elsif status == "down" %}⚠️ 哎呀!{{ name }} 遇到问题了 (。•́︿•̀。)
{% else %}📢 {{ name }} - {{ msg }}
{% endif %}

自定义正文:

<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            font-family: 'Microsoft YaHei', Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            padding: 20px;
        }
        .container {
            max-width: 600px;
            margin: 0 auto;
            background: white;
            border-radius: 15px;
            padding: 30px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.2);
        }
        .header {
            text-align: center;
            margin-bottom: 25px;
        }
        .status-badge {
            display: inline-block;
            padding: 10px 20px;
            border-radius: 20px;
            font-weight: bold;
            margin: 15px 0;
        }
        .status-up {
            background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%);
            color: #0a5f38;
        }
        .status-down {
            background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
            color: #8b0000;
        }
        .info-box {
            background: #f8f9fa;
            border-left: 4px solid #667eea;
            padding: 15px;
            margin: 15px 0;
            border-radius: 5px;
        }
        .footer {
            text-align: center;
            margin-top: 25px;
            color: #888;
            font-size: 12px;
        }
        .emoji {
            font-size: 24px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            {% if status == "up" %}
            <div class="emoji">✨🎉✨</div>
            <h2 style="color: #28a745;">太好啦!服务恢复正常 ♪(๑ᴖ◡ᴖ๑)♪</h2>
            {% elsif status == "down" %}
            <div class="emoji">⚠️💔⚠️</div>
            <h2 style="color: #dc3545;">哎呀,出问题啦 (。•́︿•̀。)</h2>
            {% else %}
            <div class="emoji">📢</div>
            <h2 style="color: #667eea;">监控通知</h2>
            {% endif %}
        </div>

        <div class="status-badge {% if status == "up" %}status-up{% else %}status-down{% endif %}">
            状态:{{ status | upcase }}
        </div>

        <div class="info-box">
            <p><strong>📛 服务名称:</strong>{{ name }}</p>
            <p><strong>🔗 地址:</strong>{{ hostnameOrURL }}</p>
            <p><strong>⏰ 时间:</strong>{{ heartbeatJSON.time }}</p>
            {% if heartbeatJSON.msg %}
            <p><strong>💬 消息:</strong>{{ heartbeatJSON.msg }}</p>
            {% endif %}
        </div>

        {% if status == "up" %}
        <p style="text-align: center; font-size: 16px; color: #28a745;">
            🌈 一切都好啦,可以放心了!<br>
            继续保持哦 (ง •̀_•́)ง
        </p>
        {% elsif status == "down" %}
        <p style="text-align: center; font-size: 16px; color: #dc3545;">
            🔧 请尽快检查一下吧!<br>
            加油加油!( •̀ ω •́ )✧
        </p>
        {% endif %}

        <div class="footer">
            <p>───── ୨୧ ─────</p>
            <p>💌 来自 Naseele的状态小站 的温馨提醒</p>
            <p>自动监控系统 • 24/7 守护中 ⭐</p>
        </div>
    </div>
</body>
</html>

使用html需要开启下面的“使用 HTML 作为自定义电子邮件内容”按钮。如果不想用HTML也可以用这个纯文本版本的:

╔═══════════════════════════════╗
{% if status == "up" %}
  ✨ 服务恢复通知 (ノ◕ヮ◕)ノ*:・゚✧
{% elsif status == "down" %}
  ⚠️  服务异常通知 (。•́︿•̀。)
{% else %}
  📢 监控通知
{% endif %}
╚═══════════════════════════════╝

📛 服务名称:{{ name }}
🔗 地址:{{ hostnameOrURL }}
📊 状态:{{ status }}
⏰ 时间:{{ heartbeatJSON.time }}

{% if heartbeatJSON.msg %}
💬 详细信息:{{ heartbeatJSON.msg }}
{% endif %}

{% if status == "up" %}
━━━━━━━━━━━━━━━━━━━━━━
🎉 太棒了!一切恢复正常!
继续保持哦~ ٩(๑❛ᴗ❛๑)۶
━━━━━━━━━━━━━━━━━━━━━━
{% elsif status == "down" %}
━━━━━━━━━━━━━━━━━━━━━━
🔧 需要处理一下啦~
冲鸭!(ง •̀_•́)ง
━━━━━━━━━━━━━━━━━━━━━━
{% endif %}

───── ୨୧ ─────
💌 Naseele的监控系统
⭐ 24/7 守护您的服务

效果图:

2.2 pushplus服务

想使用pushplus服务的话,目前版本的Uptime Kuma有点问题,虽然写了原生支持pushplus,但是连不上。我们自己配置。

先去pushplus注册账号,绑定你的微信,关注他的微信公众号,确保你的积分不小于20.然后在我们网站面板进行配置:

通知类型选Webhook,显示名称自己选,Post URL填 http://www.pushplus.plus/send ,请求体选自定义内容,然后填:

{
  "token": "你的pushplus的token",
  "title": "服务报警: {{ monitor.name }}",
  "content": "状态: {{ status }}<br>详情: {{ msg }}<br>时间: {{ time }}",
  "template": "html",
  "channel": "wechat"
}

token自己去pushplus看。

下面的额外header打开,并填入:

{
  "Content-Type": "application/json"
}

之后可以测试一下,我们应该能看到他的微信公众号给我们推送了一条消息,也能在pushplus官网看到最新请求

也可以考虑选择其他的,或者用SMTP通过邮件发送。我这个方案有少量资金消费()

3. 集成到wordpress界面

3.1 修改Caddyfile

Uptime Kuma 默认会发送一个 X-Frame-Options: SAMEORIGIN 的响应头。意思是:“我的页面只能被同一个域名下的页面嵌入”。而我们的博客在另一个域名,这两个属于跨域,所以浏览器直接拦截了。

我们需要修改Caddyfile,添加下面的header配置来解除这个限制:

{
    # ===直接关闭ocsp封套,阻止caddy每次启动时检查证书有效性(因为服务器连不上 DigiCert) ===
    ocsp_stapling off
}
你的域名 {
    encode gzip
    
    # ... 你的证书配置 ...
    tls /etc/caddy/certs/status.pem /etc/caddy/certs/status.key

    reverse_proxy uptime-kuma:3001 {
        # WebSocket 支持
        header_up Connection {http.request.header.Connection}
        header_up Upgrade {http.request.header.Upgrade}
        
        # === 关键修改:移除上游(Kuma)返回的限制头 ===
        header_down -X-Frame-Options
    }

    # === 关键修改:告诉浏览器允许 www 域名嵌入我 ===
    header {
        # 允许被自己(status)和 www 主站嵌入
        Content-Security-Policy "frame-ancestors 'self' https://www.naseele-vollerei.cn"
    }

    log {
        output file /data/access_status.log
    }
}

我这里的方案是适合允许www.naseele-vollerei.cn的,如果你的与我的不一样,请自行适配。

3.2 创建状态界面

首先在Uptime Kuma这边网页端上方-状态页面新建一个页面,然后编辑状态页面。

路径自己看着写,但是要记住写的什么。下面的描述和底部自定义文本支持Markdown语法,但是渲染有延迟,需要你点击保存之后才渲染出来,可以自由发挥。这里我添加到wordpress之后发现他的主题色怪怪的,所以加了css让他变成透明的,这样在wp那边更好看:

/* === 1. 全局圆角化 (让界面更柔和) === */
.shadow-box {
    border-radius: 16px !important; /* 卡片圆角 */
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05) !important; /* 更柔和的阴影 */
    border: none !important; /* 去掉生硬的边框 */
}

/* === 2. 让“在线”状态图标会有呼吸灯效果 (关键!) === */
.badge.bg-success, .status-icon.bg-success {
    animation: breathe 2s infinite ease-in-out;
}

@keyframes breathe {
    0% { opacity: 0.7; transform: scale(0.95); box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.7); }
    70% { opacity: 1; transform: scale(1); box-shadow: 0 0 0 6px rgba(40, 167, 69, 0); }
    100% { opacity: 0.7; transform: scale(0.95); box-shadow: 0 0 0 0 rgba(40, 167, 69, 0); }
}

/* === 3. 进度条美化 === */
/* 那些绿色的小竖条让它变圆 */
.uptime-bar {
    border-radius: 4px; 
}

/* === 4. 标题和描述字体优化 === */
h1.title {
    font-weight: 700;
    letter-spacing: 1px;
    color: #4a5568; /* 柔和的深灰色,比纯黑好看 */
}

.description {
    font-size: 1.05rem;
    line-height: 1.6;
    color: #718096; /* 描述文字稍微淡一点 */
    background-color: #f7fafc; /* 给描述加个淡淡的背景框 */
    padding: 15px;
    border-radius: 12px;
    border-left: 5px solid #48bb78; /* 左边加个绿色装饰条 */
}

/* === 5. 底部文字居中并变可爱 === */
footer {
    text-align: center;
    opacity: 0.8;
    font-size: 0.9rem;
    padding-top: 20px;
}
/* === 6. 背景透明化 (变色龙模式) === */
body, .app, .container, .status-page {
    background-color: transparent !important;
}

/* 如果有卡片背景,也让它稍微透明一点,或者直接纯白 */
.shadow-box {
    background-color: rgba(255, 255, 255, 0.8) !important; /* 卡片半透明白 */
    backdrop-filter: blur(10px); /* (可选) 增加磨砂玻璃质感 */
}

右边的监控项自己添加,把你需要展示的监控加上就行了。

3.3 集成到wp

在wordpress后台 页面-添加页面,标题自己看着写,然后添加一个自定义HTML块:

在块内输入:

<iframe 
    src="https://你的UptimeKuma的域名/status/我们状态界面的路径?kiosk=1" 
    width="100%" 
    height="1000" 
    style="border: none; overflow: hidden;" 
    scrolling="no"
    title="服务监控状态">
</iframe>

状态界面的路径是刚才3.2开头填的那个路径,如果路径是main-status的话src为https://你的UptimeKuma域名/status/main-status?kiosk=1

链接解读:

  • src: 指向你的 Kuma 页面(记得带 ?kiosk=1)。
  • width: 100%: 宽度自动填满 WordPress 的内容区域。
  • height:1000;把高度直接设定死了为 1000 像素(你可以根据你现在的监控项数量调整,如果觉得下面留白太多就改成 800,如果还出现滚动条就改成 1200
  • scrolling="no"
    这是一个强制指令,告诉浏览器:“别给这个 Iframe 显示滚动条”。
  • border: none: 去掉丑陋的边框。

点击发布即可。

我们可以给他添加到主页的菜单栏:

将这个页面添加到菜单:

我的叫无标题是因为我没写标题,菜单那边显示的是导航标签,而不是文章标题,所以不影响。