Infrastructure-as-code teams spend considerable effort ensuring their deployments are repeatable and version-controlled. A load balancer, an RDS cluster, a Kubernetes ingress — all defined in Terraform, applied consistently across environments. But most of those teams still add uptime monitors by hand: log into a dashboard, click around, paste a URL.
That breaks the IaC contract. Monitors created manually diverge from the infrastructure they watch. URLs get stale when services move. Someone deletes a monitor during a sprint and nobody notices until three months later when an outage goes undetected.
The fix is to provision Vigilmon monitors as Terraform resources alongside the infrastructure they monitor. When a service is created, its monitor is created. When a service is destroyed, its monitor is destroyed. When the URL changes, the monitor URL changes automatically on the next terraform apply.
This tutorial walks through that pattern.
What You'll Build
- Terraform resources that provision Vigilmon HTTP monitors via the Vigilmon REST API
- A reusable module for common monitoring patterns
- Automatic monitor creation and teardown tied to your infrastructure lifecycle
Prerequisites
- Terraform 1.4+ installed
- A Vigilmon account at vigilmon.online
- A Vigilmon API key (Settings → API Keys in the Vigilmon dashboard)
- An existing Terraform project (any provider: AWS, GCP, Azure, etc.)
Step 1: Get Your Vigilmon API Key
In the Vigilmon dashboard, go to Settings → API Keys and create a new key with write access. Store it securely — you'll pass it to Terraform as an environment variable, never hardcode it in your .tf files.
export VIGILMON_API_KEY="your-api-key-here"
Add this to your CI/CD environment and your local shell profile (e.g., ~/.zshrc).
Step 2: Use the http Provider to Call Vigilmon's API
Terraform doesn't have an official Vigilmon provider yet, but the hashicorp/http provider lets you make HTTP API calls directly. For creating and deleting monitors, combine it with null_resource and local-exec provisioners.
A cleaner pattern is to use Terraform's restapi community provider, which maps REST API resources into Terraform resource lifecycles (create, read, update, destroy).
Configure the restapi provider
# terraform.tf
terraform {
required_providers {
restapi = {
source = "Mastercard/restapi"
version = "~> 1.18"
}
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "restapi" {
uri = "https://vigilmon.online"
write_returns_object = true
headers = {
Authorization = "Bearer ${var.vigilmon_api_key}"
Content-Type = "application/json"
}
}
provider "aws" {
region = var.aws_region
}
# variables.tf
variable "vigilmon_api_key" {
description = "Vigilmon API key — pass via TF_VAR_vigilmon_api_key or -var flag"
type = string
sensitive = true
}
variable "aws_region" {
default = "eu-west-1"
}
Step 3: Provision Infrastructure and Monitors Together
Here's a complete example: an AWS ECS service behind an ALB, with a Vigilmon HTTP monitor created in the same Terraform root module.
# ecs.tf — your existing infrastructure (simplified)
resource "aws_lb" "api" {
name = "api-alb"
internal = false
load_balancer_type = "application"
subnets = var.public_subnet_ids
}
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.api.arn
port = 443
protocol = "HTTPS"
certificate_arn = var.acm_cert_arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.api.arn
}
}
# monitors.tf — Vigilmon monitors created alongside the infrastructure
resource "restapi_object" "api_monitor" {
path = "/api/monitors"
id_attribute = "id"
data = jsonencode({
name = "API - ${var.environment}"
url = "https://${aws_lb.api.dns_name}/health"
type = "http"
interval = 60
timeout = 10
expected_status = 200
alert_channels = var.vigilmon_alert_channel_ids
tags = ["terraform", var.environment, "api"]
})
depends_on = [aws_lb_listener.https]
}
When you run terraform apply, Vigilmon's API creates the monitor. When you run terraform destroy, the restapi_object destroy lifecycle deletes the monitor from Vigilmon automatically.
Step 4: Build a Reusable Monitor Module
For teams with multiple services, a reusable module enforces consistency. Create modules/vigilmon-http-monitor/:
# modules/vigilmon-http-monitor/main.tf
terraform {
required_providers {
restapi = {
source = "Mastercard/restapi"
version = "~> 1.18"
}
}
}
resource "restapi_object" "monitor" {
path = "/api/monitors"
id_attribute = "id"
data = jsonencode({
name = var.name
url = var.url
type = "http"
interval = var.interval
timeout = var.timeout
expected_status = var.expected_status
alert_channels = var.alert_channel_ids
tags = var.tags
})
}
output "monitor_id" {
value = restapi_object.monitor.id
}
# modules/vigilmon-http-monitor/variables.tf
variable "name" { type = string }
variable "url" { type = string }
variable "interval" { type = number; default = 60 }
variable "timeout" { type = number; default = 10 }
variable "expected_status" { type = number; default = 200 }
variable "alert_channel_ids" { type = list(string); default = [] }
variable "tags" { type = list(string); default = [] }
Now any service team can add monitoring in three lines:
module "payments_monitor" {
source = "../../modules/vigilmon-http-monitor"
name = "Payments API - prod"
url = "https://${module.payments_service.domain}/health"
alert_channel_ids = [var.slack_alert_channel_id]
tags = ["payments", "production"]
}
Step 5: Monitor Multiple Environments with Workspaces
Terraform workspaces (or separate state backends per environment) let you create environment-scoped monitors automatically.
# monitors.tf
locals {
env_prefix = terraform.workspace == "default" ? "prod" : terraform.workspace
}
module "api_monitor" {
source = "../../modules/vigilmon-http-monitor"
name = "API - ${local.env_prefix}"
url = "https://api-${local.env_prefix}.example.com/health"
interval = local.env_prefix == "prod" ? 30 : 120
alert_channel_ids = local.env_prefix == "prod" ? [var.pagerduty_webhook_id] : [var.slack_dev_channel_id]
tags = [local.env_prefix, "api", "terraform"]
}
This means:
terraform workspace select prod && terraform apply→ creates or updates a prod monitorterraform workspace select staging && terraform apply→ creates a staging monitor with relaxed intervalsterraform destroyon a decommissioned environment → removes the monitor automatically
Step 6: SSL Certificate Monitoring
If your Terraform manages TLS certificates via ACM or Certbot, add a certificate expiry monitor:
resource "restapi_object" "ssl_monitor" {
path = "/api/monitors"
id_attribute = "id"
data = jsonencode({
name = "SSL - ${var.domain}"
url = "https://${var.domain}"
type = "ssl"
interval = 3600
tags = ["ssl", "terraform", var.environment]
})
}
Vigilmon will alert you 14 days, 7 days, and 1 day before the certificate expires — before auto-renewal failures become outages.
IaC Monitoring Benefits Summary
| Manual monitoring approach | Terraform + Vigilmon approach | |---|---| | Monitor URLs drift from actual infrastructure | Monitor URL is a Terraform interpolation — always correct | | Monitors orphaned after service deletion | Destroy lifecycle removes monitors automatically | | No record of who added a monitor or when | Monitor config is in version control with your infra | | Different environments have inconsistent monitor configs | Module enforces consistent settings across envs | | New team members don't know monitoring exists | Monitors are discoverable in the same codebase |
Infrastructure-as-code means all your infrastructure is defined, versioned, and applied consistently. Uptime monitoring is part of your infrastructure. Defining it in Terraform alongside your services closes the loop: no manual monitor creation, no orphaned monitors after teardown, and no drift between what's deployed and what's being watched.
Start monitoring your infrastructure free at vigilmon.online — then codify it into your Terraform modules.
Tags: #terraform #devops #infrastructure #monitoring