Terraform provider
The official Terraform provider manages HostTracker as code: monitors, contacts, contact groups, alert and report
subscriptions, maintenance windows, webhooks and status pages, reconciled through the
REST API v2. It is published on the Terraform Registry as
HostTracker/hosttracker (current version
0.1.0), works with Terraform 1.0 or newer and OpenTofu, and is built on the Go SDK. Every
attribute is documented in the
registry documentation.
Install
Section titled “Install”terraform { required_providers { hosttracker = { source = "HostTracker/hosttracker" version = "~> 0.1" } }}
provider "hosttracker" {}Provider settings (all optional):
| Setting | Environment variable | Default | What it does |
|---|---|---|---|
token |
HT_TOKEN |
- | The API token. Keep it in the environment, not in a .tf file - a token in configuration ends up in version control and in state. |
base_url |
HT_BASE_URL |
https://api2.host-tracker.com |
The API root. |
timeout |
- | 30 | Seconds per request attempt. |
retry_max |
- | 2 | Retries for throttled or retryable requests; Retry-After is honoured. |
Authenticate
Section titled “Authenticate”Mint a token under Integrations -> API (/integrations/api) - see
API authentication. Give it the scopes your configuration uses:
monitor:read + monitor:write for monitors, subscriptions and maintenance; contact:read + contact:write for
contacts and groups; webhook:read + webhook:write; statuspage:read + statuspage:write; account:read for the
account data source. Family scopes (monitor, contact, …) cover both leaves.
export HT_TOKEN="your-api-token"terraform planExample
Section titled “Example”An HTTP monitor with a keyword, attached certificate and blacklist checks, an email contact subscribed to its alerts, a weekly maintenance window and a status page:
resource "hosttracker_monitor" "shop" { type = "http" url = "https://shop.example.com/" name = "Shop" interval = 300 tags = ["prod", "web"]
locations = { pools = ["allworld"] fallback = "world" }
recheck = { strategy = "fullAgreement" }
settings = { http = { keywords = "Add to cart" follow_redirect = true timeout = 20000 attached = { ssl_exp = { enabled = true } dnsbl = { enabled = true } } cert_watch_days = [7, 30] } }}
resource "hosttracker_contact" "ops" { type = "email" name = "Ops"}
resource "hosttracker_alert_subscription" "shop_ops" { monitor_id = hosttracker_monitor.shop.id contact_id = hosttracker_contact.ops.id alert_types = ["down", "up"]}
resource "hosttracker_maintenance" "weekly_deploy" { name = "Weekly deploy" from = 1790056800 duration_sec = 3600 timezone = "Europe/London" recurrence = { week_days = ["Tuesday"] } monitor_ids = [hosttracker_monitor.shop.id] suppress = { alerts = true, stats = true }}
resource "hosttracker_status_page" "public" { slug = "example-shop" title = "Example Shop status"
components = [ { monitor_id = hosttracker_monitor.shop.id, name = "Shop", group = "Web" }, ]
settings = { theme = "light" show_groups = true features = ["barCharts", "uptimePercent", "detailsPages", "subscribe"] }}interval is in seconds and must be allowed by your plan. The email contact is created unconfirmed; its owner
confirms it with the code they receive before alerts are delivered.
Resources
Section titled “Resources”| Resource | Manages |
|---|---|
hosttracker_monitor |
One monitor. Typed settings blocks for http, ping, port, dnsbl, ssl_exp, domain_exp, web_risk; other types (waterfall, tran, api, database, counter, cntCheck, snmp) use settings_json. |
hosttracker_contact |
An email, sms or voiceCall contact, with active hours, language, alert delay and grouped alerts. |
hosttracker_contact_group |
A named set of contacts with the events each receives. |
hosttracker_alert_subscription |
Which state changes (up, down, repeatedlyDown) of one monitor reach one contact. |
hosttracker_report_subscription |
How often (daily … yearly) one contact gets a report about one monitor. |
hosttracker_maintenance |
A one-time or weekly maintenance window, suppressing alerts, statistics or both, uniformly (monitor_ids + suppress) or per monitor (monitors). |
hosttracker_webhook |
A signed webhook: url, events, scope, headers, and its secret (rotate_secret rotates it). |
hosttracker_status_page |
A status page: settings and, optionally, its whole component list. |
Data sources
Section titled “Data sources”| Data source | Reads |
|---|---|
hosttracker_monitor, hosttracker_monitors |
One monitor by id or lookup; a filtered list (state, type, tag, text). |
hosttracker_monitor_types |
The type catalogue with your plan’s interval floors. |
hosttracker_locations |
Location pools and locations - use it for locations.pools. |
hosttracker_account |
Your package, limits and remaining API quota. |
hosttracker_contact, hosttracker_contacts |
One contact by id or lookup; a filtered list. |
hosttracker_contact_group |
One group by id or name. |
hosttracker_contact_types |
The channels and the alert delays each accepts. |
hosttracker_webhook, hosttracker_webhooks |
One webhook by id or url; all webhooks. |
hosttracker_status_page, hosttracker_status_pages |
One page by id or slug; all pages. |
hosttracker_maintenance_windows |
Maintenance windows filtered by span, state, monitor and name. |
Import existing objects
Section titled “Import existing objects”A monitor created in the app is adopted by its id (shown in its page address, or listed by the
hosttracker_monitors data source):
terraform import hosttracker_monitor.shop 8e2d4c8b-7a41-4a2b-9d0e-2f3a5c6b7d8eCreating a monitor for an address that already has one of the same type is refused with 409 duplicate_monitor,
and the error names the existing id so you can import it instead.
Things worth knowing
Section titled “Things worth knowing”- Removing an attribute keeps its value. The API reads an absent member as “leave it alone”, so deleting an
attribute from configuration does not clear it. Write the empty value (
"",[]) to clear. typeandslugare immutable - changing them replaces the monitor or page.- Status page components are a whole set. If you write
components, every apply replaces the page’s component list with yours; a component added in the app is removed on the next apply. Leavecomponentsout to manage them in the app, and keepauto_add_monitorsoff when Terraform owns the list. - Status page password and custom domain are managed in the app only (
has_passwordandcustom_domainare read-only). hide_brandinghas no effect - the “Powered by HostTracker” credit shows on every status page.- Not in 0.1.0: the maintenance window
showOnStatusPageswitch (windows created by Terraform show on status pages, the API default) and new typed settings blocks for the remaining monitor types. - Monitor
updatedmoves only on creation, up/down changes and plan-limit disabling, not on configuration edits. - Rate limits. The default parallelism of 10 is comfortable on a paid plan’s quota; on a trial token use
terraform apply -parallelism=3. The provider retries429 rate_limitedhonouringRetry-After. - Timestamps are Unix seconds (
from,created,since); some resources add*_rfc3339read-only twins.

