用自建Grafana替换官方云服务

❤️‍🩹 阅读本篇文章之前建议先完成这篇:搭建简易家庭IT实验室——监控平台

C 缘起

感谢Grafana,我免费使用它的云服务好几年了,功能强大,性能够用,还一直免费,真的很好。

但是随着我的赛博过家家越来越复杂,内容一年比一年多,Grafana的免费额度对我来说越发捉襟见肘。付费是不可能付费的,这辈子都不会付费,只有去哪薅个服务器回来才能勉强维持得了生活这样子。

要想解决也很简单,不想使用云服务,那么我可以自建相应的服务。

Prometheus diagram

Prometheus家用示意图

我只要把上图右边云里的服务用自建代替即可。其他部分能不动就不动。

正好我有台闲置的VDS,吃灰好几年了,拿出来玩玩。

D 配置

VictoriaMetrics

既然是自己玩,这次就不在公网用Prometheus了,VictoriaMetrics(简称VM,下同)是乌克兰人开发的软件,性能好,功能多,毛子在软件这块就是令人信服。VM的功能虽然多,但是我暂时只用一点,就是它全面兼容Prometheus的API。

安装清单

组件 推荐软件 说明
容器编排 Docker Compose 方便管理多个服务(Grafana, VM, Node-Exporter)。
数据库 VM (单机版)) 替代Grafana官方云的后端存储,接收 remote_write 数据。
展示层 Grafana OSS 添加 VM 作为数据源。
反向代理 Nginx / Caddy 为 Grafana 提供域名访问和 SSL 证书(HTTPS)。

我需要一个Grafana免费版,一个VM,一个Caddy和一个Docker Engine。

数据流向

  1. 我家里的Node-Exporter去读取Linux的性能数据。
  2. 家里的Prometheus读取(刮削)家里的Node-Exporter。
  3. 家里的Prometheus推送数据到VDS上跑的VM。
  4. VDS上跑的Grafana读取VDS上跑的VM的数据。

E 安装

Docker

先准备一个文件夹(我是喜欢Caddy单独跑的,假如您喜欢用Docker跑也可以在这建立子文件夹):

1
2
3
mkdir -p ~/monitoring/data/{victoriametrics,grafana}
# 或者 mkdir -p ~/monitoring/data/{victoriametrics,grafana,caddy}
cd ~/monitoring

然后准备编写文件(nano docker-compose.yml):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
services:
  # VictoriaMetrics
  victoriametrics:
    container_name: victoriametrics
    image: victoriametrics/victoria-metrics:latest
    restart: always
    volumes:
      - ./data/victoriametrics:/storage
    ports:
      - '127.0.0.1:8428:8428'
    command:
      - "--storageDataPath=/storage"
      - "--retentionPeriod=1y"
      - "--httpListenAddr=:8428"

  # Grafana
  grafana:
    container_name: grafana
    image: grafana/grafana-oss:latest
    restart: always
    environment:
      - GF_SERVER_ROOT_URL=https://grafana.miyunda.com/
    volumes:
      - ./data/grafana:/var/lib/grafana
    ports:
      - '127.0.0.1:3000:3000'

⚠️ 注意端口一定不要绑在0.0.0.0上面,很难受。

喜欢用Docker跑Caddy的点这里
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
services:
  # VictoriaMetrics
  victoriametrics:
    container_name: victoriametrics
    image: victoriametrics/victoria-metrics:latest
    restart: always
    volumes:
      - ./data/victoriametrics:/storage
    ports:
      - '127.0.0.1:8428:8428'
    command:
      - "--storageDataPath=/storage"
      - "--retentionPeriod=1y"
      - "--httpListenAddr=:8428"

  # Grafana
  grafana:
    container_name: grafana
    image: grafana/grafana-oss:latest
    restart: always
    environment:
      - GF_SERVER_ROOT_URL=https://grafana.miyunda.com/
    volumes:
      - ./data/grafana:/var/lib/grafana
    ports:
      - '127.0.0.1:3000:3000'

  # Caddy
  caddy:
    container_name: caddy
    image: caddy:latest
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./data/caddy_data:/data
      - ./data/caddy_config:/config
      - ./data/caddy_log:/var/log/caddy

设置验证密码

我的VM当然不能随便来人就能推数据,得用个密码保护起来。VM自带很多功能,其中就包括vm_auth,我是不想研究那么多,就想弄个最简单的就行。我决定用Caddy自带的密码验证。

先想一个密码,然后下面命令会搞一个哈希值出来,也存起来。

1
2
3
caddy hash-password --plaintext <密码>
或者
docker run --rm caddy caddy hash-password --plaintext <密码>

ℹ️ 现代加密哈希算法在处理密码时会自动引入一个盐值(Salt),所以每次输入相同的密码也会得到不同的哈希值。

配置Caddy

1
2
3
sudo nano /etc/caddy/Caddyfile
或者
nano Caddyfile

它的内容类似这样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
    acme_ca https://acme.zerossl.com/v2/DV90
    email <ZeroSSL的注册邮件>
}

(log-common) {
    log {
        output file /var/log/caddy/{args[0]}.log {
            mode 0664
            roll_size 10mb
            roll_keep 20
            roll_keep_for 30d
        }
    }
}


victoriametrics.miyunda.com {
    basic_auth {
        push_homelab "$2a$14$L5马赛克马赛克马赛克Ts6NCRMjfFgLsy"
    }
    reverse_proxy 127.0.0.1:8428
    import log-common victoriametrics
}

grafana.miyunda.com {
    import log-common grafana
    reverse_proxy 127.0.0.1:3000
}

其中push_homelab那里可以搞多行,每行一个用户名密码——以后有多个数据来源时可以更容易分辨,理论上也更安全。

