Consul-Terraform-Sync Part 3: Enterprise Integration

In Parts 1 and 2 of these series, I went through why and how you would use CTS. Now, let’s have a look at why and how we would run it with Terraform Cloud and Consul Enterprise.

At time of writing, support for Terraform Cloud is beta (available with CTS 0.4beta) while support for Terraform Enterprise came in a couple of weeks ago with CTS 0.3.


You will need:

  • Terraform Cloud (although everything in the blog post also applies to self-managed Terraform Enterprise)
  • Consul Enterprise

Terraform Cloud

Terraform Cloud can be found at I’ve blogged about it in the past although it’s changed a fair bit since I blogged about it a year ago. Getting onboarded should only take you a few minutes.

Consul Enterprise

In my previous post, I ran Consul locally in dev mode with the default license but for this test, I got myself a Consul Enterprise License (you can get a trial license for 30 days), exported its location as an environment variable (instructions here):

$ export CONSUL_LICENSE_PATH=consul_license.hclic

I created a service and stored its definition in a ./consul.d directory:

  "service": {
    "name": "fortinet-service",
    "id": "fortinet-service-s1-ent",
    "address": "",
    "meta": {
      "subnet_mask" : ""

And finally I started Consul (you can see it’s running the Enterprise version)

$ consul agent -dev -enable-script-checks -config-dir=./consul.d
==> Starting Consul agent...
           Version: '1.10.3+ent'
           Node ID: 'd6a6684b-70d4-af77-8b25-39d8d2fa7503'
         Node name: 'ip-172-31-10-207'
        Datacenter: 'dc1' (Segment: '<all>')
            Server: true (Bootstrap: false)
       Client Addr: [] (HTTP: 8500, HTTPS: -1, gRPC: 8502, DNS: 8600)
      Cluster Addr: (LAN: 8301, WAN: 8302)
           Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false

I’ve downloaded and installed the Enterprise version of Consul-Terraform-Sync. Note that the feature is still beta as I type this down (7th October 2021):

$ consul-terraform-sync -version
consul-terraform-sync 0.4.0+ent-beta1
Compatible with Terraform >= 0.13.0, < 1.1.0

The CTS configuration is slightly different as we’re using Terraform Enterprise|Cloud to execute Terraform and to store the states:

driver "terraform-cloud" {
  hostname = ""
  organization = "nicovibert-org"
  token = "XXXXXXXXXXX"

  required_providers {
    fortios = {
      source = "fortinetdev/fortios"

You’ll get your token from your Terraform instance (instructions). The rest of the file should be identical to the one I described in my previous post.

That’s it! You should be ready to start running CTS:

$ consul-terraform-sync -config-file=cts-config.hcl
2021-10-07T11:45:59.750Z [INFO]  cli: 0.4.0+ent-beta1
2021-10-07T11:45:59.751Z [INFO]  cli: running controller in daemon mode
2021-10-07T11:45:59.751Z [INFO]  cli: setting up controller: type=readwrite
2021-10-07T11:45:59.751Z [INFO]  ctrl: initializing Consul client and testing connection
2021-10-07T11:45:59.755Z [INFO]  cli: watch and notify any license expiration events
2021-10-07T11:45:59.755Z [INFO]  cli: initializing controller
2021-10-07T11:45:59.756Z [INFO]  ctrl: initializing driver
2021-10-07T11:46:00.213Z [INFO]  ctrl: initializing all tasks
2021-10-07T11:46:00.213Z [INFO]  ctrl: initializing task: task=cts-enterprise
2021-10-07T11:46:00.310Z [INFO]  driver.terraform: retrieved 0 Terraform handlers for task: task_name=cts-enterprise
2021-10-07T11:46:01.109Z [INFO]  templates.tftmpl: overwriting file in root module for task: task_name=cts-enterprise
2021-10-07T11:46:01.112Z [INFO]  templates.tftmpl: overwriting file in root module for task: task_name=cts-enterprise
2021-10-07T11:46:02.305Z [INFO]  driver.tfc: uploading new configuration version for workspace: workspace_name=cts-enterprise
2021-10-07T11:46:04.182Z [INFO]  driver.tfc: uploaded new configuration version for workspace: config_version_id=cv-18bmjzv1Xuy1BXjh workspace_name=cts-enterprise
2021-10-07T11:46:04.704Z [INFO]  driver.tfc: initialized task: task_name=cts-enterprise
2021-10-07T11:46:04.704Z [INFO]  ctrl: driver initialized
2021-10-07T11:46:04.704Z [INFO]  ctrl: executing all tasks once through
2021-10-07T11:46:04.955Z [INFO]  ctrl: executing task: task_name=cts-enterprise
2021-10-07T11:46:05.200Z [INFO]  driver.tfc: creating new run: workspace_name=cts-enterprise
2021-10-07T11:46:05.536Z [INFO]  driver.tfc: created new run: run_id=run-xaXsJWoPRz4sJxR4 workspace_name=cts-enterprise
2021-10-07T11:46:05.536Z [INFO]  driver.tfc: run results can be viewed at run URL: run_url=
2021-10-07T11:46:05.536Z [INFO]  ctrl: task completed: task_name=cts-enterprise
2021-10-07T11:46:05.536Z [INFO]  ctrl: all tasks completed once
2021-10-07T11:46:05.536Z [INFO]  api: starting server: port=8558

What is happening is:

  • CTS connects back to Terraform Cloud and will either create a new workspace or uses an existing one (I had already created the cts-enterprise one)
  • CTS generates the Terraform Config files
  • CTS monitors Consul for any services. As I am just booting up CTS for the first time, it can see that there is a service that is relevant.
  • CTS will upload the relevant variables to Terraform Cloud and TFC will queue up a run on the workspace.

Terraform Run (which consists of Terraform Plan, Terraform Cost Estimation and Sentinel Policies and finally Terraform Apply) is executed by TF Enterprise/Cloud:

You can apply Sentinel policies if you’re worried that Network Infrastructure Automation is not going wildly out of control.

And if you need to approve or deny a change, you can be notified by email, Slack or anything else with a webhook.

And that’s it!

In summary, the value of using CTS Enterprise is really about making this magical network infra automation….well, enterprisey for lack of a better word: you get the automation (cool!) but with the required guard rails (enabled by Sentinel policies), auditing (with state files and secure variables in TFE/TFC) and operational aspects (like notifications) that you might not have with the Open Source version.

Thanks for reading.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s