Перейти к основному содержанию
Скидка 50% все планы, ограниченное время. Начиная от $2.48/mo
14 min left
Инструменты разработчика и DevOps

Настройка стека мониторинга Grafana + Prometheus на вашем VPS (руководство по Docker Compose)

C Автор: Chike 14 мин чтения
Prometheus and Grafana monitoring stack illustration: a central dashboard panel showing Prometheus and Grafana logos over metric graphs, with three server nodes feeding metrics into it

Если вы пока не знаете, что такое Prometheus и Grafana, прочитайте нашу статью о Prometheus против Grafana. Если разницу вы уже знаете, вот как запустить их вместе.

Эта статья — практическое дополнение. Она разворачивает Prometheus, Grafana и Node Exporter на одном VPS с помощью Docker Compose, ставит перед Grafana HTTPS через Caddy, импортирует дашборд Node Exporter Full (ID 1860) и показывает, как собирать метрики со второго VPS через WireGuard.

Изначальный тест в апреле 2026 года выполнялся на Ubuntu 24.04 LTS с Docker Engine 27.x и Docker Compose v2.30. Версии, закреплённые в конфигурации ниже, с тех пор обновлены до актуальных поддерживаемых выпусков. В том первом тесте с пятью хостами хаб потреблял примерно 300 МБ ОЗУ в простое и от 530 до 650 МБ при постоянном сборе метрик.

Кратко (TL;DR)

  • На VPS-хабе Prometheus, Grafana и Node Exporter работают в одном стеке Compose, а Caddy установлен на хосте как обратный прокси.
  • Prometheus и Grafana слушают только 127.0.0.1. Публичный доступ идёт через Caddy с автоматическим HTTPS.
  • Добавляйте новые серверы, устанавливая на каждый Node Exporter и дописывая записи в prometheus.yml.
  • WireGuard — рекомендуемый сетевой канал между хабом и узлами. Приватная сеть хорошо подходит, когда ваши серверы уже находятся в одной частной сети.
  • Для теста с пятью хостами ниже хватило VPS с 2 ГБ, но воспринимайте это как ориентир, а не как жёсткое правило по количеству хостов.

Что вы построите

Diagram of monitoring traffic boundaries: ports 80 and 443 are public, Grafana on 3000, Prometheus on 9090 and Node Exporter on 9100 stay on loopback, and a remote Node Exporter on 10.10.0.2:9100 is reachable only over the private network

Вот как в общих чертах будет выглядеть готовая установка.

                 +-------------------+
                 |  Your laptop      |
                 +---------+---------+
                           | HTTPS
                           v
+--------------------------+----------------------------+
| MONITORING HUB VPS    (2 GB RAM starting point) |
|  Caddy        (reverse proxy, auto HTTPS)             |
|  Grafana      (port 3000, only via Caddy)             |
|  Prometheus   (port 9090, internal only)              |
|  Node Exporter (port 9100, scraped on localhost)      |
+----+---------------------------------+----------------+
     |                                 |
     | scrape over WireGuard           | scrape over WG
     v                                 v
+----+--------+                  +-----+-------+
|  App VPS 1  |                  |  App VPS 2  |
|  Node Expo. |                  |  Node Expo. |
+-------------+                  +-------------+

Весь стек мониторинга живёт на одном VPS-хабе. На каждом остальном VPS, который вы хотите наблюдать, работает только Node Exporter. Prometheus на хабе забирает метрики с каждого из них. Grafana их отображает. Caddy отвечает за HTTPS.

Что понадобится

Для описанной конфигурации нужны один VPS с Ubuntu под хаб, домен и доступ через sudo.

  • VPS с не менее чем 2 ГБ ОЗУ под управлением Ubuntu 24.04 LTS.
  • Доменное имя с A-записью, указывающей на публичный IP-адрес VPS (например, grafana.example.com). Необходимо для HTTPS.
  • Доступ root или sudo по SSH.

По всему руководству заменяйте grafana.example.com на тот поддомен, который вы действительно направили на свой VPS мониторинга. Используйте один и тот же домен в переменной окружения Grafana, при проверке DNS и в Caddyfile.

Если вы хотите наблюдать только за одним сервером и HTTPS вам пока не нужен, запустите стек Compose на уже имеющемся VPS без раздела про обратный прокси. Остальная часть руководства остаётся в силе.

Развернуть Ubuntu VPS

Запустите Ubuntu VPS мгновенно с root-доступом и хранилищем NVMe.

Развернуть Ubuntu VPS

Шаг 1. Подготовка сервера