对外服务的域名那里换成您自己的。

前四行可以不要,Caddy默认的ACME是Let’s Encrypt,我只是更喜欢ZeroSSL而已。(套Cloudflare的话还有谷歌或者Let’s Encrypt签发的证书)

127.0.0.1使用Docker运行Caddy可以把这里换成容器名,利用Docker提供的内部解析。

另:Caddy 版本<v2.8.0的话是不支持basic_auth的,独立运行的可能得升级Caddy版本。用Docker运行Caddy的话没有这个烦恼。下面以Debian为例安装新版本Caddy:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
caddy version
sudo apt remove caddy
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy
caddy version
sudo mkdir -p /var/log/caddy
sudo chown caddy:caddy /var/log/caddy
sudo chmod 2750 /var/log/caddy
sudo usermod -aG caddy $USER
newgrp caddy

Cloudflare (可选,建议)

为了防止别人知道我们的服务器的真实地址,同时尽可能提升访问速度,我们请出赛博菩萨——Cloudflare。

此处需要先将您的域名解析(NS)委托给Cloudflare,请自行完成。

先去Cloudflare的Web控制台给您的两个网站建好CNAME记录,并开启代理。

然后去创建一个配置规则(Configuration Rule)。该规则的核心目的是针对 ACME HTTP-01 挑战(自动申请您的SSL证书)禁用“自动HTTPS重写”,以确保验证过程不被强制跳转干扰。

  1. 基础信息设置
  • 规则名称: 输入一个易于识别的名称,例如 allow acme http-01
  1. 匹配条件设置 (If incoming requests match…)

我们需要筛选出所有指向证书验证路径的请求:

  • 选择模式: 选中 Custom filter expression
  • 字段 (Field): 下拉选择 URI Path
  • 运算符 (Operator): 选择 contains(包含)。
  • 值 (Value): 输入 /.well-known/acme-challenge/*

注意: 预览框中显示的表达式应为:(http.request.uri.path contains "/.well-known/acme-challenge/*")

  1. 操作设置 (Then the settings are…)

在下方找到具体的设置选项,调整 Cloudflare 对匹配请求的处理方式:

  • Automatic HTTPS Rewrites (自动 HTTPS 重写): 将开关拨至 关闭 (Off) 状态。

如图:

Cloudflare

这样就可以避免基于HTTP 80端口的挑战流量被Cloudflare重定向到HTTPS 443端口。

启动

1
2
docker-compose up -d
sudo systemctl start caddy #独立运行的Caddy

试试

尝试在服务器上访问两个容器,回应应该都是200:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
curl -I http://127.0.0.1:8428/metrics
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Vary: Accept-Encoding
X-Server-Hostname: 4372bbd36de6
Date: Sun, 08 Mar 2026 15:07:03 GMT

curl -I http://127.0.0.1:3000/login
HTTP/1.1 200 OK
Cache-Control: no-store
Content-Type: text/html; charset=UTF-8
X-Content-Type-Options: nosniff
X-Frame-Options: deny
X-Xss-Protection: 1; mode=block
Date: Sun, 08 Mar 2026 15:02:50 GMT

有什么不对的话可以看看有没有侦听,也看看日志:

1
2
3
sudo ss -tulpn
docker logs grafana
docker logs victoriametrics

这时应该可以从外网访问两个新域名试试了。

F 使用

VM

用浏览器打开VM的域名,输入用户名密码之后可以查询数据库,不会查询的可以去看仪表板(Dashboards)。

家里的Prometheus

编辑家里的Prometheus配置文件,找到这样的几行:

1
2
3
4
- url: https://prometheus-prod-10-prod-us-central-0.grafana.net/api/prom/push
  basic_auth:
    username: 888898
    password: glc_eyJvIjoi马赛克马赛克马赛克DQ1ZURyTVkiLCJtIjp7InIiOiJ1cyJ9fQ==

把他们都注释掉。然后在remote_write:下面添加这样的几行:

1
2
3
4
- url: https://<您自己的VM的FQDN>/api/v1/write
  basic_auth:
    username: <用户名>
    password: <密码>

然后重启服务即可:

1
2
3
sudo systemctl restart prometheus
sudo systemctl status prometheus
sudo journalctl -u prometheus -f

exporter那些不用动,因为没有变化,只是推送的去处从云服务变成自建的。

看看有没有收到数据

在VM的Web界面左上角的查询输入框里输入下面任意一条 PromQL 查询,然后点 Execute(或回车),这里的"jobname"必须存在于家里的Prometheus的配置文件中的scrape_configs: - job_name:里面。

  • up{job=“jobname”} (如果返回 1 或有数值,说明 exporter 正常被刮削,数据正在进来)

  • count({job=“jobname”})(看总指标数量,数字 > 0 就说明正在接收)

下图为我家某个路由器的累计CPU时间。

openwrt cpu_seconds_total

也可以访问https://<VM的FQDN>/vmui/#/metrics,这里能浏览所有jobname。

Grafana

浏览器访问Grafana的FQDN,先创建用户名密码,不多说了。

数据源

然后添加一个数据源,其中类型为Prometheus!!! 不要选VictoriaMetrics !!!

地址填容器名和端口就行了——比回环地址好看点。

如图:

Grafana datasource

仪表板

这个不多说了,原来在官方云上添加的仪表板,现在添加到自建的,是一样的,可以去https://grafana.com/grafana/dashboards/查看。

如图,一个闲置的小主机,安装了几个虚拟机玩过家家用的。

Grafana dashboard


好了,看过就等于会了。感谢观看🥰

接下来还将加入收集日志的功能,敬请期待。

0%