--- category: Reference title: Terraform Provider Reference description: Technical specification for the openstatus Terraform Provider. --- The openstatus Terraform provider lets you manage your monitoring infrastructure programmatically using HashiCorp Terraform. Define monitors, notification channels, and status pages as code — with full support for version control, automated deployments, and IaC workflows. **Key capabilities:** - Manage HTTP, TCP, DNS, and ICMP monitors with assertions. - Configure notification channels (Slack, PagerDuty, email, webhooks, and more). - Create and manage status pages with component groups. - Provision private locations and assign monitors to them. - Import existing resources into Terraform state. ## Installation Declare the provider in your Terraform configuration. Terraform will automatically download it when you run `terraform init`. ```terraform terraform { required_providers { openstatus = { source = "openstatusHQ/openstatus" version = "~> 0.1" } } } ``` For the latest version, refer to the [Terraform Registry](https://registry.terraform.io/providers/openstatusHQ/openstatus/latest). ## Provider configuration ```terraform provider "openstatus" { api_token = "YOUR_OPENSTATUS_API_TOKEN" # or set OPENSTATUS_API_TOKEN env var } ``` | Argument | Type | Required | Description | | :---------- | :------- | :------- | :-------------------------------------------------------------------------- | | `api_token` | `string` | Yes | Your openstatus API token. Can also be set via the `OPENSTATUS_API_TOKEN` environment variable. | | `base_url` | `string` | No | Base URL for the openstatus API. Defaults to `https://api.openstatus.dev/rpc`. | ## Resources ### `openstatus_http_monitor` Manages an HTTP monitor with support for custom headers, request bodies, and response assertions. **Arguments:** | Argument | Type | Required | Default | Description | | :----------------- | :-------------- | :------- | :------- | :-------------------------------------------------------------------------- | | `name` | `string` | Yes | | Monitor name (max 256 chars). | | `url` | `string` | Yes | | URL to monitor (max 2048 chars). | | `periodicity` | `string` | Yes | | Check frequency: `30s`, `1m`, `5m`, `10m`, `30m`, `1h`. | | `method` | `string` | No | `"GET"` | HTTP method: `GET`, `POST`, `HEAD`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`, `TRACE`, `CONNECT`. | | `body` | `string` | No | `""` | Request body for `POST`, `PUT`, `PATCH` methods. | | `timeout` | `number` | No | `45000` | Timeout in milliseconds (0–120000). | | `degraded_at` | `number` | No | computed | Response time threshold (ms) after which the monitor is considered degraded. | | `retry` | `number` | No | `3` | Number of retries on failure (0–10). | | `follow_redirects` | `bool` | No | `true` | Whether to follow HTTP redirects. | | `active` | `bool` | No | `false` | Whether the monitor is active. | | `public` | `bool` | No | `false` | Whether the monitor is visible on your public status page. | | `description` | `string` | No | | Monitor description (max 1024 chars). | | `regions` | `set(string)` | No | | Regions to monitor from. See [Available Regions](#available-regions). | **Blocks:** - **`headers`** (max 20) — Custom HTTP headers to include with each request. - `key` (string, required) — Header name. - `value` (string, required) — Header value. - **`status_code_assertions`** (max 10) — Assert on response status codes. - `target` (number, required) — Expected status code (100–599). - `comparator` (string, required) — One of: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`. - **`body_assertions`** (max 10) — Assert on response body content. - `target` (string, required) — Expected value. - `comparator` (string, required) — One of: `contains`, `not_contains`, `eq`, `neq`, `empty`, `not_empty`, `gt`, `gte`, `lt`, `lte`. - **`header_assertions`** (max 10) — Assert on response headers. - `key` (string, required) — Header name to assert on. - `target` (string, required) — Expected value. - `comparator` (string, required) — Same comparators as `body_assertions`. - **`open_telemetry`** — Export this monitor's metrics to an OTLP endpoint (HTTP only). - `endpoint` (string, optional) — OTLP metrics endpoint URL. - `headers` (block list, optional) — Headers sent with each export; each has a required `key` and `value`. **Read-only attributes:** `id` (string), `status` (string: `active`, `degraded`, `error`, `unknown`), `private_location_ids` (set of string — managed from `openstatus_private_location.monitor_ids`). **Example — Basic health check:** ```terraform resource "openstatus_http_monitor" "website" { name = "Website Availability" url = "https://www.example.com" periodicity = "1m" active = true public = true regions = ["fly-iad", "fly-ams", "fly-syd"] } ``` **Example — API monitor with assertions and headers:** ```terraform resource "openstatus_http_monitor" "api" { name = "API Health Check" description = "Monitors the /health endpoint with full assertions." url = "https://api.example.com/health" periodicity = "5m" method = "GET" timeout = 30000 active = true regions = ["fly-iad", "fly-ams", "fly-nrt"] headers { key = "Authorization" value = "Bearer ${var.api_token}" } headers { key = "Accept" value = "application/json" } status_code_assertions { target = 200 comparator = "eq" } body_assertions { target = "ok" comparator = "contains" } header_assertions { key = "Content-Type" target = "application/json" comparator = "contains" } } ``` **Example — POST monitor with request body:** ```terraform resource "openstatus_http_monitor" "webhook" { name = "Webhook Endpoint" url = "https://api.example.com/webhooks/health" periodicity = "10m" method = "POST" active = true regions = ["fly-iad"] headers { key = "Content-Type" value = "application/json" } body = jsonencode({ type = "health_check" }) status_code_assertions { target = 202 comparator = "eq" } } ``` **Import:** ```bash terraform import openstatus_http_monitor.website ``` --- ### `openstatus_tcp_monitor` Manages a TCP connection monitor to verify that a port is open and reachable. **Arguments:** | Argument | Type | Required | Default | Description | | :------------ | :------------ | :------- | :------- | :----------------------------------------------------------------- | | `name` | `string` | Yes | | Monitor name (max 256 chars). | | `uri` | `string` | Yes | | Target in `host:port` format (max 2048 chars). | | `periodicity` | `string` | Yes | | Check frequency: `30s`, `1m`, `5m`, `10m`, `30m`, `1h`. | | `timeout` | `number` | No | `45000` | Timeout in milliseconds (0–120000). | | `degraded_at` | `number` | No | computed | Degradation threshold in milliseconds. | | `retry` | `number` | No | `3` | Number of retries on failure (0–10). | | `active` | `bool` | No | `false` | Whether the monitor is active. | | `public` | `bool` | No | `false` | Whether the monitor is publicly visible. | | `description` | `string` | No | | Monitor description (max 1024 chars). | | `regions` | `set(string)` | No | | Regions to monitor from. See [Available Regions](#available-regions). | **Blocks:** - **`open_telemetry`** — Export this monitor's metrics to an OTLP endpoint (HTTP only). - `endpoint` (string, optional) — OTLP metrics endpoint URL. - `headers` (block list, optional) — Headers sent with each export; each has a required `key` and `value`. **Read-only attributes:** `id` (string), `status` (string), `private_location_ids` (set of string — managed from `openstatus_private_location.monitor_ids`). **Example — Database port check:** ```terraform resource "openstatus_tcp_monitor" "database" { name = "PostgreSQL Port Check" description = "Ensures the database port is open and reachable." uri = "db.example.com:5432" periodicity = "1m" timeout = 10000 active = true regions = ["fly-iad", "fly-fra"] } ``` **Example — Redis monitor:** ```terraform resource "openstatus_tcp_monitor" "redis" { name = "Redis Connection" uri = "redis.example.com:6379" periodicity = "30s" active = true regions = ["fly-iad", "fly-ams", "fly-nrt"] } ``` **Import:** ```bash terraform import openstatus_tcp_monitor.database ``` --- ### `openstatus_dns_monitor` Manages a DNS monitor with support for record type assertions. **Arguments:** | Argument | Type | Required | Default | Description | | :------------ | :------------ | :------- | :------- | :----------------------------------------------------------------- | | `name` | `string` | Yes | | Monitor name (max 256 chars). | | `uri` | `string` | Yes | | Domain name to monitor (max 2048 chars). | | `periodicity` | `string` | Yes | | Check frequency: `30s`, `1m`, `5m`, `10m`, `30m`, `1h`. | | `timeout` | `number` | No | `45000` | Timeout in milliseconds (0–120000). | | `degraded_at` | `number` | No | computed | Degradation threshold in milliseconds. | | `retry` | `number` | No | `3` | Number of retries on failure (0–10). | | `active` | `bool` | No | `false` | Whether the monitor is active. | | `public` | `bool` | No | `false` | Whether the monitor is publicly visible. | | `description` | `string` | No | | Monitor description (max 1024 chars). | | `regions` | `set(string)` | No | | Regions to monitor from. See [Available Regions](#available-regions). | **Blocks:** - **`record_assertions`** (max 10) — Assert on DNS record values. - `record` (string, required) — DNS record type: `A`, `AAAA`, `CNAME`, `MX`, `TXT`. - `target` (string, required) — Expected value. - `comparator` (string, required) — One of: `eq`, `neq`, `contains`, `not_contains`. - **`open_telemetry`** — Export this monitor's metrics to an OTLP endpoint (HTTP only). - `endpoint` (string, optional) — OTLP metrics endpoint URL. - `headers` (block list, optional) — Headers sent with each export; each has a required `key` and `value`. **Read-only attributes:** `id` (string), `status` (string), `private_location_ids` (set of string — managed from `openstatus_private_location.monitor_ids`). **Example — A record validation:** ```terraform resource "openstatus_dns_monitor" "main_domain" { name = "DNS A Record Check" description = "Verifies that example.com resolves to the correct IP." uri = "example.com" periodicity = "10m" active = true regions = ["fly-iad", "fly-ams"] record_assertions { record = "A" comparator = "eq" target = "93.184.216.34" } } ``` **Example — MX record validation:** ```terraform resource "openstatus_dns_monitor" "email" { name = "Email MX Record Check" uri = "example.com" periodicity = "30m" active = true regions = ["fly-iad"] record_assertions { record = "MX" comparator = "contains" target = "mail.example.com" } } ``` **Import:** ```bash terraform import openstatus_dns_monitor.main_domain ``` --- ### `openstatus_icmp_monitor` Manages an ICMP (ping) monitor that checks host reachability and round-trip latency. **Arguments:** | Argument | Type | Required | Default | Description | | :------------ | :------------ | :------- | :------- | :----------------------------------------------------------------- | | `name` | `string` | Yes | | Monitor name (max 256 chars). | | `uri` | `string` | Yes | | Target host or IP address to ping, without a port. | | `periodicity` | `string` | Yes | | Check frequency: `30s`, `1m`, `5m`, `10m`, `30m`, `1h`. | | `timeout` | `number` | No | `45000` | Budget in milliseconds for the whole check (0–120000). | | `degraded_at` | `number` | No | computed | Average-latency threshold in milliseconds. | | `retry` | `number` | No | `3` | Number of retries on a fully failed check (0–10). | | `active` | `bool` | No | `false` | Whether the monitor is active. | | `public` | `bool` | No | `false` | Whether the monitor is publicly visible. | | `description` | `string` | No | | Monitor description (max 1024 chars). | | `regions` | `set(string)` | No | | Regions to monitor from. See [Available Regions](#available-regions). | **Blocks:** - **`open_telemetry`** — Export this monitor's metrics to an OTLP endpoint (HTTP only). - `endpoint` (string, optional) — OTLP metrics endpoint URL. - `headers` (block list, optional) — Headers sent with each export; each has a required `key` and `value`. **Read-only attributes:** `id` (string), `status` (string), `private_location_ids` (set of string — managed from `openstatus_private_location.monitor_ids`). See the [ICMP monitor reference](/docs/reference/icmp-monitor) for how a check is run (three echo requests, average latency, packet loss). **Example — Gateway reachability:** ```terraform resource "openstatus_icmp_monitor" "gateway" { name = "Gateway Ping" description = "Round-trip latency to the upstream gateway." uri = "8.8.8.8" periodicity = "1m" timeout = 10000 active = true regions = ["fly-iad", "fly-fra"] open_telemetry { endpoint = "https://otel.example.com/v1/metrics" } } ``` **Import:** ```bash terraform import openstatus_icmp_monitor.gateway ``` --- ### `openstatus_notification` Manages a notification channel. Supports 13 provider types: Discord, Email, Slack, PagerDuty, OpsGenie, Webhook, Telegram, SMS, WhatsApp, Google Chat, Grafana OnCall, Microsoft Teams, and ntfy. **Arguments:** | Argument | Type | Required | Description | | :-------------- | :------------ | :------- | :------------------------------------------------------ | | `name` | `string` | No | Notification channel name. | | `provider_type` | `string` | Yes | Provider type (see supported values below). | | `monitor_ids` | `set(string)` | No | Set of monitor IDs to associate with this notification. | **Supported `provider_type` values:** `discord`, `email`, `slack`, `pagerduty`, `opsgenie`, `webhook`, `telegram`, `sms`, `whatsapp`, `google_chat`, `grafana_oncall`, `ntfy`. **Provider-specific blocks** — use exactly one block matching your `provider_type`: | Block | Arguments | | :-------------- | :----------------------------------------------------------------------------------------------------- | | `discord` | `webhook_url` (string, required, sensitive) | | `email` | `email` (string, required) | | `slack` | `webhook_url` (string, required, sensitive) | | `pagerduty` | `integration_key` (string, required, sensitive) | | `opsgenie` | `api_key` (string, required, sensitive), `region` (string, required: `us` or `eu`) | | `webhook` | `endpoint` (string, required), `headers` (optional list of `key`/`value` objects) | | `telegram` | `chat_id` (string, required) | | `sms` | `phone_number` (string, required) | | `whatsapp` | `phone_number` (string, required) | | `google_chat` | `webhook_url` (string, required, sensitive) | | `grafana_oncall` | `webhook_url` (string, required, sensitive) | | `ntfy` | `topic` (string, required), `server_url` (string, optional), `token` (string, optional, sensitive) | **Read-only attributes:** `id` (string), `created_at` (string), `updated_at` (string). **Example — Slack notification:** ```terraform resource "openstatus_notification" "slack_alerts" { name = "Slack Alerts" provider_type = "slack" monitor_ids = [openstatus_http_monitor.api.id] slack { webhook_url = var.slack_webhook_url } } ``` **Example — PagerDuty notification:** ```terraform resource "openstatus_notification" "pagerduty" { name = "PagerDuty Escalation" provider_type = "pagerduty" monitor_ids = [ openstatus_http_monitor.api.id, openstatus_tcp_monitor.database.id, ] pagerduty { integration_key = var.pagerduty_key } } ``` **Example — Email notification:** ```terraform resource "openstatus_notification" "email" { name = "On-Call Email" provider_type = "email" monitor_ids = [openstatus_http_monitor.api.id] email { email = "oncall@example.com" } } ``` **Example — Custom webhook:** ```terraform resource "openstatus_notification" "custom_webhook" { name = "Custom Webhook" provider_type = "webhook" webhook { endpoint = "https://api.example.com/alerts" headers { key = "Authorization" value = "Bearer ${var.webhook_token}" } headers { key = "Content-Type" value = "application/json" } } } ``` **Example — Discord notification:** ```terraform resource "openstatus_notification" "discord" { name = "Discord Alerts" provider_type = "discord" discord { webhook_url = var.discord_webhook_url } } ``` **Import:** ```bash terraform import openstatus_notification.slack_alerts ``` --- ### `openstatus_status_page` Manages a status page with access control and branding. **Arguments:** | Argument | Type | Required | Description | | :------------------- | :------------- | :------- | :----------------------------------------------------------------------------- | | `title` | `string` | Yes | Page title (1–256 chars). | | `slug` | `string` | Yes | URL slug (1–256 chars). Used in the status page URL. | | `description` | `string` | No | Page description (max 1024 chars). | | `homepage_url` | `string` | No | Link to your homepage. | | `contact_url` | `string` | No | Link to your contact page. | | `icon` | `string` | No | URL of the icon to display. | | `custom_domain` | `string` | No | Custom domain (DNS must point to openstatus first). | | `access_type` | `string` | No | Access control: `public`, `password`, `email-domain`, or `ip-restriction`. | | `password` | `string` | No | Required when `access_type` is `password`. Sensitive. | | `auth_email_domains` | `list(string)` | No | Required when `access_type` is `email-domain`. | | `allowed_ip_ranges` | `string` | No | Comma-separated IPv4 CIDR ranges. Required when `access_type` is `ip`. | | `theme` | `string` | No | Theme key applied to the page. | | `custom_theme` | `object` | No | Per-mode CSS variable overrides merged over `theme`, with `light` and `dark` maps. Requires the custom-theme plan feature. | | `default_locale` | `string` | No | Default language for the page. | | `locales` | `list(string)` | No | Locales offered in the language switcher. | | `allow_index` | `bool` | No | Whether search engines may index the page. | **Read-only attributes:** `id` (string), `published` (bool), `created_at` (string), `updated_at` (string). **Example — Public status page:** ```terraform resource "openstatus_status_page" "main" { title = "Example Inc. Status" slug = "example-status" description = "Real-time status for all Example Inc. services." homepage_url = "https://example.com" contact_url = "https://example.com/support" } ``` **Example — Password-protected status page:** ```terraform resource "openstatus_status_page" "internal" { title = "Internal Status" slug = "internal-status" description = "Status page for internal services." access_type = "password" password = var.status_page_password } ``` **Example — Email-domain restricted status page:** ```terraform resource "openstatus_status_page" "company" { title = "Company Status" slug = "company-status" access_type = "email-domain" auth_email_domains = ["example.com", "subsidiary.com"] } ``` **Example — IP-restricted status page:** ```terraform resource "openstatus_status_page" "internal" { title = "Internal Status" slug = "internal-status" access_type = "ip-restriction" allowed_ip_ranges = "10.0.0.0/8,192.168.0.0/16" } ``` **Import:** ```bash terraform import openstatus_status_page.main ``` --- ### `openstatus_status_page_component` Manages a component on a status page. Components can be linked to a monitor or be static. **Arguments:** | Argument | Type | Required | Description | | :------------ | :------- | :------- | :--------------------------------------------------------------------------- | | `page_id` | `string` | Yes | Status page ID this component belongs to. Forces replacement if changed. | | `type` | `string` | Yes | Component type: `monitor` or `static`. Forces replacement if changed. | | `monitor_id` | `string` | No | Required when `type` is `monitor`. The monitor ID to display. | | `name` | `string` | No | Component display name (max 256 chars). | | `description` | `string` | No | Component description (max 1024 chars). | | `order` | `number` | No | Display order on the status page. | | `group_id` | `string` | No | Component group ID this belongs to. | | `group_order` | `number` | No | Display order within its group. | **Read-only attributes:** `id` (string), `created_at` (string), `updated_at` (string). **Example — Monitor component:** ```terraform resource "openstatus_status_page_component" "api" { page_id = openstatus_status_page.main.id type = "monitor" monitor_id = openstatus_http_monitor.api.id name = "API" order = 1 } ``` **Example — Static component:** ```terraform resource "openstatus_status_page_component" "third_party" { page_id = openstatus_status_page.main.id type = "static" name = "Third-party Services" description = "Status of external dependencies." order = 2 } ``` **Import:** ```bash terraform import openstatus_status_page_component.api / ``` --- ### `openstatus_status_page_component_group` Manages a component group on a status page, allowing you to organize components visually. **Arguments:** | Argument | Type | Required | Description | | :-------- | :------- | :------- | :----------------------------------------------------------------------- | | `page_id` | `string` | Yes | Status page ID this group belongs to. Forces replacement if changed. | | `name` | `string` | Yes | Group name (1–256 chars). | **Read-only attributes:** `id` (string), `created_at` (string), `updated_at` (string). **Example:** ```terraform resource "openstatus_status_page_component_group" "infrastructure" { page_id = openstatus_status_page.main.id name = "Infrastructure" } resource "openstatus_status_page_component_group" "applications" { page_id = openstatus_status_page.main.id name = "Applications" } ``` **Import:** ```bash terraform import openstatus_status_page_component_group.infrastructure / ``` --- ### `openstatus_private_location` Manages a private location: a self-hosted checker agent that runs the monitors you assign to it. Terraform owns `monitor_ids` and `metadata` — removing either from the configuration clears it on the next apply. Liveness (`status`, `last_seen_at`) is only available on the `openstatus_private_location` data source. **Arguments:** | Argument | Type | Required | Description | | :------------ | :------------ | :------- | :----------------------------------------------------------- | | `name` | `string` | Yes | Display name for the private location. | | `monitor_ids` | `set(string)` | No | IDs of the monitors this private location runs. | | `metadata` | `map(string)` | No | User-defined key/value labels attached to this location. | **Read-only attributes:** `id` (string), `token` (string, sensitive), `created_at` (string), `updated_at` (string). ```terraform resource "openstatus_private_location" "eu_dc" { name = "EU Datacenter" monitor_ids = [openstatus_http_monitor.api.id] metadata = { env = "prod" region = "eu-west-1" } } # The agent token is generated by openstatus. Pass it to the checker agent. output "agent_token" { value = openstatus_private_location.eu_dc.token sensitive = true } ``` ## Data Sources ### `openstatus_monitor` Look up a single monitor by ID. Works for HTTP, TCP, DNS, and ICMP monitors. ```terraform data "openstatus_monitor" "existing" { id = "123" } output "monitor_name" { value = data.openstatus_monitor.existing.name } output "monitor_type" { value = data.openstatus_monitor.existing.type } ``` **Computed attributes:** `type` (`http`, `tcp`, `dns`, `icmp`), `name`, `url` (HTTP only), `uri` (TCP/DNS/ICMP only), `periodicity`, `method` (HTTP only), `active`, `public`, `description`, `timeout`, `status`, `private_location_ids`. --- ### `openstatus_monitors` List all monitors with pagination. ```terraform data "openstatus_monitors" "all" { limit = 100 offset = 0 } output "total_monitors" { value = length(data.openstatus_monitors.all.monitors) } ``` | Argument | Type | Required | Default | Description | | :------- | :------- | :------- | :------ | :----------------------- | | `limit` | `number` | No | `50` | Max results (1–100). | | `offset` | `number` | No | `0` | Pagination offset. | **Computed:** `monitors` — list of objects with `id`, `name`, `type`. --- ### `openstatus_notification` Look up a notification channel by ID. ```terraform data "openstatus_notification" "existing" { id = "456" } output "notification_provider" { value = data.openstatus_notification.existing.provider_type } ``` **Computed attributes:** `name`, `provider_type`, `monitor_ids`, `created_at`, `updated_at`. --- ### `openstatus_status_page` Look up a status page by ID. ```terraform data "openstatus_status_page" "existing" { id = "789" } output "status_page_url" { value = data.openstatus_status_page.existing.slug } ``` **Computed attributes:** `title`, `slug`, `description`, `homepage_url`, `contact_url`, `icon`, `custom_domain`, `published`, `access_type`, `password` (sensitive), `auth_email_domains`, `theme`, `created_at`, `updated_at`. --- ### `openstatus_private_location` Look up a single private location by ID. Unlike the resource, this data source exposes agent liveness. ```terraform data "openstatus_private_location" "eu_dc" { id = "12" } output "agent_last_seen" { value = data.openstatus_private_location.eu_dc.last_seen_at } ``` **Computed attributes:** `name`, `monitor_ids`, `metadata`, `status` (`active`, `error`, or `unknown`), `last_seen_at` (RFC 3339, null if the agent has never reported), `token` (sensitive), `created_at`, `updated_at`. --- ### `openstatus_private_locations` List all private locations with pagination. ```terraform data "openstatus_private_locations" "all" { limit = 100 } output "private_location_names" { value = [for l in data.openstatus_private_locations.all.private_locations : l.name] } ``` | Argument | Type | Required | Default | Description | | :------- | :------- | :------- | :------ | :----------------- | | `limit` | `number` | No | `50` | Max results. | | `offset` | `number` | No | `0` | Pagination offset. | **Computed:** `private_locations` — list of objects with `id`, `name`, `metadata`, `status`, `last_seen_at`, `monitor_count`, `created_at`, `updated_at`. Agent tokens are not returned by the list endpoint; use the singular data source to fetch one. ## Available Regions Monitors can run from any of the following 28 regions: **Fly.io:** `fly-ams`, `fly-arn`, `fly-bom`, `fly-cdg`, `fly-dfw`, `fly-ewr`, `fly-fra`, `fly-gru`, `fly-iad`, `fly-jnb`, `fly-lax`, `fly-lhr`, `fly-nrt`, `fly-ord`, `fly-sjc`, `fly-sin`, `fly-syd`, `fly-yyz` **Koyeb:** `koyeb-fra`, `koyeb-par`, `koyeb-sfo`, `koyeb-sin`, `koyeb-tyo`, `koyeb-was` **Railway:** `railway-us-west2`, `railway-us-east4`, `railway-europe-west4`, `railway-asia-southeast1` ## Full End-to-End Example This example sets up a complete monitoring stack: HTTP and TCP monitors, Slack notifications, and a public status page with grouped components. ```terraform terraform { required_providers { openstatus = { source = "openstatusHQ/openstatus" version = "~> 0.1" } } } provider "openstatus" { api_token = var.openstatus_api_token } # --- Variables --- variable "openstatus_api_token" { type = string sensitive = true } variable "slack_webhook_url" { type = string sensitive = true } # --- Monitors --- resource "openstatus_http_monitor" "api" { name = "API Health" description = "Monitors the main API health endpoint." url = "https://api.example.com/health" periodicity = "5m" method = "GET" timeout = 30000 active = true public = true regions = ["fly-iad", "fly-ams", "fly-nrt"] status_code_assertions { target = 200 comparator = "eq" } body_assertions { target = "ok" comparator = "contains" } } resource "openstatus_http_monitor" "website" { name = "Website" url = "https://www.example.com" periodicity = "1m" active = true public = true regions = ["fly-iad", "fly-ams", "fly-syd"] status_code_assertions { target = 200 comparator = "eq" } } resource "openstatus_tcp_monitor" "database" { name = "PostgreSQL" uri = "db.example.com:5432" periodicity = "1m" timeout = 10000 active = true regions = ["fly-iad"] } resource "openstatus_dns_monitor" "domain" { name = "DNS Resolution" uri = "example.com" periodicity = "10m" active = true regions = ["fly-iad", "fly-ams"] record_assertions { record = "A" comparator = "eq" target = "93.184.216.34" } } # --- Notifications --- resource "openstatus_notification" "slack" { name = "Slack Alerts" provider_type = "slack" monitor_ids = [ openstatus_http_monitor.api.id, openstatus_http_monitor.website.id, openstatus_tcp_monitor.database.id, ] slack { webhook_url = var.slack_webhook_url } } # --- Status Page --- resource "openstatus_status_page" "main" { title = "Example Inc. Status" slug = "example-status" description = "Real-time status for all Example Inc. services." homepage_url = "https://example.com" contact_url = "https://example.com/support" } resource "openstatus_status_page_component_group" "web" { page_id = openstatus_status_page.main.id name = "Web Services" } resource "openstatus_status_page_component_group" "infra" { page_id = openstatus_status_page.main.id name = "Infrastructure" } resource "openstatus_status_page_component" "api_component" { page_id = openstatus_status_page.main.id type = "monitor" monitor_id = openstatus_http_monitor.api.id name = "API" group_id = openstatus_status_page_component_group.web.id order = 1 group_order = 1 } resource "openstatus_status_page_component" "website_component" { page_id = openstatus_status_page.main.id type = "monitor" monitor_id = openstatus_http_monitor.website.id name = "Website" group_id = openstatus_status_page_component_group.web.id order = 1 group_order = 2 } resource "openstatus_status_page_component" "db_component" { page_id = openstatus_status_page.main.id type = "monitor" monitor_id = openstatus_tcp_monitor.database.id name = "Database" group_id = openstatus_status_page_component_group.infra.id order = 2 group_order = 1 } ``` ## Related Resources - **[HTTP Monitor Reference](/docs/reference/http-monitor)** — Detailed specification for HTTP monitor configuration. - **[TCP Monitor Reference](/docs/reference/tcp-monitor)** — Detailed specification for TCP monitor configuration. - **[DNS Monitor Reference](/docs/reference/dns-monitor)** — Detailed specification for DNS monitor configuration. - **[CLI Reference](/docs/reference/cli-reference)** — Manage monitors using the openstatus command-line interface. - **[Terraform Registry](https://registry.terraform.io/providers/openstatusHQ/openstatus/latest)** — Official provider page with version history. - **[Provider Source Code](https://github.com/openstatusHQ/terraform-provider-openstatus)** — GitHub repository for the Terraform provider.