LXD and Terraform integration

I want to create lxd containers using terraform
lxd and terraform are on different server
so I need to configure terraform to access the lxd server, so how to do so?
I ran the lxd init
and set Would you like LXD to be available over the network? yes
I ran the lxd server on linode instance
terraform on my local machine

Hi @zikou1997

This can be achieved by importing the client’s certificate into the LXD.
You can import the existing certificate (if exists; should be in ~/snap/lxd/common/config/client.crt) or create a new one.

Example

My local remote server setup for demo (let’s call it linode-vm):

$ lxc launch ubuntu:22.04 linode-vm --vm
$ lxc ls linode-vm -c n4
+-------------+------------------------+
|    NAME     |          IPV4          |
+-------------+------------------------+
| linode-vm   | 10.16.253.220 (enp5s0) |
+-------------+------------------------+

$ lxc exec linode-vm -- lxc config set core.https_address=:8443

If client certificate is not present locally (on ec2 in your case) in the ~/snap/lxd/common/config/client.crt you can generate your own:

openssl req \
  -new \
  -newkey ec:<(openssl ecparam -name secp384r1) \
  -x509 \
  -nodes \
  -days 365 \
  -out ~/snap/lxd/common/config/client.crt \
  -keyout ~/snap/lxd/common/config/client.key \
  -subj "/CN=my-ec2.com"

Afterwards import the certificate to the remote LXD server:

# Remote server (linode-vm):

$ lxc config trust add <cert_path>
$ lxc config trust ls
+--------+------------+-------------+--------------+-------------------------------+-------------------------------+
|  TYPE  |    NAME    | COMMON NAME | FINGERPRINT  |          ISSUE DATE           |          EXPIRY DATE          |
+--------+------------+-------------+--------------+-------------------------------+-------------------------------+
| client | client.crt | my-ec2.com  | f46cd3efd938 | Jan 18, 2024 at 12:26pm (UTC) | Jan 17, 2025 at 12:26pm (UTC) |
+--------+------------+-------------+--------------+-------------------------------+-------------------------------+

Now you should be able to run the Terraform apply:

provider "lxd" {
  accept_remote_certificate = true

  lxd_remote {
    name    = "linode"
    scheme  = "https"
    address = "10.16.253.220" # Remote LXD server IP
    port    = "8443"          # Remote LXD server port 
    default = true
  }
}

resource "lxd_instance" "inst" {
  name  = "c1"
  image = "ubuntu:22.04"
  
  # In case the above remote is not configured as default: 
  # remote = "linode"
}

To verify:

lxc exec linode-vm -- lxc ls -c nb
+------+--------------+
| NAME | STORAGE POOL |
+------+--------------+
| c1   | default      |
+------+--------------+

here is my setup
I created a linode instance (with a public ip address) on this instance I install lxd server, I enabled it to be accessible from the network
then on other server (ec2 instance) I installed terraform where I want it to provision resources on the linode instance
so I’m bit confuse how to allow terraform to authenticate to the lxd server in order to provision resources
so how to do that?

If your remote LXD server (on Linode) is already exposed, you only have to exchange the client certificate between Terraform (on EC2) and the remote LXD server (on Linode). Otherwise, remote LXD server will not trust the incoming requests from EC2.

Are you running LXD on both EC2 and Linode?

If so, the easiest way is to generate a new certificate on the remote LXD server (Linode):

# Run on Linode
# Generate client cert for EC2. This will return you a fingerprint.
lxc config trust add --name ec2

Then add new remote LXD server (on EC2):

# Run on EC2
lxc remote add linode <fingerprint>

Finally, test if you can create an instance on Linode (from EC2):

# Run on EC2
lxc launch ubuntu:22.04 linode:test

If the above works, then you can try the same with Terraform:

provider "lxd" {}

resource "lxd_instance" "inst" {
  name   = "test2"
  image  = "ubuntu:22.04"
  remote = "linode" # This remote will be imported from local LXD config.
}

If you don’t have LXD on EC2 instance, then you can generate the client certificate manually (on Linode) and import it into the remote LXD server (on EC2), as explained above.

so I need to install also lxd on the ec2 instance?
I’ll try your suggestion and see if it works

when I run the command
lxc remote add linode <fingerprint>
I paste the fingerprint generated by the lxd remote
but I got this message

All server addresses are unavailable
Please provide an alternate server address (empty to abort):

I opened port 8443 on the ec2 to allow inboud traffic

If I understand correctly, you are trying to add remote LXD server (on Linode) to LXD server (on EC2)? In such case you need to expose LXD server running on Linode not EC2.

The above error indicates that the target LXD server address is unreachable (most likely due to firewall). Can you ensure the target instance (the one where the fingerprint was generated) allows inbound traffic on port 8443?

I fix the issue
I was able to provision lxd resource using terraform on my local machine and also on ec2 instance

lxc remote add linode <fingerprint>

to

lxc remote add linode <lxd-remote-server-ip>
1 Like