Подключитесь по SSH к VPS-хабу под пользователем с правами sudo. Сначала обновите систему.

sudo apt update && sudo apt upgrade -y

Установите Docker Engine и плагин Compose из официального репозитория Docker.

# Install prerequisites
sudo apt install -y ca-certificates curl gnupg lsb-release

# Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the Docker repository
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Убедитесь, что оба компонента установлены.

docker --version
docker compose version

Обе команды должны без ошибок вывести версию. Конкретные версии Docker Engine и Compose будут зависеть от того, что предлагает официальный репозиторий на момент установки.

sudo usermod -aG docker $USER

Прежде чем продолжать, выйдите из сессии и войдите заново, чтобы членство в новой группе вступило в силу. Группа docker фактически даёт права уровня root, поэтому добавляйте в неё только доверенных администраторов.

Настройте UFW так, чтобы на хабе мониторинга были разрешены SSH, HTTP и HTTPS. Порт 80 нужен для перенаправления с HTTP на HTTPS и проверки ACME. Сама Grafana остаётся за Caddy.

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status

Не открывайте порты 3000, 9090 и 9100 в интернет. Сервисы мониторинга слушают 127.0.0.1 не просто так.

Шаг 2. Стек Compose

Создайте каталог для стека и конфигурации Prometheus.

mkdir -p ~/monitoring/prometheus
cd ~/monitoring

Создайте файл Compose.

# ~/monitoring/docker-compose.yml
services:
  prometheus:
    image: prom/prometheus:v3.13.2
    container_name: prometheus
    restart: unless-stopped
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=15d'
      - '--web.enable-lifecycle'
      - '--web.listen-address=127.0.0.1:9090'
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus_data:/prometheus
    network_mode: host
  node-exporter:
    image: prom/node-exporter:v1.12.1
    container_name: node-exporter
    restart: unless-stopped
    pid: host
    network_mode: host
    command:
      - '--path.rootfs=/host'
      - '--web.listen-address=127.0.0.1:9100'
      - '--collector.filesystem.mount-points-exclude=^/(dev|proc|sys|var/lib/docker/.+|var/lib/kubelet/.+)($$|/)'
    volumes:
      - '/:/host:ro,rslave'
  grafana:
    image: grafana/grafana:13.1.3
    container_name: grafana
    restart: unless-stopped
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
      - GF_USERS_ALLOW_SIGN_UP=false
      - GF_SERVER_ROOT_URL=https://grafana.example.com
      - GF_SERVER_HTTP_ADDR=127.0.0.1
    volumes:
      - grafana_data:/var/lib/grafana
    network_mode: host
    depends_on:
      - prometheus
volumes:
  prometheus_data:
  grafana_data:

Теперь создайте конфигурацию Prometheus.

# ~/monitoring/prometheus/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s
  external_labels:
    monitor: 'monitoring-hub'
scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['127.0.0.1:9090']
  - job_name: 'node'
    static_configs:
      - targets: ['127.0.0.1:9100']
        labels:
          host: 'monitoring-hub'

Создайте файл .env с паролем администратора Grafana. Возьмите надёжный пароль. Не добавляйте этот файл в git.

cat > ~/monitoring/.env <<'EOF'
GRAFANA_ADMIN_PASSWORD='replace-with-a-strong-password'
EOF
chmod 600 ~/monitoring/.env

Несколько флагов выше заслуживают пояснения.

  • --web.listen-address=127.0.0.1:9090 заставляет Prometheus слушать только петлевой интерфейс хоста. Порт 9090 остаётся вне публичной сети, но по-прежнему доступен для Grafana и локального администрирования.
  • --web.enable-lifecycle включает POST /-/reload, благодаря чему изменения конфигурации Prometheus применяются без перезапуска контейнера.
  • pid: host, network_mode: host, монтирование корня хоста и --path.rootfs=/host дают Node Exporter в контейнере нужный контекст хоста вместо того, чтобы он видел только собственное окружение контейнера.
  • GF_USERS_ALLOW_SIGN_UP=false запрещает посетителям самостоятельно создавать учётные записи Grafana. Приватной от этого Grafana не становится: страница входа по-прежнему доступна публично через Caddy.

Совет: Если ручная установка вам не по душе, у Cloudzy есть развёртывание в один клик для Grafana и Prometheus . Развёртывание Prometheus может заодно установить и Node Exporter.

Шаг 3. Первый запуск и проверка

Поднимите стек.

cd ~/monitoring
docker compose up -d

Подождите несколько секунд и проверьте, что все три контейнера работают.

docker compose ps

