
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Sat, 04 Apr 2026 15:46:53 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Deploy Workers using Terraform]]></title>
            <link>https://blog.cloudflare.com/deploy-workers-using-terraform/</link>
            <pubDate>Thu, 13 Sep 2018 16:03:15 GMT</pubDate>
            <description><![CDATA[ Today we're excited to announce that Cloudflare Workers are now supported in the Cloudflare Terraform Provider.  ]]></description>
            <content:encoded><![CDATA[ <p></p><p>Today we're excited to announce that Cloudflare Workers are now supported in the <a href="https://www.terraform.io/docs/providers/cloudflare/index.html">Cloudflare Terraform Provider</a>.</p><p><a href="https://www.terraform.io/">Terraform</a> is a fantastic tool for configuring your infrastructure. Traditionally if you wanted to spin up, tear down or update some of your infrastructure you would have to click around on a website or make some API calls, which is prone to human error. With Terraform, you define your infrastructure in simple, declarative configuration files and let Terraform figure out how to make the API calls for you. This also lets you treat your infrastructure like your code. You can check your Terraform configuration files into version control and integrate them into your normal software development workflow.</p><p>Terraform integrates with <a href="https://www.terraform.io/docs/providers/">many infrastructure providers</a> including Cloudflare. If you'd like to read more about setting up Terraform with Cloudflare, check out <a href="/getting-started-with-terraform-and-cloudflare-part-1/">Getting started with Terraform and Cloudflare</a>. In this post, I'm going to focus specifically on how to integrate <a href="https://www.cloudflare.com/products/cloudflare-workers/">Cloudflare Workers</a> with Terraform.</p><p>In this example we're going to create <a href="https://partyparrot.business">partyparrot.business</a>, and we're going to serve the whole site out of a worker without any origin server. We're starting from scratch here, but if you're already using Cloudflare workers and want to migrate to managing your workers with Terraform, you'll need to import your existing script and routes so that Terraform knows about them. See the "Importing your existing workers" section at the end.</p>
    <div>
      <h3>Prerequisites</h3>
      <a href="#prerequisites">
        
      </a>
    </div>
    <ul><li><p><a href="https://www.terraform.io/intro/getting-started/install.html">Install Terraform</a></p></li><li><p>Provide your Cloudflare credentials via environment variables</p><ul><li><p>Set <code>CLOUDFLARE_EMAIL</code> to your email address</p></li><li><p>Set <code>CLOUDFLARE_TOKEN</code> to your <a href="https://support.cloudflare.com/hc/en-us/articles/200167836-Where-do-I-find-my-Cloudflare-API-key-">Cloudflare API key</a></p></li><li><p>If you're on an Enterprise plan and want to use multiple scripts, you'll also need to set <code>CLOUDFLARE_ORG_ID</code> to your account ID. You can find your account ID by using the <a href="https://api.cloudflare.com/#accounts-list-accounts">List Accounts API</a></p></li></ul></li></ul>
    <div>
      <h3>Create the Terraform config file</h3>
      <a href="#create-the-terraform-config-file">
        
      </a>
    </div>
    <p>Create a file with any name and give it a <code>.tf</code> file extension. This is where we'll define our Terraform resources. In this file, first we'll need to setup the Cloudflare provider:</p>
            <pre><code>provider "cloudflare" {}</code></pre>
            <p>You could define your credentials in this file, but in general it's better to use environment variables so that you can check the configuration file into version control without including any private data.</p><p>Next we're going to create a variable named <code>zone</code>. One of the benefits about defining the zone in a variable as opposed to hard-coding it is that you can setup a separate staging domain and use the same Terraform configuration as your production domain. See the <a href="https://www.terraform.io/docs/configuration/variables.html">documentation</a> for more information on working with variables.</p>
            <pre><code>variable "zone" {
  default = "partyparrot.business"
}</code></pre>
            
    <div>
      <h3>Setting up the worker script</h3>
      <a href="#setting-up-the-worker-script">
        
      </a>
    </div>
    <p>Now let's write our worker script. If you're looking for inspiration, check out some <a href="https://developers.cloudflare.com/workers/recipes/">Worker recipes</a>. For this example, I'll use <a href="https://gist.github.com/jRiest/7893cf10c550057ce1ff53f270683e1c#file-party_parrot_worker-js">this script</a> and name it <code>party_parrot_worker.js</code>.</p><p>Next we need to add a <code>cloudflare_worker_script</code> resource to our Terraform config and reference the script file. Open your <code>.tf</code> file and add the following:</p>
            <pre><code>resource "cloudflare_worker_script" "main_script" {
  zone = "${var.zone}"
  content = "${file("party_parrot_worker.js")}"
}</code></pre>
            <p>If you're new to Terraform, check out the <a href="https://www.terraform.io/docs/configuration/resources.html">Terraform Resource documentation</a> to learn more about this schema. Here we provide 2 parameters, the <code>zone</code> which references the variable we defined earlier and <code>content</code> which references the file we just created.</p><p><b>NOTE:</b> The <a href="https://www.cloudflare.com/plans/enterprise/">Cloudflare Enterprise plan</a> supports using multiple (named) scripts. To use this, the parameters will be slightly different. Remove the <code>zone</code> parameter since named scripts are not tied to a particular zone and instead add a <code>name</code> parameter to define the name of the script. See <a href="https://www.terraform.io/docs/providers/cloudflare/r/worker_script.html">the cloudflare_worker_script documentation</a> for an example.</p>
    <div>
      <h3>Setting up the worker routes</h3>
      <a href="#setting-up-the-worker-routes">
        
      </a>
    </div>
    <p>In order for the worker to start handling traffic, we'll also need to define at least one route. To do so, add a <code>cloudflare_worker_route</code> resource to the Terraform config.</p>
            <pre><code>resource "cloudflare_worker_route" "catch_all_route" {
  zone = "${var.zone}"
  pattern = "*${var.zone}/*"
  enabled = true
  depends_on = ["cloudflare_worker_script.main_script"]
}</code></pre>
            <p>Just like with the script resource, the <code>zone</code> parameter references the variable we defined earlier.</p><p>The <code>pattern</code> parameter defines which requests should be sent to the worker. In this example we use a route pattern like <code>*partyparrot.business*</code> which will match all traffic. If, however, you only want your worker to handle a subset of requests to your zone, you can define a more specific pattern like <code>mysubdomain.example.com/*</code> or <code>*example.com/mypath*</code>. More information on route patterns is available <a href="https://developers.cloudflare.com/workers/api/route-matching/">here</a>.</p><p>The <code>enabled</code> parameter specifies that requests that match the pattern <b>should</b> run the worker. Alternatively, you can set <code>enabled</code> to <code>false</code> which would mean that any requests that match the pattern <b>should not</b> run the worker. You can create multiple route patterns, and more-specific route patterns apply before less-specific route patterns. For example, you could create one route pattern like <code>example.com/assets/*</code> and set <code>enabled = false</code> then create another pattern like <code>*example.com*</code> and set <code>enabled = true</code>. This would enable the worker for all traffic <i>except</i> for requests that match <code>example.com/assets/*</code>.</p><p>Finally, we set <code>depends_on</code> to point to the script resource we created above. In general, Terraform will try to create resources in parallel, but you may get an error if you try to create a route before you have a script. By using the <code>depends_on</code> parameter, Terraform will know to create the script first before creating the route.</p><p><b>NOTE:</b> As with the script resource, some of the parameters are different if you're on the Enterprise plan and using multiple scripts. Remove the <code>enabled</code> parameter and instead set <code>script_name = "${cloudflare_worker_script.your_script_resource.name}"</code> to specify which script the route should run. By directly referencing the script resource using this syntax, Terraform already knows that the route depends on the script, so you can also remove the <code>depends_on</code> parameter. You can see more details in <a href="https://www.terraform.io/docs/providers/cloudflare/r/worker_route.html">the cloudflare_worker_route documentation</a>.</p>
    <div>
      <h3>Applying the Terraform config</h3>
      <a href="#applying-the-terraform-config">
        
      </a>
    </div>
    <p>Now that we've defined our script and route resources in the config file, we're ready to deploy! To initialize Terraform, run <code>terraform init</code></p>
            <pre><code>$ terraform init

Initializing provider plugins...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.</code></pre>
            <p>Now to deploy the changes, run <code>terraform apply</code>. Terraform will show you a preview of the changes it will make.</p>
            <pre><code>$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + cloudflare_worker_route.catch_all_route
      id:           &lt;computed&gt;
      enabled:      "true"
      multi_script: &lt;computed&gt;
      pattern:      "*partyparrot.business/*"
      zone:         "partyparrot.business"
      zone_id:      &lt;computed&gt;

  + cloudflare_worker_script.main_script
      id:           &lt;computed&gt;
      content:      "...omitted for brevity..."
      zone:         "partyparrot.business"
      zone_id:      &lt;computed&gt;


Plan: 2 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:</code></pre>
            <p>If everything looks good, type <code>yes</code> and press return to apply the changes.</p>
            <pre><code>cloudflare_worker_script.main_script: Creating...
  content: "" =&gt; "...omitted for brevity..."
  zone:    "" =&gt; "partyparrot.business"
  zone_id: "" =&gt; "&lt;computed&gt;"
cloudflare_worker_script.main_script: Creation complete after 1s (ID: zone:partyparrot.business)
cloudflare_worker_route.catch_all_route: Creating...
  enabled:      "" =&gt; "true"
  multi_script: "" =&gt; "&lt;computed&gt;"
  pattern:      "" =&gt; "*partyparrot.business/*"
  zone:         "" =&gt; "partyparrot.business"
  zone_id:      "" =&gt; "&lt;computed&gt;"
cloudflare_worker_route.catch_all_route: Creation complete after 0s (ID: af595c1bb7cd4d1698c4d6cbcb364662)

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.</code></pre>
            <p>Congratulations, your worker script and route are deployed! You can see the example script running at <a href="https://partyparrot.business/">partyparrot.business</a>.</p><p>As you make changes to your script or Terraform config, you can run <code>terraform apply</code> again and Terraform will figure out what's changed and deploy any updates.</p>
    <div>
      <h3>Importing your existing workers</h3>
      <a href="#importing-your-existing-workers">
        
      </a>
    </div>
    <p>If you're already using Cloudflare Workers but want to start managing them via Terraform, you'll need to let Terraform know about your existing configuration so it knows how to apply changes going forward.</p><p>First you’ll need to create your <code>.tf</code> file and add <code>cloudflare_worker_script</code> and <code>cloudflare_worker_route</code> resources for all of your existing scripts and routes.</p><p>Next you'll need to individually run the appropriate <code>terraform import ...</code> command for each script and route resource. The import command takes two arguments:</p><ul><li><p>the identifier of the resource that you defined in your <code>.tf</code> file (ex: <code>cloudflare_worker_script.main_script</code> or <code>cloudflare_worker_route.catch_all_route</code>)</p></li><li><p>an ID that's used to lookup the resource from the cloudflare API. See the <a href="https://www.terraform.io/docs/providers/cloudflare/r/worker_script.html">cloudflare_worker_script</a> and <a href="https://www.terraform.io/docs/providers/cloudflare/r/worker_route.html">cloudflare_worker_route</a> documentation for more information.</p></li></ul>
    <div>
      <h3>Wrapping up</h3>
      <a href="#wrapping-up">
        
      </a>
    </div>
    <p>The complete script and terraform configuration file for this example are hosted <a href="https://gist.github.com/jRiest/7893cf10c550057ce1ff53f270683e1c">on Github</a>.</p><p>Whether you're already using Cloudflare Workers or just getting started, Terraform can be a great way to manage your Workers configuration. If you're interested in learning more, here's a few useful links:</p><ul><li><p><a href="https://developers.cloudflare.com/workers/">Cloudflare Workers documentation</a></p></li><li><p><a href="https://developers.cloudflare.com/terraform/">Cloudflare Terraform Provider documentation</a></p></li><li><p><a href="/tag/workers/">More Workers blog posts</a></p></li><li><p><a href="/tag/terraform/">More Terraform blog posts</a></p></li><li><p><a href="https://github.com/terraform-providers/terraform-provider-cloudflare">terraform-provider-cloudflare source</a></p></li></ul> ]]></content:encoded>
            <category><![CDATA[Cloudflare Workers]]></category>
            <category><![CDATA[Serverless]]></category>
            <category><![CDATA[JavaScript]]></category>
            <category><![CDATA[Terraform]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Programming]]></category>
            <category><![CDATA[Developers]]></category>
            <category><![CDATA[Developer Platform]]></category>
            <guid isPermaLink="false">5QupFF8DVLR5KBikEm5App</guid>
            <dc:creator>Jake Riesterer</dc:creator>
        </item>
    </channel>
</rss>