Using an LXD Storage Bucket as a Terraform S3 backend
Table of Contents
Update 2023-12-16: Added skip_requesting_account_id = true
to the backend configuration.
With the latest version 5.12 of LXD it is now possible to use the Storage Bucket feature of LXD as Terraform S3 backend.
Prerequisites #
- You are familiar with Terraform and LXD
- I would recommend looking at Stéphane Graber’s introduction LXD’s S3 API.
- For this to work, you must have a valid SSL certificate for LXD’s Storage Bucket API, otherwise Terraform will report an error:
x509: "root@servername certificate is not standards compliant"
I would recommend using a reverse proxy like Traefik that can provide an SSL certificate like Let’s Encrypt.
Setup the Storage Bucket #
- Create a new storage bucket:
lxc storage bucket create default terraform
- Get the access and secret key:
lxc storage bucket key show default terraform admin
description: Admin user
role: admin
access-key: A234234....
secret-key: N234Masdf....
name: admin
- Set environment variables that will be used later by Terraform:
$ export AWS_ACCESS_KEY_ID="A234234...."
$ export AWS_SECRET_ACCESS_KEY="N234Masdf...."
Setup Terraform to use the Storage Bucket as S3 backend #
- Create the
provider.tf
file and take a look at the provider documentation to understand how the LXD connection works:
terraform {
required_providers {
lxd = {
source = "terraform-lxd/lxd"
version = "1.9.0"
}
}
}
provider "lxd" {
accept_remote_certificate = true
generate_client_certificates = false
}
- Create the
backend.tf
file and set the correct endpoint:
terraform {
backend "s3" {
bucket = "terraform"
key = "state.json"
endpoint = "https://YOUR_LXD_S3_API_HOSTNAME"
region = "main"
skip_credentials_validation = true
skip_metadata_api_check = true
skip_region_validation = true
skip_requesting_account_id = true
force_path_style = true
}
}
- Create the
instance.tf
file to deploy an instance:
resource "lxd_container" "ubuntu" {
name = "ubuntu"
image = "ubuntu:22.04"
ephemeral = false
limits = {
"cpu" = 1
"memory" = "512MiB"
}
}
Run
terraform init
Run
terraform plan
and you should see the following output:
Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# lxd_container.ubuntu will be created
+ resource "lxd_container" "ubuntu" {
+ ephemeral = false
+ id = (known after apply)
+ image = "ubuntu:22.04"
+ ip_address = (known after apply)
+ ipv4_address = (known after apply)
+ ipv6_address = (known after apply)
+ limits = {
+ "cpu" = "1"
+ "memory" = "512MiB"
}
+ mac_address = (known after apply)
+ name = "ubuntu"
+ privileged = false
+ profiles = (known after apply)
+ start_container = true
+ status = (known after apply)
+ target = (known after apply)
+ type = (known after apply)
+ wait_for_network = true
}
Plan: 1 to add, 0 to change, 0 to destroy.
───────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't
guarantee to take exactly these actions if you run "terraform apply" now.