Все три сервиса должны быть в состоянии running.

Откройте SSH-туннель со своего ноутбука, чтобы проверить страницу целей Prometheus.

ssh -L 9090:localhost:9090 your-user@your-vps-ip

Затем откройте в браузере http://localhost:9090/targets. Вы должны увидеть две цели, обе в состоянии UP:

prometheus            UP    http://127.0.0.1:9090/metrics
node                  UP    http://127.0.0.1:9100/metrics

Если хотя бы одна в состоянии DOWN, перейдите к разделу «Частые проблемы». Не продолжайте, пока обе не станут UP.

Закройте туннель, когда закончите проверять цели. Снаружи VPS Prometheus останется доступен только через этот SSH-туннель. На следующем шаге мы откроем Grafana по HTTPS.

Шаг 4. Обратный прокси с HTTPS на Caddy

Caddy — это один бинарник. HTTPS он настраивает автоматически. Для обратного прокси на один сайт его конфигурация короче эквивалентного блока Nginx.

Установите 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 chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy

Перед следующим шагом убедитесь, что A-запись DNS для grafana.example.com указывает на публичный IP-адрес VPS. Без этого проверка ACME не пройдёт.

dig +short grafana.example.com
# Should print the VPS public IP

Отредактируйте Caddyfile.

# /etc/caddy/Caddyfile
grafana.example.com {
    reverse_proxy 127.0.0.1:3000
    encode gzip
}

Перезагрузите конфигурацию Caddy.

sudo systemctl reload caddy

Caddy автоматически получает и продлевает публично доверенные TLS-сертификаты через ACME, как только домен указывает на ваш сервер, а порты 80 и 443 доступны. Откройте в браузере https://grafana.example.com: вы должны увидеть страницу входа Grafana по действующему HTTPS-соединению. Войдите под именем admin с паролем из файла .env.

Шаг 5. Добавляем Prometheus как источник данных и импортируем дашборд 1860

В интерфейсе Grafana перейдите в Подключения > Data sources > Add data source и выберите Prometheus.

Укажите такой URL:

http://127.0.0.1:9090

В этой конфигурации Grafana и Prometheus используют сеть хоста, при этом Prometheus слушает только петлевой интерфейс. Нажмите Save & test и убедитесь, что Grafana может обращаться к API Prometheus. Должно появиться сообщение «Successfully queried the Prometheus API».

Теперь импортируем дашборд. Node Exporter Full (ID 1860, автор rfmoz) — широко используемый общественный дашборд для метрик Node Exporter. Он охватывает процессор, память, дисковый ввод-вывод, сеть, файловые дескрипторы и температуры оборудования, если хост их отдаёт. В нём есть переменные job и instance, поэтому схема «хаб и спицы» работает без доработок.

Перейти к Dashboards > Новинка > Import dashboard, введите ID дашборда 1860, выберите свой источник данных Prometheus и импортируйте его.

Дашборд должен заполниться, как только цель Node Exporter перейдёт в состояние UP. Для части панелей дашборд 1860 использует метрики необязательных коллекторов systemd и processes, поэтому одна пустая панель ещё не означает, что цель сломана.

Шаг 6. Добавляем второй VPS (схема «хаб и спицы»)

Прежде чем запускать Node Exporter, убедитесь, что приватный IP-адрес, к которому вы собираетесь его привязать, уже существует на втором VPS. Если вы используете WireGuard, сначала завершите его настройку.

На втором VPS установите Docker по той части шага 1, где описана установка Docker, но не открывайте порты 80 и 443 только ради мониторинга. Затем запустите один только Node Exporter.

mkdir -p ~/node-exporter
cd ~/node-exporter

cat > docker-compose.yml <<'EOF'
services:
  node-exporter:
    image: prom/node-exporter:v1.12.1
    container_name: node-exporter
    restart: unless-stopped
    pid: host
    command:
      - '--path.rootfs=/host'
      - '--web.listen-address=10.10.0.2:9100'  # bind to the private monitoring IP, never 0.0.0.0
    volumes:
      - '/:/host:ro,rslave'
    network_mode: host
EOF

docker compose up -d

Замените 10.10.0.2 на приватный IP-адрес этого сервера для мониторинга. Если вы используете WireGuard, возьмите его WireGuard-адрес. Если используете приватную сеть Cloudzy, возьмите IP приватного интерфейса VPS. Если на этом VPS уже включён UFW, разрешите доступ к Node Exporter только хабу мониторинга. Например, если приватный IP хаба 10.10.0.1:

