Terraform provider
Manage cron jobs, heartbeat monitors, and alert rules as infrastructure as code with the official SteadyCron Terraform provider. Export an existing account to HCL in one command.
The SteadyCron Terraform provider lets you manage cron jobs alongside the rest of your infrastructure in HCL — no separate YAML manifests required if you are already running Terraform.
Prerequisites
- Terraform ≥ 1.5 (required for the
import {}block syntax the exporter generates) - A SteadyCron API key — create one in Settings → API keys with Full scope
Set the key as an environment variable:
export STEADYCRON_API_KEY=sc_...
Adopting an existing account
If you already have jobs in the SteadyCron dashboard, export your entire account as a ready-to-apply Terraform configuration in one command:
steadycron export --format terraform -o main.tf
The exported file contains:
- A
terraform {}block with the provider pinned to the current version import {}blocks for every existing resource (tags, channels, jobs, alert rules)resource "steadycron_*" "..."blocks with all settings filled invariable "..." { sensitive = true }blocks for secrets (webhook URLs, bot tokens)
Because the file includes import {} blocks, running terraform apply will adopt
all existing resources into Terraform state rather than creating duplicates.
Supply sensitive variable values
Secrets are never embedded in the exported file. The exporter declares them as
sensitive Terraform variables that you must supply at apply time. Create a
terraform.tfvars file (keep it out of git):
# terraform.tfvars — do not commit this file
sc_channel_ops_slack_webhook_url = "https://hooks.slack.com/services/..."
sc_channel_pagerduty_secret = "your-webhook-secret"
Or pass them inline:
terraform apply -var='sc_channel_ops_slack_webhook_url=https://...'
Apply
terraform init
terraform plan # review what will be imported / changed
terraform apply
On first apply, Terraform imports every existing resource into state. Subsequent
terraform plan runs show only drift from your configuration.
Starting from scratch
If you have no existing jobs, write a configuration by hand and apply:
terraform {
required_providers {
steadycron = {
source = "steadycron/steadycron"
version = "1.0.4"
}
}
}
# api_key from STEADYCRON_API_KEY env var
provider "steadycron" {}
resource "steadycron_alert_channel" "ops_email" {
name = "ops-email"
kind = "email"
email_to = "ops@example.com"
}
resource "steadycron_http_job" "weekly_digest" {
name = "weekly-digest"
method = "POST"
url = "https://api.example.com/jobs/digest"
cron_expression = "0 9 * * 1" # Monday 09:00
timezone = "Europe/Berlin"
timeout_seconds = 120
max_retries = 2
}
resource "steadycron_alert_rule" "digest_failure" {
job_id = steadycron_http_job.weekly_digest.id
channel_id = steadycron_alert_channel.ops_email.id
trigger = "on_failure"
}
terraform init && terraform apply
Resources
| Resource | Description |
|---|---|
steadycron_http_job | Scheduled HTTPS call |
steadycron_heartbeat_monitor | Expected-ping monitor with a unique ping URL |
steadycron_alert_channel | Email, Slack, Discord, webhook, or Telegram channel |
steadycron_alert_rule | Links a job to a channel with a trigger condition |
steadycron_tag | key=value label for grouping/filtering jobs |
steadycron_template_variable | Named placeholder for server-side substitution in job fields |
Data sources (data.steadycron_http_job, data.steadycron_heartbeat_monitor,
data.steadycron_tag, data.steadycron_alert_channel) let you reference existing
resources without managing them.
Importing individual resources
To bring a single resource under Terraform management without a full account export:
# Resource IDs are UUIDs — find them in the dashboard URL or via:
# steadycron jobs list (shows the id column)
terraform import steadycron_http_job.weekly_digest <job_id>
terraform import steadycron_heartbeat_monitor.db_backup <job_id>
terraform import steadycron_alert_channel.ops_email <channel_id>
terraform import steadycron_alert_rule.digest_failure <rule_id>
terraform import steadycron_tag.env_prod <tag_id>
After importing, run terraform plan. Fields the API redacts on read (alert channel
secrets, heartbeat tokens) will show as diffs — add their values to your
configuration.
Interoperability with the CLI
Resources created via Terraform have a null manifest_namespace, so they are
never pruned by steadycron apply --prune. Manage a resource with Terraform
or with the YAML CLI, not both — mixing tools for the same resource is
unsupported.
Rate limits
The SteadyCron API allows 120 requests per minute per key. The provider automatically
retries 429 Too Many Requests responses with exponential backoff (up to 5 retries,
honouring Retry-After). If you hit limits regularly, lower provider parallelism:
terraform apply -parallelism=5
CI/CD with GitHub Actions
The steadycron/action GitHub Action supports
Terraform natively via tool: terraform. It handles terraform init automatically, posts
a plan diff as a sticky PR comment, and uses a saved plan file when plan and apply run
as separate steps in the same job.
Plan on pull request:
- uses: steadycron/action@v1
with:
tool: terraform
command: plan
working-directory: infra/steadycron
comment-on-pr: 'true'
env:
STEADYCRON_API_KEY: ${{ secrets.STEADYCRON_API_KEY }}
Apply on merge:
- uses: steadycron/action@v1
with:
tool: terraform
command: apply
working-directory: infra/steadycron
env:
STEADYCRON_API_KEY: ${{ secrets.STEADYCRON_API_KEY }}
See CI/CD setup for complete workflow files, the remote state backend pattern, and all available action inputs.
Related
- CI/CD setup — full GitHub Actions workflow examples for Terraform and YAML
- YAML & CLI — manage jobs with a YAML manifest instead of HCL
- API & authentication — API key management