Getting started with Terraform and StatusPal status pages
Learn how to provision your StatusPal status page, including monitoring and incident automation, with Terraform in this step-by-step guide.
Introduction
Terraform, created by HashiCorp, is a popular infrastructure-as-code software tool used to provision various types of infrastructure and services, including StatusPal status pages, monitoring checks, and incident automation.
This step-by-step guide teaches you how to set up StatusPal status pages with Terraform from the ground up, including the following resources:
StatuPal status page
Status page services
Enable monitoring checks for your services
Configure incident automation from external monitoring services
Before you begin
To use this guide, you should have some basic knowledge of both StatusPal and Terraform. If you don't have a StatusPal account, you can register here. Also, you will need to install the Terraform CLI.
1. Bootstrap Terraform and the StatusPal provider
Start by initializing a working directory and creating a Terraform configuration file:
Next, instruct Terraform to install and use the StatusPal provider, by setting the terraform and required_providers blocks in main.tf:
terraform {# Require Terraform version >= 1.1.0 required_version =">= 1.1.0"# Require the latest version of the StatusPal provider# You can find it here: https://registry.terraform.io/providers/statuspal/statuspal/latestrequired_providers { statuspal = { source ="statuspal/statuspal" version ="0.2.7" } }}
In this code block, you're setting the required version of Terraform to 1.9.0 and setting the StatusPal provider to the latest version. Using the right version constraints for your setup will provide better stability with your Terraform runs.
Now that you've set your Terraform and StatusPal provider versions, you need to configure the StatusPal provider.
2. Configure the StatusPal provider
With terraform all set, configure the StatusPal provider with the following items:
Your StatusPal API key, it can be a user API key or an organization API key.
Your StatusPal region. It can be US or EU.
In main.tf, set those values on the provider:
provider "statuspal" { api_key ="uk_aERPQU1kUzUrRmplaXJRMlc2TDEwZz09"# Your Statuspal user or organization API key region ="US"# US or EU}
By setting these values on the StatusPal provider, you're configuring that provider to make changes on behalf of your account through StatusPal APIs.
You can also configure the StatusPal provider usingenvironment variables. This is a useful way to set default values for your provider configuration.
For more information about configuring the StatusPal provider, please feel free to check out our official providerdocumentation.
With your StatusPal provider configured, initialize Terraform:
terraforminit
When Terraform finishes installing and registering the StatusPal provider, you'll receive a success message and some actionable next steps, such as running terraform plan. Before you can run terraform plan, however, you need to create your resources.
3. Configure a status page with services
With the StatusPal provider configured and initialized, you can define a status page.
Using the statuspal_status_page resource you can create an example status page:
resource "statuspal_status_page" "example" { organization_id = "1" # Your StatusPal organization ID. Find it in your organization's settings (https://docs.statuspal.io/faq#how-to-access-my-statuspal-organizations-settings), at the end of the URL (e.g. /admin/orgs/1)
status_page = { name ="Example Terraform Status Page" url ="example.com" time_zone ="America/New_York" }}
Now you should be able to test your configuration with a dry run:
terraformplan
You should see output that displays Terraform's execution plan. The plan contains the actions Terraform performs when your run terraform apply:
# Example output------------------------------------------------------------------------Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+createTerraformwillperformthefollowingactions:# statuspal_status_page.example will be created+resource"statuspal_status_page""example"{+id= (known afterapply)+organization_id="4612"+status_page={+about= (known afterapply)+bg_image= (known afterapply)+calendar_enabled= (known afterapply)+captcha_enabled=true+current_incidents_position="below_services"+custom_css= (known afterapply)+custom_domain_enabled= (known afterapply)+custom_footer= (known afterapply)+custom_header= (known afterapply)+custom_incident_types_enabled= (known afterapply)+custom_js= (known afterapply)+date_format= (known afterapply)+date_format_enforce_everywhere= (known afterapply)+discord_notifications_enabled= (known afterapply)+display_about= (known afterapply)+display_calendar=true+display_uptime_graph=true+domain= (known afterapply)+email_confirmation_template= (known afterapply)+email_layout_template= (known afterapply)+email_notification_template= (known afterapply)+email_templates_enabled= (known afterapply)+enable_auto_translations= (known afterapply)+feed_enabled=true+google_calendar_enabled= (known afterapply)+google_chat_notifications_enabled= (known afterapply)+head_code= (known afterapply)+header_bg_color1="009688"+header_bg_color2="0c91c3"+header_fg_color="ffffff"+header_logo_text= (known afterapply)+hide_watermark= (known afterapply)+history_limit_days=90+incident_header_color="009688"+incident_link_color= (known afterapply)+info_notices_enabled=true+inserted_at= (known afterapply)+link_color="0c91c3"+locked_when_maintenance= (known afterapply)+maintenance_notification_hours=6+major_notification_hours=3+mattermost_notifications_enabled= (known afterapply)+member_restricted= (known afterapply)+minor_notification_hours=6+name="Example Terraform Status Page"+noindex= (known afterapply)+notification_email= (known afterapply)+notify_by_default= (known afterapply)+public_company_name= (known afterapply)+reply_to_email= (known afterapply)+restricted_ips= (known afterapply)+scheduled_maintenance_days=7+slack_subscriptions_enabled= (known afterapply)+sms_notifications_enabled= (known afterapply)+status_maintenance_color="5378c1"+status_major_color="e75a53"+status_minor_color="FFA500"+status_ok_color="48CBA5"+subdomain= (known afterapply)+subscribers_enabled=true+support_email= (known afterapply)+teams_notifications_enabled= (known afterapply)+theme_configs= (known afterapply)+theme_selected="default"+time_format= (known afterapply)+time_zone="America/New_York"+translations= (known afterapply)+tweet_by_default= (known afterapply)+tweeting_enabled=true+twitter_public_screen_name= (known afterapply)+updated_at= (known afterapply)+uptime_graph_days=90+url="example.com" } }Plan:1toadd,0tochange,0todestroy.------------------------------------------------------------------------
In this case, the plan shows you that Terraform will create a new status page when you run terraform apply. After verifying the details, execute the plan to provision the status page resource in your StatusPal account:
terraformapply
Every time you apply changes, Terraform asks you to confirm the actions you've told it to run. Type "yes".
While it's running, Terraform sends logs to your console:
Log in to StatusPal and navigate to /admin/orgs/:organization_id to confirm that Terraform created your new status page in your organization.
At this point you can add services to your status page:
# Manage example service of the previously defined example status page's subdomain.resource "statuspal_service" "example" { status_page_subdomain = statuspal_status_page.example.status_page.subdomain service = { name ="Example Terraform Service" }}# Manage example child service of the previously defined example service.resource "statuspal_service" "child" { status_page_subdomain = statuspal_status_page.example.status_page.subdomain service = { name ="Example Terraform Child Service" parent_id = statuspal_service.example.service.id }}
Run terraform plan again to see what will happen if you apply the plan.
terraformplan
You should see the following output:
# Example output------------------------------------------------------------------------statuspal_status_page.example:Refreshingstate... [id=placeholder]Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+createTerraformwillperformthefollowingactions:# statuspal_service.child will be created+resource"statuspal_service""child"{+id= (known afterapply)+service={+auto_incident= (known afterapply)+auto_notify= (known afterapply)+children_ids= (known afterapply)+current_incident_type= (known afterapply)+description= (known afterapply)+display_response_time_chart= (known afterapply)+display_uptime_graph= (known afterapply)+id= (known afterapply)+inbound_email_id= (known afterapply)+incident_type= (known afterapply)+inserted_at= (known afterapply)+is_up= (known afterapply)+monitoring= (known afterapply)+name="Example Terraform Child Service"+order= (known afterapply)+parent_id= (known afterapply)+parent_incident_type= (known afterapply)+pause_monitoring_during_maintenances= (known afterapply)+ping_url= (known afterapply)+private= (known afterapply)+private_description= (known afterapply)+translations= (known afterapply)+updated_at= (known afterapply) }+status_page_subdomain="example-com" }# statuspal_service.example will be created+resource"statuspal_service""example"{+id= (known afterapply)+service={+auto_incident= (known afterapply)+auto_notify= (known afterapply)+children_ids= (known afterapply)+current_incident_type= (known afterapply)+description= (known afterapply)+display_response_time_chart= (known afterapply)+display_uptime_graph= (known afterapply)+id= (known afterapply)+inbound_email_id= (known afterapply)+incident_type= (known afterapply)+inserted_at= (known afterapply)+is_up= (known afterapply)+monitoring= (known afterapply)+name="Example Terraform Service"+order= (known afterapply)+parent_id= (known afterapply)+parent_incident_type= (known afterapply)+pause_monitoring_during_maintenances= (known afterapply)+ping_url= (known afterapply)+private= (known afterapply)+private_description= (known afterapply)+translations= (known afterapply)+updated_at= (known afterapply) }+status_page_subdomain="example-com" }Plan:2toadd,0tochange,0todestroy.------------------------------------------------------------------------
In this case, the plan shows you that Terraform will create 2 services when you run terraform apply. Maybe you already noticed, it's possible to create child services also. After verifying the details, execute the plan to provision the service resources in your example status page:
terraformapply
The same procedure is before, you need to write "yes" to approve the changes.
While it's running, Terraform sends logs to your console:
Again, you can navigate to /admin/status_pages/:status_page_subdomain/services to confirm that Terraform created your new services in your status page.
4. Configure StatusPal monitoring on a service
To configure StatusPal monitoring on a service you will need the change a few attributes.
We will use the previously defined service as an example:
resource "statuspal_service" "example" { status_page_subdomain = statuspal_status_page.example.status_page.subdomain service = { name ="Example Terraform Service" monitoring ="internal"# <- this means to use the StatusPal monitoring ping_url ="https://www.statuspal.io"# <- this is the URL to ping in every minute }}
5. Configure 3rd-party monitoring with incoming webhook URL
To configure 3rd-party monitoring with incoming webhook URL on a service you will need the change a few attributes.
We will use the previously defined service as an example:
resource "statuspal_service" "example" { status_page_subdomain = statuspal_status_page.example.status_page.subdomain service = { name ="Example Terraform Service" monitoring = "webhook" # <- this means to use the incoming webhook monitoring
webhook_monitoring_service = "custom-jsonpath" # <- with this attribute you can the webhook monitoring service
webhook_custom_jsonpath_settings = { # <- this is the settings for custom-jsonpath type of webhook monitoring service
jsonpath ="$.status" expected_result ="\"up\"" } }}output "example_service_incoming_webhook_url" { value = statuspal_service.example.service.incoming_webhook_url}
After applying the plan with terraform apply you will be able to see the incoming webhook URL in the outputs: