Terraform and Packer with Digital Ocean
Automate all the things
- tags
- terraform
- packer
- devops
Contents
Terraform orchastrates the setting up of your infrastructure, and packer helps you build images. We are going to setup terraform to work with Digital Ocean, and then use package to create and image and deploy it.
Install terraform
Install terraform from the download page. I’m on Linux, so we’ll download the latest version and put it in /usr/local/bin
.
|
|
Setup Digital Ocean API
We need two tokens. One for accessing the Digital Ocean API for infrastructure, and the other to access the spaces API.
Log into your account at cloud.digitalocean.com and go to API
on the left. Generate a new access token with read and write privileges.
Copy this token and keep it somewhere safe. Our terraform scripts will access this token, but we’ll keep the actual values in the environment rather than hardcoding them. We’ll be able to pass things in when prefixed with TF_VAR
.
Then create a Spaces API key, which will have an Access Token and a Secret Key.
We are going to setup 4 environment variables that we will use for terraform.
- do_token: the actual API token
- do_access_key: the spaces api access key
- do_secret_key: the spaces api secret key
- ssh_fingerprint: a finger print for installing a key on a droplet
Note that my public key is in ~/.ssh/id_rsa.pub
|
|
Create provider.tf
The first file we are going to use is provider.tf
:
|
|
We are declaring the variables at top, which will look first in the environment for them and if not found will prompt you to enter a value. We are going to use the name for the space that we’re storing the terraform state in multiple places, so we’ll define it as a variable, though unforunately we’ll need to hard code it when we setup the terraform backend.
Now run terraform init
. This should download the digitalocean
plugin in the .terraform
directory, and we should be ready to start making terraform commands! When we do terraform plan
it should say that everything is up to date.
Create a secure store for holding the config
Now lets use terraform to create a digitalocean store to save our deployment state. spaces.tf
:
|
|
As a reminder, space names need to be globally unique so you’ll need to update your name to make it your own. Now run terraform plan
to see what its going to do. You should see that it wants to create the space.
Run terraform apply
to actually bring your environment up!
Once your space is up and running, lets configure terraform to use this as a backend. backend.tf
:
|
|
We are using the S3 backend but pointing it to Digital Ocean’s endpoint. If you don’t know what endpoint you are using, you can see inside of the Digital Ocean console.
I don’t want to keep my access keys inside this file, but we can’t pull them out using variables due to the way that terraform works. So since we are pretending to be AWS, let’s set the environment variables for AWS access to the keys that we got from the Spaces API.
Note: While I don’t use AWS and therefor don’t mind messing with these keys, if you do use AWS from the shell you are working in this will point to the wrong place.
|
|
We need to run terraform init
again to pull down the right plugins and configure everything. If all goes well, you’ll be asked to migrate your local state over. Go for it!
Create a droplet
Now that we have the plumbing working, lets create an actual droplet to play with.
In droplets.tf.orig
:
|
|
When going through this, rename to droplet.rf
. Later, we will be editing this file and so this is the base version of it.
You can find a list of Digital Ocean image and sizes to choose from, here we are using debian-10
and one of the smaller vms.
We also define an output
named ip
that pulls from the digital ocean API based on what has been created.
Additionally we have added an SSH key to the image.
So to connect, we can do
|
|
And you should be able to connect to your server.
Creating a custom image
From this point you should be able to add other services with terraform to wire up your application. We’ll skip a more elaborate network and service configuration – which is really where terraform makes sense – since there are plenty of other places that document that.
Instead, lets look at how to build a custom image that, perhaps, would contain your application. We’re going to use packer
to build this image, on which we’ll just install docker
. There’s already an official docker image in Digital Ocean so this is really just an excersize so you get the idea.
|
|
Now we create a docker.json
file that we’ll give to packer
that will provision the instance for us. Inside you’ll notice that I named the snapshot packer-docker-0.0.1
. In a real build process, this should probably be passed into packer.
|
|
And then a script that will be run on the build image that actually installs docker. docker_install.sh
:
|
|
We also need to set the region as the same you have it in the providers.tf
file.
|
|
Then run packer validate docker.json
to make sure that everything is copacitic. Once that’s good, then run packer build docker.json
.
Telling terraform to use your image
Once this is done, use this new droplets.tf
file to deploy this image onto your droplet. The first stanza looks up the image from the snapshot name, and then we use that inside of the image
attribute to tell terraform
which droplet should be running.
|
|
Now lets test it out:
|
|
And then connect:
|
|
Once it connects, you should be able to run on the host machine:
|
|
At which point we end our tutorial!
Cleanup
To clean up everything, you can run terraform destroy
. This will leave the snapshot, which was created by packer
and not managed by terraform
, and it will probably leave the space that we created since its not empty. Which is fine, since its better to keep the state around anyway, these things can be cleaned up by hand.
This is basically just a howto to get things initially setup, there’s a lot more you can do with organizing your files and managing different environments. The droplet that we created is on the public internet which is where most of my toys live, and we didn’t explore the more interesting parts of terraform where you setup networks and other services. But most of the tutorials I’ve seen are for setting things up with AWS, and I wanted to see how to get it done with Digital Ocean.
References
- https://www.digitalocean.com/community/tutorials/how-to-use-terraform-with-digitalocean
- https://medium.com/@chris_linguine/dont-push-your-terraform-state-files-945cfdf71f88
- https://www.terraformupandrunning.com/
- https://dev.to/jmarhee/digitalocean-spaces-as-a-terraform-backend-3lck
- https://slugs.do-api.dev/
- https://github.com/gokhansengun/packer-terraform-demo
Previously
Next