I’ve been researching setting up DigitalOcean droplets via Terraform Cloud and while I’m still relatively new to this I’m stumped by SSH connections for remote-exec. For my tinkering needs I’m just trying to get a generic ubuntu droplet running then have remote-exec run apt update/upgrade followed by installing nginx.
Running from my local machine I can setup the connection to grab a private SSH key from a local file but I’m a little confused as to how to accomplish this with Terraform Cloud. I have tried puttingthe key into an input variable and an environment variable by removing the line breaks but haven’t managed to get it working.
I’m certain I’m missing something elementary - does anyone have any suggestions to accomplish this or a keyword I’m missing in my google searches that might help?
1 Like
Hi @ewokninja!
As described on the provisioners documentation page, provisioners are a feature of last resort because they introduce a lot of additional setup complexity, including SSH keys, the need for direct network connectivity from Terraform to instances, etc.
Although that documentation doesn’t talk about DigitalOcean specifically, DigitalOcean does have a user_data
feature similar to that of Amazon EC2. If the Ubuntu image includes cloud-init
(Ubuntu images on cloud platforms usually do) then you can use cloud-init
to configure your droplet by placing either a cloud-init
configuration or a shell script directly into the user_data
argument of digitalocean_droplet
.
cloud-init
has a built-in ability to interact with apt
for package upgrade and installation, so you might be able to get the result you want declaratively with a cloud-init
configuration like this:
# JSON is a subset of YAML, so we can use JSON encoding
# here for simplicity as long as we add the #cloud-init
# prefix to help cloud-init detect it as a configuration.
user_data = "#cloud-config\n${jsonencode({
package_update = true
package_upgrade = true
packages = ["nginx"]
})}"
The key advantage of using cloud-init
via user_data
is that this configuration is then sent to the droplet indirectly via the DigitalOcean API, rather than requiring Terraform to connect directly to the droplet and log in over SSH.
This avoids the need to configure SSH credentials and the need to have the SSH server accessible from the host where Terraform is running, and it will also generally allow your instance to initialize faster because the initialization process can begin immediately that cloud-init
loads, rather than pausing initialization until Terraform has successfully connected via SSH.
Terraform Cloud does have a mechanism to configure an SSH key for a workspace, which you can use in situations where SSH-based provisioning is unavoidable, but I think it should be unnecessary in your case because cloud-init
and user_data
can solve the same problem in a simpler way.
2 Likes
Hi @apparentlymart !
Thank you for the quick response and the details! It makes a lot of sense to make use of cloud-init
/ user-data
and I’ll go down that path with my experimentation!
Is there a best way to place keys into Terraform Cloud’s Variables? I need it for the OCI provider’s connection.
1 Like