sudo ufw allow proto tcp from 10.10.0.1 to any port 9100
sudo ufw status

Замените 10.10.0.1 на реальный приватный IP хаба. Если UFW выключен, явно заданный --web.listen-address по-прежнему держит Node Exporter вне публичного интерфейса, но другие машины, имеющие доступ к этой приватной сети, тоже смогут достучаться до порта 9100.

Два хороших варианта сетевого канала между хабом и узлами:

  1. Сеть WireGuard. Каждый VPS подключается к сети WireGuard, а Prometheus опрашивает приватные адреса. Это самый безопасный вариант после первоначальной настройки WireGuard. Мы предлагаем WireGuard как развёртывание в один клик, а ещё у нас есть готовое руководство по настройке по нему.
  2. Приватная сеть Cloudzy. Инстансы VPS Cloudzy в одном регионе получают приватный интерфейс для трафика «восток-запад», поэтому вы можете опрашивать этот адрес вместо того, чтобы поднимать отдельный туннель WireGuard.

Когда Node Exporter заработает на втором VPS и станет доступен по приватному IP, замените существующий job node в файле prometheus.yml на хабе приведённым ниже блоком.

# Update the existing 'node' job in ~/monitoring/prometheus/prometheus.yml
  - job_name: 'node'
    static_configs:
      - targets: ['127.0.0.1:9100']
        labels:
          host: 'monitoring-hub'
      - targets: ['10.10.0.2:9100']
        labels:
          host: 'app-vps-1'
          tier: 'production'

Перезагрузите конфигурацию Prometheus без перезапуска контейнера.

curl -X POST http://localhost:9090/-/reload

Снова откройте SSH-туннель из шага 3 и зайдите на http://localhost:9090/targets. Новая цель должна отображаться как UP. Откройте дашборд Node Exporter Full, переключите переменную instance вверху на новый сервер, и вы увидите его графики.

Потребление ресурсов и когда пора расширяться

Observed five-host baseline from the April 2026 test: Prometheus 250 to 350 MB, Grafana 200 MB, Caddy 40 MB, hub Node Exporter 15 to 20 MB, total hub 530 to 650 MB RAM on a 2 GB VPS with a 1.5 GB fifteen-day working set

Эти цифры взяты из первоначального теста в апреле 2026 года на VPS с Ubuntu и 2 ГБ памяти при пяти наблюдаемых хостах. Считайте их ориентиром для такой нагрузки, а не гарантией размера для более новых версий.

КомпонентRAM в простоеОЗУ под нагрузкой (1 хост)ОЗУ при 5 хостахДиск (хранение 15 дней, 5 хостов)
Prometheus~100 MB~150 MB~250-350 МБ~500 МБ до 1,5 ГБ
Grafana~150 MB~180 MB~200 MB~50 MB
Node Exporter~15 МБ~20 МБне применимопренебрежимо мало
Caddy~30 MB~40 МБ~40 МБне применимо
Всего на хабе~300 МБ~390 МБ~530-650 МБ~1,5 ГБ рабочего набора

Расширяйтесь, когда хабу начинает не хватать памяти или запаса на диске. Само по себе число хостов — плохой ориентир для выбора размера, потому что на потребление влияют кардинальность серий, включённые коллекторы, интервал сбора и срок хранения. Для долговременного централизованного хранения Prometheus поддерживает интеграции с удалёнными хранилищами. VictoriaMetrics — один из совместимых с Prometheus вариантов.

Частые проблемы

Семь самых частых проблем и способы их устранения.

  1. Prometheus доступен из публичного интернета. Обычный проброс порта 9090:9090 открывает Prometheus всему миру. Решение: оставьте --web.listen-address=127.0.0.1:9090 в команде Prometheus, как показано выше. Тогда Prometheus слушает только петлевой интерфейс хоста.
  2. Источник данных Grafana не может достучаться до Prometheus. Этот стек использует сеть хоста, поэтому Grafana обращается к Prometheus по адресу http://127.0.0.1:9090. Проверьте, что Prometheus запущен и по-прежнему слушает петлевой интерфейс.
  3. Дашборд Node Exporter показывает «No data». Три обычные причины. (a) Prometheus не опрашивает цель. Проверьте /targets. (b) Метка job в переменной дашборда не совпадает с job_name в конфигурации сбора. (c) Файрвол блокирует порт 9100 между хабом и целью.
  4. Пароль администратора Grafana остался admin/admin в продакшене. Задайте GF_SECURITY_ADMIN_PASSWORD из файла .env ещё до первого запуска. Если вы это упустили, смените пароль при первом входе и отключите саморегистрацию.
  5. Caddy сообщает «ACME challenge failed». A-запись DNS ещё не распространилась либо порт 80 заблокирован. Выполните ufw allow 80,443/tcp, дождитесь распространения DNS и выполните sudo systemctl reload caddy. Используйте dig +short , чтобы подтвердить распространение.
  6. Диск под Prometheus заполняется. Метки с высокой кардинальностью или короткие интервалы сбора при большом числе хостов быстро забивают том. Следите за prometheus_tsdb_head_series и размером тома. Что можно сделать: отключить неиспользуемые коллекторы Node Exporter, увеличить scrape_interval до 30s или сократить срок хранения.
  7. Ошибки прав доступа при bind-монтировании. Если вы монтируете каталог хоста вместо именованного тома, UID контейнера (65534 для Prometheus, 472 для Grafana) должен иметь права на запись. Именованные тома, как в файле Compose выше, снимают эту проблему.

