One place for hosting & domains

      Terraform

      A Beginner's Guide to Terraform


      Updated by Linode Written by Linode

      Terraform by HashiCorp is an orchestration tool that allows you to represent your Linode instances and other resources with declarative code inside configuration files, instead of manually creating those resources via the Linode Manager or API. This practice is referred to as Infrastructure as Code, and Terraform is a popular example of this methodology. The basic workflow when using Terraform is:

      1. Write configuration files on your computer in which you declare the elements of your infrastructure that you want to create.

      2. Tell Terraform to analyze your configurations and then create the corresponding infrastructure.

      Terraform’s primary job is to create, modify, and destroy servers and other resources. Terraform generally does not configure your servers’ software. Configuring your software can be performed with scripts that you upload to and execute on your new servers, or via configuration management tools or container deployments.

      The Linode Provider

      Terraform is a general orchestration tool that can interface with a number of different cloud platforms. These integrations are referred to as providers. The Terraform provider for Linode was officially released in October 2018.

      Note

      The Linode provider can be used to create Linode instances, Images, domain records, Block Storage Volumes, StackScripts, and other resources. Terraform’s official Linode provider documentation details each resource that can be managed.

      Infrastructure as Code

      Terraform’s representation of your resources in configuration files is referred to as Infrastructure as Code (IAC). The benefits of this methodology and of using Terraform include:

      • Version control of your infrastructure. Because your resources are declared in code, you can track changes to that code over time in version control systems like Git.

      • Minimization of human error. Terraform’s analysis of your configuration files will produce the same results every time it creates your declared resources. As well, telling Terraform to repeatedly apply the same configuration will not result in extra resource creation, as Terraform tracks the changes it makes over time.

      • Better collaboration among team members. Terraform’s backends allow multiple team members to safely work on the same Terraform configuration simultaneously.

      HashiCorp Configuration Language

      Terraform’s configuration files can be written in either the HashiCorp Configuration Language (HCL), or in JSON. HCL is a configuration language authored by HashiCorp for use with its products, and it is designed to be human readable and machine friendly. It is recommended that you use HCL over JSON for your Terraform deployments.

      The next sections will illustrate core Terraform concepts with examples written in HCL. For a more complete review of HCL syntax, see Introduction to HashiCorp Configuration Language (HCL).

      Resources

      Here’s a simple example of a complete Terraform configuration in HCL:

      example.tf
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      
      provider "linode" {
          token = "your-linode-api-token"
      }
      
      resource "linode_instance" "example_instance" {
          label = "example_instance_label"
          image = "linode/ubuntu18.04"
          region = "us-central"
          type = "g6-standard-1"
          authorized_keys = ["ssh-rsa AAAA...Gw== user@example.local"]
          root_pass = "your-root-password"
      }

      Note

      The SSH key in this example was truncated for brevity.

      This example Terraform file, with the Terraform file extension .tf, represents the creation of a single Linode instance labeled example_instance_label. This example file is prefixed with a mandatory provider block, which sets up the Linode provider and which you must list somewhere in your configuration.

      The provider block is followed by a resource declaration. Resource declarations correspond with the components of your Linode infrastructure: Linode instances, Block Storage Volumes, etc.

      Resources can accept arguments. region and type are required arguments for the linode_instance resource. A root password must be assigned to every Linode, but the root_pass Terraform argument is optional; if it is not specified, a random password will be generated.

      Note

      The example_instance string that follows the linode_instance resource type declaration is Terraform’s name for the resource. You cannot declare more than one Terraform resource with the same name and resource type.

      The label argument specifies the label for the Linode instance in the Linode Manager. This name is independent of Terraform’s name for the resource (though you can assign the same value to both). The Terraform name is only recorded in Terraform’s state and is not communicated to the Linode API. Labels for Linode instances in the same Linode account must be unique.

      Dependencies

      Terraform resources can depend on each other. When one resource depends on another, it will be created after the resource it depends on, even if it is listed before the other resource in your configuration file.

      The following snippet expands on the previous example. It declares a new domain with an A record that targets the Linode instance’s IP address:

      example.tf
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      
      provider "linode" {
          # ...
      }
      
      resource "linode_instance" "example_instance" {
          # ...
      }
      
      resource "linode_domain" "example_domain" {
          domain = "example.com"
          soa_email = "example@example.com"
      }
      
      resource "linode_domain_record" "example_domain_record" {
          domain_id = "${linode_domain.example_domain.id}"
          name = "www"
          record_type = "A"
          target = "${linode_instance.example_instance.ip_address}"
      }

      The domain record’s domain_id and target arguments use HCL’s interpolation syntax to retrieve the ID of the domain resource and the IP of the Linode instance, respectively. Terraform creates an implicit dependency on the example_instance and example_domain resources for the example_domain_record resource. As a result, the domain record will not be created until after the Linode instance and the domain are created.

      Note

      Input Variables

      The previous example hard-coded sensitive data in your configuration, including your API token and root password. To avoid this practice, Terraform allows you to provide the values for your resource arguments in input variables. These variables are declared and referenced in your Terraform configuration (using interpolation syntax), and the values for those variables are assigned in a separate file.

      Input variables can also be used for non-sensitive data. The following example files will employ variables for the sensitive token and root_pass arguments and the non-sensitive authorized_keys and region arguments:

      example.tf
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      
      provider "linode" {
          token = "${var.token}"
      }
      
      resource "linode_instance" "example_instance" {
          label = "example_instance_label"
          image = "linode/ubuntu18.04"
          region = "${var.region}"
          type = "g6-standard-1"
          authorized_keys = ["${var.ssh_key}"]
          root_pass = "${var.root_pass}"
      }
      
      variable "token" {}
      variable "root_pass" {}
      variable "ssh_key" {}
      variable "region" {
        default = "us-southeast"
      }
      terraform.tfvars
      1
      2
      3
      
      token = "your-linode-api-token"
      root_pass = "your-root-password"
      ssh_key = "ssh-rsa AAAA...Gw== user@example.local"

      Note

      Place all of your Terraform project’s files in the same directory. Terraform will automatically load input variable values from any file named terraform.tfvars or ending in .auto.tfvars.

      The region variable is not assigned a specific value, so it will use the default value provided in the variable’s declaration. See Introduction to HashiCorp Configuration Language for more detailed information about input variables.

      Terraform CLI

      You interact with Terraform via its command line interface. After you have created the configuration files in your Terraform project, you need to run the init command from the project’s directory:

      terraform init
      

      This command will download the Linode provider plugin and take other actions needed to initialize your project. It is safe to run this command more than once, but you generally will only need to run it again if you are adding another provider to your project.

      Plan and Apply

      After you have declared your resources in your configuration files, you create them by running Terraform’s apply command from your project’s directory. However, you should always verify that Terraform will create the resources as you expect them to be created before making any actual changes to your infrastructure. To do this, you can first run the plan command:

      terraform plan
      

      This command will generate a report detailing what actions Terraform will take to set up your Linode resources.

      If you are satisfied with this report, run apply:

      terraform apply
      

      This command will ask you to confirm that you want to proceed. When Terraform has finished applying your configuration, it will show a report of what actions were taken.

      State

      When Terraform analyzes and applies your configuration, it creates an internal representation of the infrastructure it created and uses it to track the changes made. This state information is recorded in JSON in a local file named terraform.tfstate by default, but it can also be stored in other backends.

      Caution

      Your sensitive infrastructure data (like passwords and tokens) is visible in plain-text in your terraform.tfstate file. Review Secrets Management with Terraform for guidance on how to secure these secrets.

      Other Commands

      Other useful commands are available, like terraform show, which reports a human-readable version of your Terraform state. A full list of Terraform commands is available in the official Terraform documentation.

      Provisioners

      In addition to resource declarations, Terraform configurations can include provisioners. You declare provisioners to run scripts and commands in your local development environment or on your Terraform-managed servers. These actions are performed when you apply your Terraform configuration.

      The following example uploads a setup script to a newly created Linode instance and then executes it. This pattern can be used to bootstrap the new instance or enroll it in configuration management:

      example.tf
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      
      resource "linode_instance" "example_instance" {
        # ...
      
        provisioner "file" {
            source      = "setup_script.sh"
            destination = "/tmp/setup_script.sh"
        }
      
        provisioner "remote-exec" {
          inline = [
            "chmod +x /tmp/setup_script.sh",
            "/tmp/setup_script.sh",
          ]
        }
      }

      Most provisioners are declared inside of a resource declaration. When multiple provisioners are declared inside a resource, they are executed in the order they are listed. For a full list of provisioners, review the official Terraform documentation.

      Note

      Linode StackScripts can also be used to set up a new Linode instance. A distinction between using StackScripts and the file and remote-exec provisioners is that those provisioners will run and complete synchronously before Terraform continues to apply your plan, while a StackScript will run in parallel while Terraform creates the rest of your remaining resources. As a result, Terraform might complete its application before a StackScript has finished running.

      Modules

      Terraform allows you to organize your configurations into reusable structures called modules. This is useful if you need to create multiple instances of the same cluster of servers. Review Create a Terraform Module for more information on authoring and using modules.

      Backends

      By default, Terraform maintains its state in your project’s directory. Terraform also supports storing your state in non-local backends. The benefits of including your state in another backend include:

      • Better collaboration with your team. Backends let you share the same state as other team members that have access to the backend.

      • Better security. The state information stored in and retrieved from backends is only kept in memory on your computer.

      • Remote operations. When working with a large infrastructure, terraform apply can take a long time to complete. Some backends allow you to run the apply remotely, instead of on your computer.

      The kinds of backends available are listed in Terraform’s official documentation.

      Importing

      It is possible to import Linode infrastructure that was created outside of Terraform into your Terraform plan. Review Import Existing Infrastructure to Terraform for instructions on this subject.

      Next Steps

      To get started with installing Terraform and creating your first projects, read through our Use Terraform to Provision Linode Environments guide.

      More Information

      You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

      Find answers, ask questions, and help others.

      This guide is published under a CC BY-ND 4.0 license.



      Source link

      Secrets Management with Terraform


      Updated by Linode Contributed by Linode

      Terraform is an Infrastructure as Code (IaC) tool that allows you to write declarative code to manage your infrastructure. In order to implement IaC with Terraform it is necessary to supply secrets, such as server passwords and API tokens, within your code. This guide will discuss methods for securing those secrets within Terraform.

      Keeping Secrets Out of .tf Files

      In Terraform, .tf files contain the declarative code used to create, manage, and destroy infrastructure. This code is often committed to a version control system like Git, using a platform like GitHub, and shared within a team. Because it is easy for this information to become public-facing, it is important that you make sure your committed code is free of secrets.

      Input Variables

      Terraform configurations in .tf files can accept values from input variables. These variables are included in your configuration using Terraform’s interpolation syntax.

      For example, you might have a linode-infrastructure.tf file with a provider block that requires an API access token. The token variable definition is declared inside your .tf file and is then interpolated inside the provider declaration with the "${var.token}" syntax:

      linode-infrastructure.tf
      1
      2
      3
      4
      5
      6
      7
      
      variable "token" {
        description = "Your API access token"
      }
      
      provider "linode" {
          token = "${var.token}"
      }

      Variable definitions are written in .tf files. In this example, it’s the same file as your provider configuration, but the definition could have been in a separate .tf file too.

      Note

      Your variable definitions can have default values assigned to them. Here’s an example that encodes Linode’s Newark data center as the default value for a region variable:

      variables.tf
      1
      2
      3
      4
      
      variable "region" {
        description = "The region to deploy Linode instances in"
        default = "us-east"
      }

      You could later use this variable when declaring your Linode instances.

      Assigning Variable Values in a File

      The values assigned to your variables (aside from default values) are not included in the variable definitions in your .tf files. Instead, the values are stored in separate files with the .tfvars extension. When Terraform runs a command like plan or apply, it automatically looks through the working directory for a file named terraform.tfvars, or for files with the .auto.tfvars extension.

      Here’s an example terraform.tfvars which supplies a value for the token variable from the previous example:

      terraform.tfvars
      1
      
      token = 'your-token-value'

      You would then add the terraform.tfvars file to your .gitignore file and keep it out of version control. This strategy allows you to safely commit the linode-infrastructure.tf file.

      For ease of use with large terraform.tfvars files, it might be beneficial to include an example terraform.tfvars.example in your Git repository with all of the variable names recorded (but none of the values entered). Team members could then copy this example into their local repository’s terraform.tfvars and enter the appropriate values.

      Note

      Variable value files with names that don’t match terraform.tfvars or *.auto.tfvars can be specified with the -var-file option:

      terraform apply -var-file=myvars.tfvars
      

      Supplying multiple .tfvars files is another way to further separate secret variables and non-secret variables; e.g.:

      terraform apply 
      -var-file=non-secret-variables.tfvars 
      -var-file=secret-variables.tfvars
      

      Assigning Values in Environment Variables

      Terraform allows you to keep input variable values in environment variables. These variables have the prefix TF_VAR_ and are supplied at the command line. Using the above example of an API access token, you could export the variable and use it like so:

      export TF_VAR_token=your-token-value
      terraform apply
      

      You could also include the variable on the same line when running terraform plan or terraform apply:

      TF_VAR_token=your-token-value terraform apply
      

      Caution

      This method commits the environment variable to your shell’s history, so take care when using this method.

      Assigning Values in Command-Line Flags

      Variable values can be set with the -var option:

      terraform apply -var 'token=your-token-value'
      

      Caution

      This method commits the command-line variable to your shell’s history, so take care when using this method.

      Supply Variables at Prompt

      If Terraform does not find a default value for a defined variable; or a value from a .tfvars file, environment variable, or CLI flag; it will prompt you for a value before running an action:

        
      $ terraform plan
      var.token
        Your API access token
      
        Enter a value:
      
      

      This method is a bit easier to use than supplying environment variables, and has the added benefit of displaying the description you set up when defining your variable.

      How to Manage Your State File

      While it is relatively easy to keep secrets out of .tf files using any of the above methods, there is another file you need to be aware of when managing secrets, and that is the terraform.tfstate file.

      This state file contains a JSON object that holds your managed infrastructure’s current state. This state is a snapshot of the various attributes of your infrastructure at the time it was last modified. It is generated on terraform apply and is a necessary part of the Terraform process, as it maps the declarative code of your .tf files to your real world infrastructure.

      As of the writing of this guide, sensitive information used to generate your Terraform state can be stored as plain text in the terraform.tfstate file. For example, if you are working with the Linode provider and have supplied a root password for your Linode instance, that root password will be stored as plain text in the state file. Avoid checking your terraform.tfstate file into your version control repository. Instead, the following are some strategies for storing and sharing your state files.

      Remote Backends

      Terraform backends allow the user to securely store their state in a remote location, such as a key/value store like Consul, or an S3 compatible bucket storage like Minio. This allows the Terraform state to be read from the remote store, and because the state only ever exists locally in memory, there is no worry about storing secrets in plain text.

      Some backends, like Consul, also allow for state locking. If one user is applying a state, another user will be unable to make any changes.

      Using a Terraform backend is the preferred way to share a Terraform state file.

      Encrypting Secrets

      Third-party tools exist that allow you to encrypt your secrets. If you encrypt the secrets in your terraform.tfstate (or your .tfvars files), you can check them into version control securely:

      • git-crypt allows you to encrypt files when they are committed to a Git repository. git-crypt also decrypts files when they are checked out.

        Note

        You must initialize git-crypt in a repository before committing your state file or variable value files, or they will not be eligible for encryption.

      • Terrahelp allows you to encrypt and decrypt a whole state file, or just the variables you have include in your terraform.tfvars file.

      Use a Dummy Password

      It is possible to supply a dummy password to Terraform and later change that password manually to a more secure one. For instance, if you were to create a Linode instance with a dummy root password, you could later change that password from the command line or in the Linode Manager.

      Note

      Any attempt to change the password in a .tf file will result in the creation of new resources on terraform apply.

      Privatize Version Control

      If you are unwilling or unable to use the above options to help manage your state file, and if you are using a platform like GitHub or GitLab to share your state files, then at minimum the repository should be private.

      More Information

      You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

      Find answers, ask questions, and help others.

      This guide is published under a CC BY-ND 4.0 license.



      Source link

      Deploy a WordPress Site Using Terraform and Linode StackScripts


      Updated by Linode Contributed by Linode

      Linode’s Terraform provider supports StackScripts. StackScripts allow you to automate the deployment of custom software on top of Linode’s default Linux images, or on any of your saved custom images. You can create your own StackScripts, use a StackScript created by Linode, or use a Community StackScript.

      In this guide you will learn how to use a Community StackScript to deploy WordPress on a Linode using Terraform.

      Caution

      Following this guide will result in the creation of billable Linode resources on your account. To prevent continued billing for these resources, remove them from your account when you have completed the guide, if desired.

      Before You Begin

      1. Install Terraform on your computer by following the Install Terraform section of our Use Terraform to Provision Linode Environments guide.

      2. Terraform requires an API access token. Follow the Getting Started with the Linode API guide to obtain one.

      3. If you have not already, assign Linode’s name servers to your domain at your domain name’s registrar.

      4. Browse the existing StackScripts Library to familiarize yourself with common tasks you can complete with existing StackScripts.

      Create a Terraform Configuration

      Terraform defines the elements of your Linode infrastructure inside of configuration files. Terraform refers to these infrastructure elements as resources. Once you declare your Terraform configuration, you then apply it, which results in the creation of those resources on the Linode platform.

      Create the Terraform Configuration File

      1. Ensure that you are in the terraform directory.

        cd ~/terraform
        
      2. Using your preferred text editor, create a Terraform configuration file named main.tf to hold your resource definitions:

        ~/terraform/main.tf
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        
        provider "linode" {
            token = "${var.token}"
        }
        
        resource "linode_sshkey" "my_wordpress_linode_ssh_key" {
            label = "my_ssh_key"
            ssh_key = "${chomp(file("~/.ssh/id_rsa.pub"))}"
        }
        
        resource "random_string" "my_wordpress_linode_root_password" {
            length  = 32
            special = true
        }
        
        resource "linode_instance" "my_wordpress_linode" {
            image = "${var.image}"
            label = "${var.label}"
            region = "${var.region}"
            type = "${var.type}"
            authorized_keys = [ "${linode_sshkey.my_wordpress_linode_ssh_key.ssh_key}" ]
            root_pass = "${random_string.my_wordpress_linode_root_password.result}"
            stackscript_id = "${var.stackscript_id}"
            stackscript_data = "${var.stackscript_data}"
        }
        
        resource "linode_domain" "my_wordpress_domain" {
            domain = "${var.domain}"
            soa_email = "${var.soa_email}"
            type = "master"
         }
        
        resource "linode_domain_record" "my_wordpress_domain_www_record" {
            domain_id = "${linode_domain.my_wordpress_domain.id}"
            name = "www"
            record_type = "${var.a_record}"
            target = "${linode_instance.my_wordpress_linode.ipv4[0]}"
        }
        
        resource "linode_domain_record" "my_wordpress_domain_apex_record" {
            domain_id = "${linode_domain.my_wordpress_domain.id}"
            name = ""
            record_type = "${var.a_record}"
            target = "${linode_instance.my_wordpress_linode.ipv4[0]}"
        }

        The Terraform configuration file uses an interpolation syntax to reference Terraform input variables, call Terraform’s built-in functions, and reference attributes of other resources.

        Variables and their values will be created in separate files later on in this guide. Using separate files for variable declaration allows you to avoid hard-coding values into your resources. This strategy can help you reuse, share, and version control your Terraform configurations.

      Examining the Terraform Configuration

      Let’s take a closer look at each block in the configuration file:

      1. The first stanza declares Linode as the Terraform provider that will manage the life cycle of any resources declared throughout the configuration file. The Linode provider requires your Linode APIv4 token for authentication:

        1
        2
        3
        
        provider "linode" {
            token = "${var.token}"
        }
      2. The next resource configures an SSH Key that will be uploaded to your Linode instance later in the configuration file:

        1
        2
        3
        4
        
        resource "linode_sshkey" "my_wordpress_linode_ssh_key" {
            label = "my_ssh_key"
            ssh_key = "${chomp(file("~/.ssh/id_rsa.pub"))}"
        }

        ssh_key = "${chomp(file("~/.ssh/id_rsa.pub"))}" uses Terraform’s built-in file() function to provide a local file path to the public SSH key’s location. The chomp() built-in function removes trailing new lines from the SSH key.

        Note

        If you do not already have SSH keys, follow the steps in the Create an Authentication Key-pair section of the Securing Your Server Guide.
      3. The random_string resource can be used to create a random string of 32 characters. The linode_instance resource will use it to create a root user password:

        1
        2
        3
        4
        
        resource "random_string" "my_wordpress_linode_root_password" {
            length  = 32
            special = true
        }
      4. The linode_instance resource creates a Linode with the declared configurations:

         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        
        resource "linode_instance" "my_wordpress_linode" {
            image = "${var.image}"
            label = "${var.label}"
            region = "${var.region}"
            type = "${var.type}"
            authorized_keys = [ "${linode_sshkey.my_wordpress_linode_ssh_key.ssh_key}" ]
            root_pass = "${random_string.my_wordpress_linode_root_password.result}"
            stackscript_id = "${var.stackscript_id}"
            stackscript_data = "${var.stackscript_data}"
        }
        • The authorized_keys argument uses the SSH public key provided by the linode_sshkey resource in the previous stanza. This argument expects a value of type list, so the value must be wrapped in brackets.

        • The root_pass argument is assigned to the value of the random_string resource previously declared.

        • To use an existing StackScript you must use the stackscript_id argument and provide a valid ID as a value. Every StackScript is assigned a unique ID upon creation. This guide uses the WordPress on Ubuntu 16.04 StackScript provided by Linode user hmorris. This StackScript’s ID will be assigned to a Terraform variable later in this guide.

          StackScripts support user defined data. A StackScript can use the UDF tag to create a variable whose value must be provided by the user of the script. This allows users to customize the behavior of a StackScript on a per-deployment basis. Any required UDF variable can be defined using the stackscript_data argument.

          The StackScript will be responsible for installing WordPress on your Linode, along with all other requirements, like installing and configuring the Apache Web Server, configuring the Virtual Hosts file, and installing MySQL.

        • Other arguments are given values by the Terraform variables that will be declared later in this guide.

      5. In order to complete your WordPress site’s configuration, you need to create a domain and corresponding domain records for your site. The linode_domain and linode_domain_record resources handle these configurations:

         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        
        resource "linode_domain" "my_wordpress_domain" {
            domain = "${var.domain}"
            soa_email = "${var.soa_email}"
            type = "master"
         }
        
        resource "linode_domain_record" "my_wordpress_domain_www_record" {
            domain_id = "${linode_domain.my_wordpress_domain.id}"
            name = "www"
            record_type = "${var.a_record}"
            target = "${linode_instance.linode_id.ipv4[0]}"
        }
        
        resource "linode_domain_record" "my_wordpress_domain_apex_record" {
            domain_id = "${linode_domain.my_wordpress_domain.id}"
            name = ""
            record_type = "${var.a_record}"
            target = "${linode_instance.my_wordpress_linode.ipv4[0]}"
        }

        Note

        The linode_domain resource creates a domain zone for your domain.

        Each linode_domain_record resource retrieves the linode_domain resource’s ID and assigns it to that record’s domain_id argument. Each record’s target argument retrieves the IP address from the Linode instance. Every linode_instance resource exposes several attributes, including a Linode’s IPv4 address.

      Define the Input Variables

      In the terraform directory, create a file named variables.tf. This will define all the variables that were used in the main.tf file in the previous section. The values for these variables (aside from their default values) will be assigned in another file:

      ~/terraform/variables.tf
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      
      variable "token" {
        description = "Linode API Personal Access Token"
      }
      
      variable "image" {
        description = "Image to use for Linode instance"
        default = "linode/ubuntu16.04lts"
      }
      
      variable "label" {
        description = "The Linode's label is for display purposes only."
        default = "default-linode"
      }
      
      variable "region" {
        description = "The region where your Linode will be located."
        default = "us-east"
      }
      
      variable "type" {
        description = "Your Linode's plan type."
        default = "g6-standard-1"
      }
      
      variable "stackscript_id" {
        description = "Stackscript ID"
      }
      
      variable "stackscript_data" {
        description = "Map of required StackScript UDF data."
        type = "map"
      }
      
      variable "domain" {
        description = "The domain this domain represents."
      }
      
      variable "soa_email" {
        description = "Start of Authority email address. This is required for master domains."
      }
      
      variable "a_record" {
        description = "The type of DNS record. For example, `A` records associate a domain name with an IPv4 address."
        default = "A"
      }
          

      Note

      It is recommended to include a description attribute for each input variable to help document your configuration’s usage. This will make it easier for anyone else to use this Terraform configuration.

      Every variable can contain a default value. The default value is only used if no other value is provided. You can also declare a type for each variable. If no type is provided, the variable will default to type = "string".

      The stackscript_data variable is of type map. This will allow you to provide values for as many UDF variables as your StackScript requires.

      Assign Values to the Input Variables

      Terraform allows you to assign variables in many ways. For example, you can assign a variable value via the command line when running terraform apply. In order to persist variable values, you can also create files to hold all your values.

      Note

      Terraform will automatically load any file named terraform.tfvars and use its contents to populate variables. However, you should separate out any sensitive values, like passwords and tokens, into their own file. Keep this sensitive file out of version control.

      1. Create a file named terraform.tfvars in your terraform directory to hold all non-sensitive values:

        ~/terraform/terraform.tfvars
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        
        label = "wp-linode"
        stackscript_id = "81736"
        stackscript_data = {
          ssuser = "username"
          hostname = "wordpress"
          website = "example.com"
          dbuser = "wpuser"
        }
        domain = "example.com"
        soa_email = "user@email.com"
      2. Create a file name secrets.tfvars in your terraform directory to hold any sensitive values:

        ~/terraform/secrets.tfvars
        1
        2
        3
        4
        5
        6
        
        token = "my-linode-api4-token"
        stackscript_data = {
          sspassword = "my-secure-password"
          db_password = "another-secure-password"
          dbuser_password = "a-third-secure-password"
        }

        Note

      3. Replace the following values in your new .tfvars files:

        • token should be replaced with your own Linode account’s APIv4 token.

        • For security purposes, the StackScript will create a limited Linux user on your Linode. ssuser should be replaced with your desired username for this user.

        • sspassword, db_password, and dbuser_password should be replaced with secure passwords of your own.

        • domain should be replaced with your WordPress site’s domain address.

        • soa_email should be the email address you would like to use for your Start of Authority email address.

      Initialize, Plan, and Apply the Terraform Configuration

      Your Terraform configuration has been recorded, but you have not told Terraform to create the resources yet. To do this, you will invoke commands from Terraform’s CLI.

      Initialize

      Whenever a new provider is used in a Terraform configuration, it must be initialized before you can create resources with it. The initialization process downloads and installs the provider’s plugin and performs any other steps needed to prepare for its use.

      Navigate to your terraform directory in your terminal and run:

      terraform init
      

      You will see a message that confirms that the Linode provider plugins have been successfully initialized.

      Plan

      It can be useful to view your configuration’s execution plan before actually committing those changes to your infrastructure. Terraform includes a plan command for this purpose. Run this command from the terraform directory:

      terraform plan 
      -var-file="secrets.tfvars" 
      -var-file="terraform.tfvars"
      

      plan won’t take any actions or make any changes on your Linode account. Instead, an analysis is done to determine which actions (i.e. Linode resource creations, deletions, or modifications) are required to achieve the state described in your configuration.

      Apply

      You are now ready to create the infrastructure defined in your main.tf configuration file:

      1. Run Terraform’s apply command from the terraform directory:

        terraform apply 
        -var-file="secrets.tfvars" 
        -var-file="terraform.tfvars"
        

        Since you are using multiple variable value files, you must include each file individually using the var-file argument. You will be prompted to confirm the apply action. Type yes and press enter.

      2. Terraform will begin to create the resources you’ve defined throughout this guide. This process will take several minutes to complete. Once the infrastructure has been successfully built you will see a similar output:

          
        Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
        
        
      3. Navigate to your WordPress site’s domain and verify that the site loads. You may have to wait a few minutes more after the terraform apply command returns, as the StackScript takes time to install WordPress. Additionally, it make take some time for your domain name changes to propagate:

        Install WordPress

      4. Complete the remaining WordPress configuration steps provided by the prompts.

      (Optional) Destroy the Linode Resources

      If you do not want to keep using the resources created by Terraform in this guide, run the destroy command from the terraform directory:

      terraform destroy 
      -var-file="secrets.tfvars" 
      -var-file="terraform.tfvars"
      

      Terraform will prompt you to confirm this action. Enter yes to proceed.

      More Information

      You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

      Find answers, ask questions, and help others.

      This guide is published under a CC BY-ND 4.0 license.



      Source link