Terraform & OpenTofu
Monitors that live next to your infrastructure.
Describe your checks and alert routing in code. Review them in a pull request, see every change in the plan, and apply them with the rest of your stack.
Checks and alert routing in code, reviewed in a pull request and applied with your stack.
terraform { required_providers { culipulse = { source = "culipulse/culipulse", version = "~> 0.1" } }}data "culipulse_agents" "singapore" { kind = "first_party" region = "sg"}resource "culipulse_http_monitor" "api" { name = "API health" url = "https://api.example.com/health" interval_seconds = 300 agent_ids = data.culipulse_agents.singapore.ids expected_status = "200" secret_headers = { "X-Api-Key" = var.health_check_key } assertions = [ { source = "json_body", op = "equals", path = "$.status", value = "ok" }, ]}
resource "culipulse_http_monitor" "api" { name = "API health" url = "https://api.example.com/health" interval_seconds = 300 expected_status = "200"}
Get started
Three steps to your first plan.
In the console, open Settings → API tokens and create a read-and-write token.
Settings → API tokensSet it as an environment variable so it never lands in your code.
export CULIPULSE_API_TOKEN=cpk_…Add the provider block, then run the usual commands. Nothing changes until you apply.
terraform init && terraform plan$ terraform plandata.culipulse_agents.singapore: Reading...data.culipulse_agents.singapore: Read complete after 0sTerraform will perform the following actions: # culipulse_channel_routing.incidents will be created # culipulse_heartbeat_monitor.backup will be created # culipulse_http_monitor.api will be created + resource "culipulse_http_monitor" "api" { + agent_ids = ["agt_31f061d9-1aaf-430c-b85b-b63dad638cfa"] + expected_status = "200" + interval_seconds = 300 + url = "https://api.example.com/health" … } # culipulse_webhook_channel.incidents will be createdPlan: 4 to add, 0 to change, 0 to destroy.
$ terraform plan # culipulse_channel_routing.incidents will be created # culipulse_heartbeat_monitor.backup will be created # culipulse_http_monitor.api will be created # culipulse_webhook_channel.incidents will be createdPlan: 4 to add, 0 to change, 0 to destroy.
Real terraform plan output against a CuliPulse test account (excerpt)Real plan output (excerpt)
What you can manage
Start with the checks you change most.
Version 0.1 covers website and scheduled-job monitors, webhooks and alert routing. Other monitor types stay in the console for now.
Not in Terraform yet
- Port, UDP and ping monitors
- DNS, domain and vendor status monitors
- Connecting Slack or Telegram (connect once in the console)
Set these up in the console. Alert channels you connect there can still be used from Terraform.
Examples
Real configurations, ready to copy.
Send one monitor to a Telegram chat you connected in the console, and every monitor to your incident webhook.
Watch a nightly backup. Terraform hands you the ping URL to call as the last step of the job.
Already built monitors in the console? Bring them under Terraform by id, then add any secret headers to your config before the first apply.
More examples in the docs →# A Telegram chat connected in the consoledata "culipulse_channel" "payments" { name = "Payments team" type = "telegram"}resource "culipulse_channel_routing" "payments" { channel_id = data.culipulse_channel.payments.id monitor_ids = [culipulse_http_monitor.api.id]}# Every monitor, including ones created laterresource "culipulse_channel_routing" "incidents" { channel_id = culipulse_webhook_channel.incidents.id all_monitors = true}
resource "culipulse_heartbeat_monitor" "backup" { name = "Nightly backup" interval_seconds = 86400 grace_seconds = 1800}# Give this to your job, e.g. curl -fsS "$PING_URL"output "backup_ping_url" { value = culipulse_heartbeat_monitor.backup.ping_url sensitive = true}
# The monitor id is in the console URL$ terraform import culipulse_http_monitor.api \ mon_3f2c9a1e-6b4d-4c8a-9f0e-1a2b3c4d5e6fculipulse_http_monitor.api: Importing...Import successful!