In this blog post, we'll show how Terraform can create a running instance of Discourse on DigitalOcean in one command.
Following the release of Terraform 0.2, we wanted to publish the first of several examples of using Terraform to automate the creation and management of infrastructure.
Terraform is abstract, so it can be hard to grasp and understand it's capabilities without seeing and using it in a real world example. Even if you don't intend to keep Discourse running, this may be a good chance to learn more about Terraform.
Discourse is a discussion platform "built for the next decade of the Internet". That means it uses modern frameworks and tools to run. Because of this, installing Discourse can be challenging for new and inexperienced users.
Terraform, of course, is intended for a technical audience, but there's also potential to build tooling around it to take advantage of it's automation and friendly declarative configuration.
Discourse 1.0 was just released, so we find it fitting to use it to see Terraform in action. This configuration was based on the beginner installation guide published by Discourse.
Before running terraform apply
, you'll need to have accounts and access information for the configured providers.
Note: This example uses the DigitalOcean and Mailgun providers, but you could modify the configuration to use any other Terraform providers in place or in addition, like Route53 or DNSimple. For a full list of providers, visit the documentation.
curl -X GET "https://api.digitalocean.com/v2/account/keys" -H "Authorization: Bearer $ACCESS_TOKEN"
example.com
) and point the nameservers at DigitalOcean.Terraform is configured by .tf
files. By default, Terraform collects all *.tf
files in a directory and merges them together.
You'll need to clone the following example repository with Git:
$ git clone https://github.com/pearkes/discourse-terraform.git
Once the repository is retrieved from GitHub, we can try running Terraform.
Although not required for a terraform apply
, terraform plan
helps you visualize what Terraform will do. In this case, you should see output similar to the following:
$ terraform plan \
-var 'developer_email=YOUR_ACCESS_KEY' \
-var 'smtp_password=YOUR_SECRET_KEY' \
-var 'domain=YOUR_DOMAIN' \
-var 'ssh_key_id=YOUR_SSH_KEY_ID' \
-var 'do_token=YOUR_DO_TOKEN' \
-var 'mailgun_key=YOUR_MAILGUN_KEY' \
-var 'ssh_key_path=YOUR_KEY_PATH'
...
+ digitalocean_domain.discourse
ip_address: "" => "${digitalocean_droplet.discourse.ipv4_address}"
name: "" => "YOUR_DOMAIN"
+ digitalocean_droplet.discourse
backups: "" => "<computed>"
image: "" => "ubuntu-14-04-x64"
ipv4_address: "" => "<computed>"
ipv4_address_private: "" => "<computed>"
ipv6: "" => "<computed>"
ipv6_address: "" => "<computed>"
ipv6_address_private: "" => "<computed>"
locked: "" => "<computed>"
name: "" => "discourse"
private_networking: "" => "<computed>"
region: "" => "nyc2"
size: "" => "2gb"
ssh_keys.#: "" => "1"
ssh_keys.0: "" => "YOUR_SSH_KEY_ID"
status: "" => "<computed>"
+ mailgun_domain.mail
name: "" => "YOUR_DOMAIN"
receiving_records.#: "" => "<computed>"
sending_records.#: "" => "<computed>"
smtp_login: "" => "<computed>"
smtp_password: "" => "YOUR_SECRET_KEY"
spam_action: "" => "disabled"
wildcard: "" => "<computed>"
If you're happy with the output, you can move on to apply and create the resources.
$ terraform apply \
-var 'developer_email=YOUR_ACCESS_KEY' \
-var 'smtp_password=YOUR_SECRET_KEY' \
-var 'domain=YOUR_DOMAIN' \
-var 'ssh_key_id=YOUR_SSH_KEY_ID' \
-var 'do_token=YOUR_DO_TOKEN' \
-var 'mailgun_key=YOUR_MAILGUN_KEY' \
-var 'ssh_key_path=YOUR_KEY_PATH'
...
This will create your infrastructure, showing you the output along the way. In this example, the following steps occur:
The whole process takes some time, depending on several factors, as the provisioner on the server is installing, configuring and restarting Discourse. Under the hood, this uses Docker, which Terraform happily provisions on top of the DigitalOcean droplet.
Additionally, DigitalOcean DNS may take some time to propagate.
If you're interested in seeing detailed logs of what Terraform is doing, run the command with TF_LOG=1 ...
prepended.
Setting up Discourse with Terraform is an interesting example of what kind of automation is possible.
Part of the value of Terraform is how it combines resources, as demonstrated with Mailgun, and the resulting provisioning of SMTP credentials for the application to read.
If you're interested in learning more about Terraform, follow the links below.
A recap of HashiCorp infrastructure and security news and developments from Google Cloud Next, from scaling infrastructure as code to fighting secrets sprawl and more.
New in Terraform 1.8: Provider-defined functions let users extend Terraform with custom capabilities. Plus, refactoring can now be done across resource types.
See usage examples of Terraform 1.8's new launch-day provider-defined functions for AWS, Google Cloud, and Kubernetes.