Home Deploy Servers with Terraform
Post
Cancel

Deploy Servers with Terraform


Introduction

The concept of infrastructure as Code has revolutionised the way servers are provisioned. Once reserved for entreprise-grade setups, nowadays IaC is easily configurable in a home setup with popular open-source tools such as Terraform, enabling an automated and easily maintainable environment. In this post I will be going through installation of Terraform and provisioning a new server on Proxmox Server using Terraform configuration files.

Terraform takes the code that describes the desired state of infrastructure and based on that, automatically configures an infrastructure, service or even cloud resource.

image-20230918232109392

[Good to know vocabulary]
Resource: Infrastructure object being managed by Terraform
Provider: Terraform Plugin responsible for understanding API interactions for each type of external resource
Resource Block: Code block used to define and configure the infrastructure resources

[Links]
Terraform Homepage: https://www.terraform.io/


1. Terraform Installation

1.1 Install Terraform on MacOS

1
2
brew tap hashicorp/tap
brew install hashicorp/tap/terraform

1.2 Prep Proxmox Server

To accept remote connection, we need to generate an API Token.
Open Proxmox server -> Select Datacenter -> Permissions -> API Tokens -> Add Token ID -> Unselect Privilege Separation. Copy the Token ID and secret to configure later in Terraform.

Unselecting Privilege Separation grants the API Token Full access to the system

image-20230918235014980

image-20230918234853955


2. Terraform Configuration

2.1 Provider configuration file

Create a “provider.tf” file in project folder. Configuration needs an API Token ID, Token secret and API URL. For security reason these are not added to the configuration file as plain text and instead using from environment variable.

For each variable value referenced there should be an environment variable with “TF_VAR_” added in front.
For example, var.exampleurl -> TF_VAR_exampleurl

API URL format - “https://your-proxmox-host:8006/api2/json”
API Token ID format - “user@pam!terraform2”

Token ID contains a ! characher. In Zsh, the ! character has a special meaning and is used for history expansion. To avoid getting error, use Single Qoutes ( ‘ ) to enclose the entry value. Or if using double quotes to enclose the value, escape the charater using a backslash \

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
# Proxmox Provider

terraform {
    required_version = ">= 0.13.0"
    required_providers {
        proxmox = {
            source = "telmate/proxmox"
        }
    }
}

variable "proxmox_api_url" {
    type = string
}
variable "proxmox_api_token_id" {
    type = string
}
variable "proxmox_api_token_secret" {
    type = string
}

provider "proxmox" {
    pm_api_url = var.proxmox_api_url
    pm_api_token_id = var.proxmox_api_token_id
    pm_api_token_secret = var.proxmox_api_token_secret

    # Skip TLS Verification
    pm_tls_insecure = true
}

2.2 Terraform Configuration Files

Create configuration file create_vm.tf. In this file, I will add configuration to state infrastructure that I want to have on Proxmox server. First example is to configure a VM and second one is to configure a Container, can use either or both.

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
# Create VM in Proxmox with Terraform

resource "proxmox_vm_qemu" "docker-server" {
    name = "docker-server"
    target_node = "proxmox"
    iso = "local:iso/ubuntu-23.04-live-server-amd64.iso"
    agent = 1

    # VM CPU Settings
    cores = 2
    sockets = 1
    cpu = "host"
    memory = 2048

    # VM Network Settings
    network {
        bridge = "vmbr0"
        model  = "virtio"
    }

    disk {
        size      = "32G"
        type      = "scsi"
        storage   = "local-lvm"
    }
    agent = 1   # run qemu agent on guest

//    onboot = true   # start server on boot
//		clone = "template-server"   # clone from existing VM
//    os_type = "cloud-init"
//    ipconfig0 = "ip=192.168.86.150/24,gw=192.168.86.1"
//    nameserver = "1.1.1.1"
//
//    sshkeys = <<EOF
//    ssh-rsa AAAAB.....omitted
//    EOF
    
}
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
# Create Container in Proxmox with Terraform

variable "vm_password" {
    type = string
}
resource "proxmox_lxc" "Container1" {
    vmid = 155
    hostname = "Container1"
    target_node = "proxmox"
    ostemplate   = "local:vztmpl/debian-12-standard_12.0-1_amd64.tar.zst"
    unprivileged = true
    password = var.vm_password

    rootfs {
      storage = "local-lvm"
      size    = "32G"
    }
    onboot = true   # boot on start
    start = true    # start after creation
    cores = 2
    memory = 2048
    swap = 2048

    network {
      name   = "eth0"
      bridge = "vmbr0"
      ip     = "192.168.86.155/24"
      gw     = "192.168.86.1"
    }

    ssh_public_keys = <<-EOT
      ssh-rsa AAAAB...omitted
    EOT

    features {
      nesting = true   # ability to run virtualization software. eg Docker
  }
}

3. Provision Infrastructure

Initialize configuration

1
terraform init

Preview the changes that Terraform will make

1
terraform plan

Apply provisioning

1
terraform apply -auto-approve

Provisioning is completed with 2 clicks and Container is created in 8 seconds !!

image-20230919011048840

image-20230919011738720

This post is licensed under CC BY 4.0 by the author.

Repurpose old Macbook to Proxmox Server

Juniper vSRX on Proxmox VE

Comments powered by Disqus.