├── .gitignore ├── README.md ├── main.tf ├── outputs.tf └── variables.tf /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | 11 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 12 | # .tfvars files are managed as part of configuration and so should be included in 13 | # version control. 14 | # 15 | # example.tfvars 16 | 17 | # Ignore override files as they are usually used to override resources locally and so 18 | # are not checked in 19 | override.tf 20 | override.tf.json 21 | *_override.tf 22 | *_override.tf.json 23 | 24 | # Include override files you do wish to add to version control using negated pattern 25 | # 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DigitalOcean Spaces as a Terraform Backend 2 | 3 | Demonstrates how to use [DigitalOcean Spaces](https://www.digitalocean.com/products/spaces/) as a [Terraform Backend](https://www.terraform.io/docs/backends/index.html). 4 | 5 | DigitalOcean Spaces are `S3` compatible, making the large ecosystem of `S3` tools and libraries available. 6 | 7 | ## Prerequisites 8 | 9 | - Create a `Space` via the DigitalOcean console or CLI 10 | - A Spaces `Access Key` and `Secret` 11 | - The [`aws cli`](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) installed 12 | - _Optional:_ A DigitalOcean personal access token (used to create an example Droplet) 13 | 14 | ## Setup 15 | 16 | We can use the [`S3`](https://www.terraform.io/docs/backends/types/s3.html) Terraform Backend to instead point to our `Space`. 17 | 18 | The required keys are `endpoint`, `key`, and `bucket`. 19 | 20 | - `endpoint`: Available in the Settings of your `Space`. 21 | - `key`: path and name of `.tfstate` file that will be written 22 | - `bucket`: the name of your `Space` 23 | 24 | ```hcl 25 | terraform { 26 | backend "s3" { 27 | endpoint = "sfo2.digitaloceanspaces.com" 28 | key = "terraform.tfstate" 29 | bucket = "rappiddev-terraform-remote-state" 30 | region = "us-west-1" 31 | skip_requesting_account_id = true 32 | skip_credentials_validation = true 33 | skip_get_ec2_platforms = true 34 | skip_metadata_api_check = true 35 | } 36 | } 37 | ``` 38 | 39 | ## Authentication 40 | 41 | Terraform uses the standard `.aws/credentials` file to authenticate to the `S3` backend. This is created by the `aws cli`. 42 | 43 | We can use [named profiles](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html) to create one to access DigitalOcean Spaces. 44 | 45 | ```bash 46 | aws configure --profile digitalocean 47 | ``` 48 | 49 | You can tell the `aws cli` (and the `terraform` command by extension) which profile to use by setting the `AWS_PROFILE` environment variable. 50 | 51 | ```bash 52 | export AWS_PROFILE=digitalocean 53 | ``` 54 | 55 | Verify it's set: 56 | 57 | ``` 58 | echo $AWS_PROFILE 59 | ``` 60 | 61 | ## Initialize Backend 62 | 63 | Once your named profile is configured and your shell knows which profile to use, Terraform can initialize. 64 | 65 | ```bash 66 | terraform init 67 | ``` 68 | 69 | If all goes well you should see: 70 | 71 | ```bash 72 | Terraform has been successfully initialized! 73 | ``` 74 | 75 | ## Optional: Create a Droplet 76 | 77 | Set environment variable `DIGITALOCEAN_TOKEN` with a DigitalOcean Personal Access Token: 78 | 79 | ```bash 80 | export DIGITALOCEAN_TOKEN="YOUR API TOKEN" 81 | ``` 82 | 83 | Add your SSH key fingerprint to `variables.tf`. Your key must be added in the DigitalOcean console. 84 | 85 | ```bash 86 | ssh-keygen -E md5 -lf ~/.ssh/id_rsa.pub | awk '{print $2}' 87 | ``` 88 | 89 | **Copy everything except the initial `MD5:`** and paste it into the variable. 90 | 91 | Create a \$5/month Ubuntu Droplet: 92 | 93 | ```bash 94 | terraform plan 95 | terraform destroy 96 | ``` 97 | 98 | To get the IP of the Droplet: 99 | 100 | ```bash 101 | terraform output ip 102 | ``` 103 | 104 | To SSH into the Droplet: 105 | 106 | ``` 107 | ssh root@ 108 | ``` 109 | 110 | To delete the Droplet: 111 | 112 | ``` 113 | terraform destroy 114 | ``` 115 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | backend "s3" { 3 | endpoint = "sfo2.digitaloceanspaces.com" 4 | key = "terraform.tfstate" 5 | bucket = "rappiddev-terraform-remote-state" 6 | region = "us-west-1" 7 | skip_requesting_account_id = true 8 | skip_credentials_validation = true 9 | skip_get_ec2_platforms = true 10 | skip_metadata_api_check = true 11 | } 12 | } 13 | 14 | provider "digitalocean" { 15 | # export DIGITALOCEAN_TOKEN="API TOKEN" 16 | } 17 | 18 | resource "digitalocean_droplet" "example_server" { 19 | image = "${var.ubuntu}" 20 | region = "${var.do_nyc1}" 21 | ssh_keys = ["${var.ssh_fingerprint}"] 22 | size = "512mb" 23 | name = "my-first-terraform-droplet" 24 | } 25 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | output "ip" { 2 | value = "${digitalocean_droplet.example_server.ipv4_address}" 3 | } 4 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "do_nyc1" { 2 | description = "Digital Ocean New York Data Center 1" 3 | default = "nyc1" 4 | } 5 | 6 | variable "do_nyc2" { 7 | description = "Digital Ocean New York Data Center 2" 8 | default = "nyc2" 9 | } 10 | 11 | variable "do_nyc3" { 12 | description = "Digital Ocean New York Data Center 3" 13 | default = "nyc3" 14 | } 15 | 16 | variable "ubuntu" { 17 | description = "Default Ubuntu LTS" 18 | default = "ubuntu-18-04-x64" 19 | } 20 | 21 | # Personal Variables 22 | 23 | variable "ssh_fingerprint" { 24 | description = "Finger print of personal SSH" 25 | default = "5b:3a:b0:84:11:16:39:7c:01:c3:53:b7:1e:c3:22:3e" 26 | } 27 | --------------------------------------------------------------------------------