Когда этот стек избыточен

Если всё, что вам нужно, — уведомление о том, что URL перестал отвечать, этот стек избыточен. Uptime Kuma гораздо легче и подойдёт лучше, если вам нужны только базовые проверки доступности.

Часто задаваемые вопросы

В чём разница между Prometheus и Grafana?

Prometheus — это база данных временных рядов: она собирает метрики с настроенных целей с заданным вами интервалом, хранит их на диске и отвечает на запросы PromQL. Grafana — слой визуализации, который подключается к Prometheus (и ко многим другим источникам) и рисует дашборды. Почти всегда нужны оба: Prometheus собирает и хранит, Grafana показывает.

Сколько оперативной памяти нужно связке Prometheus + Grafana?

Хаб мониторинга, на котором в пределах одного VPS работают Prometheus, Grafana, Node Exporter и обратный прокси, потребляет примерно 300 МБ ОЗУ в простое и от 530 до 650 МБ при активном сборе метрик с пяти хостов каждые 15 секунд.

Можно ли следить за несколькими серверами из одного экземпляра Grafana?

Да. Стандартная схема — «хаб и спицы». Один экземпляр Prometheus на VPS-хабе опрашивает Node Exporter, работающий на каждом другом сервере, за которым вы хотите следить. Grafana на хабе обращается к этому единственному Prometheus. В дашборде Node Exporter Full (ID 1860) есть переменная instance, поэтому переключаться между серверами можно прямо в одном дашборде.

Какой дашборд Grafana лучше всего подходит для Node Exporter?

Для такой конфигурации Node Exporter Full (дашборд ID 1860 от rfmoz) — отличный выбор по умолчанию. Он охватывает основные хостовые метрики Node Exporter и поддерживает переменные job и instance для наблюдения за несколькими серверами. Часть панелей зависит от необязательных коллекторов Node Exporter, поэтому одна пустая панель ещё не значит, что цель сбора сломана.

Как открыть Grafana по HTTPS?

Запустите Grafana с привязкой к 127.0.0.1:3000 и поставьте перед ней обратный прокси, который возьмёт на себя HTTPS. Проще всего с Caddy: Caddyfile из четырёх строк с reverse_proxy 127.0.0.1:3000 и блоком домена делает всё, включая автоматическое управление TLS-сертификатами.

Бесплатны ли Prometheus и Grafana для коммерческого использования?

Prometheus распространяется по лицензии Apache 2.0. Grafana OSS — под AGPLv3. Внутреннее и коммерческое использование немодифицированной Grafana OSS разрешено, но её изменение, распространение или предоставление модифицированной версии по сети может повлечь обязательства по раскрытию исходного кода в рамках AGPL. Grafana Enterprise и Grafana Cloud работают по отдельным коммерческим условиям.

Когда стоит переходить с Prometheus на VictoriaMetrics?

Присмотритесь к VictoriaMetrics, когда более долгое хранение, высокая кардинальность серий или несколько экземпляров Prometheus затрудняют эксплуатацию локальной TSDB Prometheus в рамках памяти и диска вашего сервера. VictoriaMetrics умеет принимать данные Prometheus и предоставляет совместимый с Prometheus API запросов, поэтому может работать как долговременное хранилище или как бэкенд метрик для Grafana. Проверьте её на своей нагрузке, а не переключайтесь по фиксированному порогу ОЗУ.

Поделиться

Ещё в блоге

Читайте дальше.

Готовы к развёртыванию? От $2,48/мес.

Независимое облако с 2008 года. AMD EPYC, NVMe, 40 Gbps. Возврат денег в течение 14 дней.