---
title: Terraform-провайдер Pingvera — мониторинг как код
description: Официальный Terraform-провайдер pingvera/pingvera в реестре HashiCorp — заводите мониторы и статус-страницы в том же plan/apply, что и остальную инфраструктуру. Плюс pingvera terraform generate — выгрузка уже существующего кабинета в HCL за одну команду.
source: https://pingvera.ru/blog/terraform-provider-monitoring-kak-kod.html
---
# Terraform-провайдер Pingvera: мониторинг как код

Сервер заводится в Terraform. DNS-запись — в Terraform. База данных, сеть, права доступа — тоже. А монитор для этого же сервера почему-то заводится руками, через веб-форму, в отдельной вкладке, отдельным человеком, который вспомнил об этом на следующий день после релиза. Разрыв не архитектурный, а организационный — но именно он оставляет прод без наблюдения в первые часы после раскатки. Мы закрыли его официальным Terraform-провайдером: `pingvera/pingvera` опубликован в Terraform Registry, и монитор заводится тем же `terraform apply`, что и сама инфраструктура.

## Провайдер в реестре, не заготовка

Провайдер зарегистрирован в публичном Terraform Registry под адресом `pingvera/pingvera` — ставить его в проект так же, как любой провайдер AWS или Cloudflare: указать `source` в `required_providers`, и Terraform сам скачает нужную платформу и проверит GPG-подпись релиза при `terraform init`. Никаких `dev_overrides` и локальной сборки — это готовый к использованию плагин, а не внутренний прототип.

`terraform {
 required_providers {
 pingvera = {
 source = "pingvera/pingvera"
 version = "~> 0.1"
 }
 }
}

provider "pingvera" {
 # endpoint по умолчанию https://app.pingvera.ru (RU-инстанс)
 # для EN-инстанса: endpoint = "https://app.pingvera.com"
}`
 Токен передаётся через переменную окружения `PINGVERA_TOKEN` — атрибут `token` в конфигурации можно не указывать вовсе, и тогда в `.tf`-файлах секрета просто нет:

`export PINGVERA_TOKEN=pv_...
terraform apply`

 Два ресурса, никакой лишней логики
 Провайдер сознательно устроен просто: это клиент уже существующего write-API хаба (`/api/v1/monitors`, `/api/v1/status-pages`), а не отдельный слой бизнес-правил. Квоты тарифа, валидация полей, лимиты на количество сайтов — всё это по-прежнему считает сервер, провайдер лишь передаёт запрос и синхронизирует состояние.

`pingvera_monitor` — монитор любого из типов, что есть в дашборде: `http`, `tcp`, `dns`, `tls`, `wp`, `domain`, `links`, `heartbeat`. Обязательные поля — `type` и `target`, они неизменяемы после создания (правка требует пересоздания ресурса, как замена диска в облаке): нельзя молча превратить HTTP-монитор в TCP тем же `id`. Остальное — интервал, порог срабатывания, латентность деградации, теги, а для типов со своими настройками (например, `wp`) — сырой JSON в поле `config`.

`resource "pingvera_monitor" "site" {
 type = "http"
 name = "Основной сайт"
 target = "https://example.com"

 interval_s = 60
 fail_threshold = 2
 degraded_latency_ms = 800

 tags = ["prod", "website"]

 config = jsonencode({
 fail_on_4xx = true
 })
}

resource "pingvera_monitor" "db" {
 type = "tcp"
 name = "PostgreSQL"
 target = "db.example.com:5432"
}`
 `pingvera_status_page` — публичная статус-страница: слаг, заголовок, тема (в том числе тёмная), список привязанных мониторов, брендирование под свой цвет и текст в подвале. Список мониторов — это ссылки на другие ресурсы в том же конфиге, поэтому связь «статус-страница показывает вот эти три монитора» тоже становится кодом, а не ручным чекбоксом в дашборде:

`resource "pingvera_status_page" "public" {
 slug = "example"
 title = "Статус example.com"
 theme = "dark"

 monitors = [
 pingvera_monitor.site.id,
 pingvera_monitor.db.id,
 ]

 brand_color = "#4f46e5"
 footer_md = "Вопросы — support@example.com"
}`

 Почему это не просто «ещё один способ настроить»
 Ценность IaC-подхода к мониторингу не в том, что HCL красивее веб-формы. Она в том, что монитор перестаёт быть отдельным действием, про которое можно забыть, и становится частью того же ревью, того же `plan`, того же `apply`, что и остальная инфраструктура. Заводите новый сервис в проекте — в том же пул-реквесте, рядом с ресурсом сервера или DNS-записью, добавляете `pingvera_monitor` на его health-check. Ревьюер видит оба изменения одним диффом: «добавили сервис» и «добавили за ним присмотр» — это одна логическая единица, а не два действия, разнесённые по разным интерфейсам и людям.

