What is Terraform / OpenTofu?
You can skip this section if all of these words make perfect sense:
- HCL
- provider
- tfstate
Terraform is a declarative infrastructure-as-code tool.
OpenTofu is the open-source fork of Terraform.
Instead of writing imperative scripts that get executed to create or configure infrastructure
resources, like you would with Ansible, you describe the resources you want to exist
and their configuration, but not the steps to get there. Using the provider of a given service
or platform, the accumulated tfstate, the Terraform plan
and apply
commands, resources
are created, modified, or deleted to reflect the description.
You have a text file under version control that closely reflects the state of:
- hardware
- virtual machines
- VPC networks and policies
- GitHub account policies
- DNS records
- etc.
Terraform vs. OpenTofu
The Open Source fork of Terraform is OpenTofu.
OpenTofu was announced in Sept. 2023 after Terraform switched to a Business Source License (BSL).
Both are available in nixpkgs and are compatible with terranix, but Terraform requires allowing
unfree software using e.g. nixpkgs.config.allowUnfree = true;
so it's slightly
easier to create working examples with OpenTofu.
HCL vs. Terraform JSON
Terraform comes with two syntaxes, HCL and Terraform JSON.
HCL compiles to Terraform JSON.
The main role of terranix is to compile Nix to Terraform JSON.
Here is a complete resource definition for a Hetzner VPS one could store to myserver.tf
:
# Control the API token with a variable to hide it from version control
variable "hcloud_token" {}
# Configure the Hetzner Cloud Provider
provider "hcloud" {
token = "${var.hcloud_token}"
}
resource "hcloud_server" "myserver" {
image = "debian-12"
name = "myserver.example.org"
server_type = "cx22"
datacenter = "nbg1-dc3"
ssh_keys = [ hcloud_ssh_key.my_key.id ]
public_net {
ipv4_enabled = true
ipv6_enabled = true
}
}
resource "hcloud_ssh_key" "my_key" {
name = "my-ssh-key"
public_key = file("~/.ssh/id_ed25519.pub")
}
The same definition using Terraform JSON looks like the following.
One could store this to myserver.tf.json
:
{
"variable": {
"hcloud_token": {}
},
"provider": {
"hcloud": {
"token": "${var.hcloud_token}"
}
},
"resource": {
"hcloud_server": {
"myserver": {
"image": "debian-12",
"name": "myserver.example.org",
"server_type": "cx22",
"datacenter": "nbg1-dc3",
"ssh_keys": ["${hcloud_ssh_key.my_key.id}"],
"public_net": {
"ipv4_enabled": true,
"ipv6_enabled": true
}
}
},
"hcloud_ssh_key": {
"my_key": {
"name": "my-ssh-key",
"public_key": "${file(\"~/.ssh/id_ed25519.pub\")}"
}
}
}
}
What is myserver.tf / myserver.tf.json?
myserver.tf
or myserver.tf.json
is the file that contains the setup descriptions to be realized
behind one or multiple APIs. The majority of your work will be to create and maintain these files.
Besides a declarative description of your resource, Terraform also requires:
- the
terraform
(oropentofu
) CLI for runningplan
orapply
commands - the provider software to be installed for each relevant service or platform
- an API token for each relevant service or platform
- a tfstate
What are providers?
Providers are plugins that enables Terraform to interact with external services and platforms, like cloud or SaaS providers, through their APIs, translating Terraform's resource definitions into API calls.
A huge list of providers is available on Terraform.io.
Here is an example of how you would define multiple providers of the same kind
provider.aws = [
{ region = "us-east-1"; }
{ region = "eu-central-1"; alias = "eu"; }
];
What is Terraform state?
Terraform state, or tfstate, keeps track of the resources that Terraform has created and is currently managing.
Terraform is not capable of seeing the state behind APIs, because APIs never share all information. This is why Terraform creates a state file on every run to provide information for the next run.
This means a part of managing resources with Terraform is to store the tfstate and keep it in sync.