Skip to main content

Terraform provider

Manage HostTracker monitoring as code. Declare your monitors, contacts, alert routing and status pages in Terraform and let it reconcile them through the REST API v2 - the same review, the same history and the same pipeline as the rest of your infrastructure. Published on the Terraform Registry as HostTracker/hosttracker, and it works with OpenTofu too.

Before you start

One API token, in the environment

Mint a token on the API page with the scopes the configuration actually needs - monitor:read and monitor:write for the monitor resource, plus account:read for the hosttracker_account data source. Put it in the environment rather than in a .tf file: a token written into the configuration ends up in version control, and in the state file as well.

export HT_TOKEN="…"
# export HT_BASE_URL="https://api2.host-tracker.com"   # the default

The endpoint-by-endpoint reference for everything the provider calls is at /apidocs/v2, the narrative documentation at /apidocs/v2/guide, and the schema of every resource and data source at the registry documentation. Prefer a library or a shell? The same surface is available through the official SDKs and ht-cli.

Install

Declare the provider, then terraform init

terraform {
  required_providers {
    hosttracker = {
      source  = "HostTracker/hosttracker"
      version = "~> 0.1"
    }
  }
}

provider "hosttracker" {}

Requires Terraform 1.0 or newer, or OpenTofu. The empty provider block reads the token from HT_TOKEN; token, base_url, timeout and retry_max can be set explicitly instead.

Your first monitor

A keyword-checked http monitor, run from everywhere

data "hosttracker_locations" "all" {}

resource "hosttracker_monitor" "marketing" {
  type     = "http"
  url      = "https://example.com/"
  name     = "Marketing site"
  interval = 300
  tags     = ["prod", "web"]

  locations = {
    pools    = ["allworld"]
    fallback = "world"
  }

  recheck = {
    strategy = "fullAgreement"
  }

  settings = {
    http = {
      keywords        = "Sign in"
      follow_redirect = true
      timeout         = 20000

      headers = [
        { name = "X-Monitored-By", value = "terraform" },
      ]

      # Sub-checks riding on this monitor rather than costing one of their own.
      attached = {
        ssl_exp = { enabled = true }
        dnsbl   = { enabled = true }
      }

      cert_watch_days = [7, 30]
    }
  }
}

output "marketing_state" {
  value = hosttracker_monitor.marketing.state
}

terraform plan and terraform apply as usual. Reading monitors back is a data source, so a configuration can act on what is already there:

# Every production monitor that is currently down.
data "hosttracker_monitors" "down_in_prod" {
  tag   = ["prod"]
  state = ["down"]
}

output "down_urls" {
  value = [for m in data.hosttracker_monitors.down_in_prod.monitors : m.url]
}

Import existing resources

Adopt what the web app already created

A monitor created in the web app is adopted by its id, which the address bar of its page shows and the hosttracker_monitors data source publishes as ids:

terraform import hosttracker_monitor.marketing 8e2d4c8b-7a41-4a2b-9d0e-2f3a5c6b7d8e

Creating a monitor for an address that already has one is refused with 409 duplicate_monitor, and the provider puts the existing monitor's id in the error - so a duplicate is never created silently, and the message tells you exactly what to import instead.

An optional attribute is also computed: the API reads an absent member as "leave this alone", never as "clear this". Removing an attribute from the configuration keeps the value it last had; to clear one, write the empty value ("", []) explicitly.

What you can manage

The infrastructure you would keep in code

Resources

  • hosttracker_monitor A check: type, address, interval, tags, locations, recheck policy and the per-type settings block.
  • hosttracker_contact Where an alert goes - email, SMS, voice, a messenger. Confirmation stays out of band.
  • hosttracker_contact_group A named set of contacts, addressed as one.
  • hosttracker_maintenance A planned window in which alerts are suppressed, one-off or recurring.
  • hosttracker_webhook An HTTPS endpoint receiving events, with its scope, headers and signing secret.
  • hosttracker_alert_subscription Which contact is alerted for which monitor, and on which events.
  • hosttracker_report_subscription Which contact receives which monitor's reports, and how often.
  • hosttracker_status_page A public status page with its components, in the order they are shown.

Data sources

  • hosttracker_monitor One monitor, by id.
  • hosttracker_monitors A filtered list - by tag, type or state - with the ids to import or reference.
  • hosttracker_monitor_types The check types the account may create, with their minimum intervals.
  • hosttracker_locations The location pools and agents a monitor's locations block may name.
  • hosttracker_account The account's plan, limits and API quota.

A check type with no typed settings block yet - waterfall, tran, api, database, counter, snmp, cntCheck - is written through settings_json, which takes the settings object as JSON and manages only the members it names. The registry documentation is the exact schema for the version you install.

Rate limits. Terraform's default parallelism of 10 is comfortable under a paid plan's quota. On a trial token (10 reads and 5 writes a minute) run:

terraform apply -parallelism=3

The provider retries a 429 rate_limited honouring the API's Retry-After, but a whole plan applied at once can still exhaust the window.

Questions about the provider belong in its GitHub repository; account and billing matters go to support.