Для агентства, ведущего инфраструктуру нескольких клиентов через Terraform-модули, это ещё и способ не плодить расхождения между окружениями. Модуль «типовой WordPress-сайт клиента» может сразу включать нужный набор мониторов и статус-страницу — применили модуль к новому клиенту, получили не только сервер, но и наблюдение за ним, с одинаковыми порогами и одинаковой конвенцией именования для всех.

## Уже есть мониторы в дашборде — переписывать не нужно

Самое частое возражение против IaC для существующей системы — «а у меня уже двадцать мониторов настроены руками, не пересоздавать же их». Не нужно: в [CLI](https://pingvera.ru/blog/cli-pingvera-monitoring-iz-terminala.html) есть команда `pingvera terraform generate`, которая читает read-API кабинета и печатает готовый `.tf` с блоками `resource "pingvera_monitor"` и `resource "pingvera_status_page"` — и сразу с `import`-блоками на каждый ресурс (config-driven import, доступен с Terraform 1.5+), включая уже расставленные ссылки между статус-страницами и их мониторами.

`export PINGVERA_TOKEN=pv_...
pingvera terraform generate --out pingvera.tf

terraform init
terraform apply # применит import-блоки, свяжет state с существующими ресурсами
terraform plan # ноль изменений — это и есть цель generate`
 После этого `terraform plan` должен не показать вообще никакого дрейфа — сгенерированный код описывает ровно то, что уже стоит в кабинете. Это не приближение и не «почти совпадает»: цель команды — получить состояние Terraform, которое с первого же прогона синхронно с реальностью, без ручной подгонки атрибутов после генерации.

## Что нужно для работы

Провайдер использует Terraform Plugin Framework и протокол 6.0 — подходит любой Terraform CLI версии 1.0 и новее. Для `terraform import`-блоков, которые печатает `pingvera terraform generate`, нужен Terraform 1.5+ (более ранние версии умеют импортировать только командой `terraform import` вручную, по одному ресурсу). Аутентификация — Bearer-токен из дашборда с нужными скоупами: `write:monitors` для управления мониторами, `write:status-pages` — для статус-страниц. Организация определяется самим токеном и нигде отдельно не передаётся.

## Что не входит в провайдер

Провайдер намеренно не тянет на себя то, что уже решено на уровне сервиса. Тарифные лимиты, проверку прав, антифрод — всё это делает хаб при обработке запроса, а не Terraform-схема; провайдер вернёт ровно ту ошибку API, что прислал сервер. Каналы уведомлений (Telegram, email, [вебхуки](https://pingvera.ru/blog/podpisannye-vebhuki.html)) пока в схему не входят — сегодня это ресурсы для мониторов и статус-страниц, расширение на остальные сущности кабинета возможно позже, но не обещано датой.

## Главное

Terraform-провайдер не меняет то, как работает мониторинг Pingvera — он меняет то, где живёт решение его завести. Вместо отдельного шага «не забыть поставить монитор после деплоя» — строчка в том же файле, что описывает сам сервис, под тем же ревью и с той же историей изменений в git. А если мониторинг уже настроен через дашборд — `pingvera terraform generate` заберёт его под управление кодом за одну команду, без переписывания вручную и без риска расхождения между тем, что реально стоит, и тем, что описано в конфигурации.

## Частые вопросы

**Что умеет провайдер — какие у него ресурсы?**

Два ресурса: `pingvera_monitor` (тип http/tcp/dns/tls/wp/domain/links/heartbeat, цель, интервал, пороги, теги, произвольный JSON-конфиг типа) и `pingvera_status_page` (slug, заголовок, тема, список привязанных мониторов, брендирование). Провайдер — чистый клиент write-API хаба, без своей бизнес-логики: квоты и тарифы проверяет сервер.

**Как перенести уже существующий мониторинг в Terraform без ручного переписывания?**

Командой `pingvera terraform generate` из CLI: она читает read-API кабинета и печатает готовый `.tf` с resource-блоками и import-блоками (Terraform 1.5+) на каждый монитор и статус-страницу, уже со связями между ними. После `terraform apply` состояние привязывается к существующим ресурсам, и первый `terraform plan` показывает ноль изменений.

**Где взять токен для провайдера и какие нужны скоупы?**

В дашборде: Настройки → API-токены. Токену нужны скоупы `write:monitors` и/или `write:status-pages` в зависимости от того, какими ресурсами управляет конфигурация. Токен передаётся через переменную окружения `PINGVERA_TOKEN` — в `.tf` его хранить не стоит.
