You can manage Netlify sites using Terraform, but it’s not just about declarative infrastructure; it’s about treating your entire Netlify deployment – including site configuration, environment variables, and even redirects – as code.

Here’s a Netlify site managed with Terraform, deployed to example.netlify.app. Notice how the netlify_site resource defines the site name, the build image, and the repository details.

resource "netlify_site" "my_app" {
  name                 = "my-awesome-app"
  repository_url       = "https://github.com/my-org/my-awesome-app"
  repository_provider  = "github"
  build_image          = "ubuntu-20.04"
  branch               = "main"
  cmd                  = "npm run build"
  dir                  = "dist"
  netlify_cancel_build = false
  split_test_enabled   = true
}

resource "netlify_environment_variable" "api_key" {
  site_id = netlify_site.my_app.id
  key     = "API_KEY"
  value   = "my-super-secret-key"
}

resource "netlify_redirect_rule" "spa_redirects" {
  site_id   = netlify_site.my_app.id
  from_path = "/*"
  to_path   = "/"
  status    = 200
  conditions = {
    "Language" = "en"
  }
}

This Terraform configuration goes beyond just provisioning a new site. It declares the site’s build settings, the source repository, and even critical runtime configurations like API keys and single-page application (SPA) redirects. When you run terraform apply, Terraform communicates with the Netlify API to create or update the site, its environment variables, and its redirect rules. This means your Netlify deployment becomes a reproducible, version-controlled entity, just like your application code.

The core problem this solves is drift. Without a system like Terraform, you might manually configure redirects, set environment variables in the Netlify UI, or tweak build settings. Over time, these manual changes become undocumented and inconsistent, making it hard to replicate your deployment elsewhere or understand its exact state. By codifying these aspects, you eliminate drift. Your Terraform state file becomes the single source of truth for your Netlify site’s configuration.

Internally, the Netlify Terraform provider acts as a translator. You define your desired Netlify infrastructure in HCL (HashiCorp Configuration Language), and the provider maps these resources to specific Netlify API endpoints. For netlify_site, it calls the POST /api/v1/sites or PUT /api/v1/sites/:site_id endpoints. For netlify_environment_variable, it uses POST /api/v1/sites/:site_id/env or PUT /api/v1/sites/:site_id/env/:env_id. The provider handles authentication (typically via a Netlify API token), request formatting, and response parsing, ensuring that your declared state matches the actual state in Netlify.

You control the entire Netlify experience through these resources. Want to add a new custom domain? Use the netlify_domain_nft resource. Need to configure feature flags? You might use netlify_site attributes for features like split_test_enabled. The provider exposes a wide array of Netlify’s capabilities, allowing you to manage DNS records, deploy keys, and more, all within your Terraform workflow.

The netlify_site resource supports the split_test_enabled attribute, which when set to true, tells Netlify to automatically enable split testing for your deployed site. This means Netlify will serve two versions of your site simultaneously, routing 50% of traffic to each, allowing you to A/B test different deployments without manual intervention or complex configuration.

This entire approach also makes disaster recovery and migration a breeze. If your Netlify account were compromised or you needed to move to a different Netlify team, you could simply re-apply your Terraform configuration, and your entire site infrastructure, including its settings, would be recreated.

When you define a netlify_redirect_rule with from_path = "/*" and to_path = "/", it doesn’t just redirect from any path to the root. It also implies that Netlify’s edge network will perform this redirection before any build artifacts are served, which is crucial for single-page applications (SPAs) where client-side routing handles paths. The status = 200 ensures that search engines don’t see these as broken links or non-existent pages, which is a common pitfall when setting up SPA redirects.

The next step is managing Netlify functions and their configurations as code.

Want structured learning?

Take the full Netlify course →