<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet type="text/xsl" href="/pretty-feed-v3.xsl"?>
<rss
  version="2.0"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:source="https://source.scripting.com/"
>
  <channel>
    <title>Paul Tibbetts</title>
    <link>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/tags/terraform/</link>
    <description>Recent posts by Paul Tibbetts on Terraform</description>
    <generator>Hugo</generator>
    <language>en-gb</language>
    <lastBuildDate>Wed, 04 Mar 2026 15:27:40 +0000</lastBuildDate>
    <atom:link href="https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/tags/terraform/feed.xml" rel="self" type="application/rss+xml" /><item>
      <title>I Made a Terraform Provider for Mythic Beasts</title>
      <link>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/03/03/i-made-a-terraform-provider-for-mythic-beasts/</link>
      <pubDate>Tue, 03 Mar 2026 12:00:17 +0000</pubDate>
      <guid>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/03/03/i-made-a-terraform-provider-for-mythic-beasts/</guid>
      <category>Terraform</category>
      <category>Mythic Beasts</category>
      <category>go</category>
      <category>code</category>
      <description>paultibbetts/terraform-provider-mythicbeasts is a Terraform provider that lets you declare infrastructure from the company Mythic Beasts as code.
I use it to provision the infrastructure for my personal website.
This is why I built it, what it does, and how to use it.</description>
      <content:encoded><![CDATA[<p><a href="https://github.com/paultibbetts/terraform-provider-mythicbeasts">paultibbetts/terraform-provider-mythicbeasts</a>
 is a Terraform provider that lets you declare infrastructure from the company <a href="https://www.mythic-beasts.com/">Mythic Beasts</a>
 as code.</p>
<p>I use it to provision the infrastructure for my personal website.</p>
<p>This is why I built it, what it does, and how to use it.</p>
<h2 id="why-i-built-it">Why I built it</h2>
<p>I prefer writing down my infrastructure as code. It&rsquo;s something I&rsquo;ve been doing for years now, and I don&rsquo;t think I could go back to doing things manually, no matter how small or simple the setup.</p>
<p>I&rsquo;d decided to use a Pi from Mythic Beasts to host my site and saw that they had APIs available, but no Terraform provider.</p>
<p>Terraform is a tool I&rsquo;ve been using for infrastructure for a while now, and I wanted to use it with Mythic Beasts because:</p>
<ul>
<li>I wanted a fully reproducible setup</li>
<li>I didn&rsquo;t want to click around the control panel</li>
<li>their Pis are IPv6-only, so I&rsquo;d need to also set up the proxy</li>
<li>
<ul>
<li>I wanted to declare the Pi and the endpoints for the proxy in the same place</li>
</ul>
</li>
</ul>
<p>Plus, I&rsquo;d never written a Terraform provider before, and I wanted to see what it was like.</p>
<h2 id="what-it-does">What it does</h2>
<p>Terraform is a tool for writing your infrastructure as code, and a provider is a plugin that lets it work with different infrastructure providers.</p>
<p>For example you can write:</p>
<pre><code class="language-hcl">terraform {
  required_version = &#34;&gt;= 1.11.0&#34;

  required_providers {
    mythicbeasts = {
      source = &#34;paultibbetts/mythicbeasts&#34;
    }
  }
}

resource &#34;mythicbeasts_pi&#34; &#34;pi&#34; {
	identifier   = &#34;web&#34;
	disk_size    = 10
	model        = 4
	memory       = 4096
	os_image     = &#34;rpi-bookworm-arm64&#34;
    ssh_key      = &#34;ssh-ed25519 ...&#34;
    wait_for_dns = true
}</code></pre>
<p>then run <code>terraform apply</code>, and you would get a Raspberry Pi 4 from Mythic Beasts.</p>
<h3 id="resources">Resources</h3>
<p>The provider uses the Mythic Beasts APIs to configure the following resources:</p>
<ul>
<li>VPS</li>
<li>Raspberry Pi</li>
<li>Proxy endpoint</li>
</ul>
<p>The Raspberry Pis from Mythic Beasts are on an IPv6-only network, so the Proxy endpoints are to allow users trying to access from an IPv4-only network.</p>
<h3 id="data-sources">Data sources</h3>
<p>Some of the settings for the resources require specific values, like the <code>os_image</code> to use, and data sources make it easy to get this info from the API.</p>
<p>For example, the <code>mythicbeasts_pi_operating_systems</code> data source can be used to get all valid <code>os_image</code> values for a Raspberry Pi 4:</p>
<pre><code class="language-hcl">data &#34;mythicbeasts_pi_operating_systems&#34; &#34;four&#34; {
  model = 4
}</code></pre>
<p>where you would inspect the data to choose the right value to use.</p>
<p>Alternatively you could use Terraform to find the right value for you, for example to use &ldquo;Bookworm&rdquo; for &ldquo;Arm64&rdquo;:</p>
<pre><code class="language-hcl">data &#34;mythicbeasts_pi_operating_systems&#34; &#34;four&#34; {
  model = 4
}

locals {
  bookworm_arm64 = one([
    for image in data.mythicbeasts_pi_operating_systems.four.images :
    image.id
    if strcontains(image.id, &#34;bookworm&#34;) &amp;&amp;
    strcontains(image.id, &#34;arm64&#34;)
  ])
}

resource &#34;mythicbeasts_pi&#34; &#34;bookworm&#34; {
  model    = 4
  os_image = local.bookworm_arm64
  ...
}</code></pre>
<p>where Terraform will find the image with both &ldquo;bookworm&rdquo; and &ldquo;arm64&rdquo; in the ID.</p>
<h3 id="attributes">Attributes</h3>
<p>Using Terraform for your infrastructure not only lets you write it down as code, with all the <a href="https://infra.paultibbetts.uk/decisions/why-iac/">benefits that brings</a>
, but you can use the attributes of one thing as inputs for another.</p>
<p>For example: the Pis from Mythic Beasts are on an IPv6-only network and need endpoints set up on the proxy to let users access them from IPv4-only networks.</p>
<p>To do this you can get the attribute from a Pi, like the IP address, and then use that as the input for the proxy endpoint resource:</p>
<pre><code class="language-hcl">locals {
  domain = &#34;example.com&#34;
  subdomains = {
    apex  = &#34;@&#34;
    www   = &#34;www&#34;
  }
}

resource &#34;mythicbeasts_pi&#34; &#34;web&#34; {
	identifier   = &#34;web&#34;
	disk_size    = 10
	model        = 4
	memory       = 4096
	os_image     = &#34;rpi-bookworm-arm64&#34;
    ssh_key      = &#34;ssh-ed25519 ...&#34;
    wait_for_dns = true
}

resource &#34;mythicbeasts_proxy_endpoint&#34; &#34;endpoint&#34; {
  for_each = local.subdomains

  domain         = local.domain
  hostname       = each.value
  address        = mythicbeasts_pi.web.ip
  site           = &#34;all&#34;
  proxy_protocol = true
}</code></pre>
<h2 id="how-to-use-it">How to use it</h2>
<p>The provider is available on <a href="https://registry.terraform.io/providers/paultibbetts/mythicbeasts/">the Terraform registry</a>
.</p>
<h3 id="authentication">Authentication</h3>
<p>The Mythic Beasts APIs require an <a href="https://www.mythic-beasts.com/customer/api-users">API key</a>
 for authentication.</p>
<p>When creating the key you must add permissions to work with the APIs you wish to use, such as:</p>
<ul>
<li>&ldquo;Virtual Server Provisioning&rdquo; for VPS</li>
<li>&ldquo;Raspberry Pi provisioning&rdquo; for Pis</li>
<li>&ldquo;IPv4 to IPv6 Proxy API&rdquo; for Proxy endpoints</li>
</ul>
<h3 id="proxy-endpoint-domain-management">Proxy endpoint domain management</h3>
<p>The domain used for proxy endpoints must be registered with the Mythic Beasts control panel.</p>
<p>This can be done by registering the domain using their <a href="https://www.mythic-beasts.com/customer/domains">domain management</a>
 or by <a href="https://www.mythic-beasts.com/customer/3rdpartydomain">adding it as a 3rd party domain</a>
.</p>
<h3 id="installation">Installation</h3>
<pre><code class="language-hcl">terraform {
  required_version = &#34;&gt;= 1.11.0&#34;

  required_providers {
    mythicbeasts = {
      source = &#34;paultibbetts/mythicbeasts&#34;
    }
  }
}

provider &#34;mythicbeasts&#34; {
  keyid  = &#34;your-keyid&#34;
  secret = &#34;your-secret&#34;
}</code></pre>
<p>Alternatively, credentials can be supplied via environment variables:</p>
<ul>
<li><code>MYTHICBEASTS_KEYID</code></li>
<li><code>MYTHICBEASTS_SECRET</code></li>
</ul>
<h2 id="examples">Examples</h2>
<p>Examples of each resource and data source can be found at <a href="https://github.com/paultibbetts/terraform-provider-mythicbeasts/blob/main/examples">/examples</a>
.</p>
<p>These are also used to generate the <a href="https://registry.terraform.io/providers/paultibbetts/mythicbeasts/latest/docs">documentation hosted by the Terraform registry</a>
.</p>
<h2 id="how-it-works">How it works</h2>
<p>The provider uses the newer <a href="https://github.com/hashicorp/terraform-plugin-framework">Terraform Plugin Framework</a>
.</p>
<p>For it to work with the Mythic Beasts APIs I had to create a Go client, which can be found <a href="https://github.com/paultibbetts/mythicbeasts-client-go/">on GitHub</a>
. The client handles the APIs and means that the provider only needs to focus on Terraform itself.</p>
<p>The Mythic Beasts VPS API needs values that are only ever used when creating a VPS and so the provider uses the new <a href="https://developer.hashicorp.com/terraform/language/manage-sensitive-data/write-only">write-only</a>
 arguments feature, which is only available in Terraform v1.11.0 and later. Write-only is normally used for sensitive values like passwords but the VPS API doesn&rsquo;t return every attribute so write-only is used for these values when creating the VPS and then they are forgotten.</p>
<h2 id="support">Support</h2>
<p>To make it clear, this is an unofficial provider that is not endorsed by Mythic Beasts.</p>
<p>It&rsquo;s currently at version <code>v0.1</code> and I wouldn&rsquo;t consider it stable until it hits <code>v1.0</code>.</p>
<p>Right now it supports the APIs I need it to. Further features will be added as needed.</p>
<h2 id="in-use">In use</h2>
<p>I use the provider to provision a Raspberry Pi 4 from Mythic Beasts and set up the proxy endpoints for my personal website.</p>
<p>The whole setup, with Terraform to provision the Pi and then Ansible to configure it, is documented at <a href="https://infra.paultibbetts.uk">infra.paultibbetts.uk</a>
.</p>
<h2 id="whats-next">What&rsquo;s next?</h2>
<p>The provider works with the VPS, Pi, and Proxy APIs, as these are what I currently use or have used in the past.</p>
<p>Mythic Beasts also have a <a href="https://www.mythic-beasts.com/support/api/dnsv2">DNS API</a>
 which lets you manage the DNS records for domains.</p>
<p>If I were to add this to the provider I could change the management of my domain from Cloudflare over to Mythic Beasts, which would improve my website&rsquo;s <a href="https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/19/moved-my-website-from-github-pages-to-a-raspberry-pi/">sovereignty</a>
.</p>]]></content:encoded><source:markdown>
[paultibbetts/terraform-provider-mythicbeasts](https://github.com/paultibbetts/terraform-provider-mythicbeasts) is a Terraform provider that lets you declare infrastructure from the company [Mythic Beasts](https://www.mythic-beasts.com/) as code.

I use it to provision the infrastructure for my personal website.

This is why I built it, what it does, and how to use it.

&lt;!--more--&gt;

## Why I built it

I prefer writing down my infrastructure as code. It&#39;s something I&#39;ve been doing for years now, and I don&#39;t think I could go back to doing things manually, no matter how small or simple the setup.

I&#39;d decided to use a Pi from Mythic Beasts to host my site and saw that they had APIs available, but no Terraform provider.

Terraform is a tool I&#39;ve been using for infrastructure for a while now, and I wanted to use it with Mythic Beasts because:

- I wanted a fully reproducible setup
- I didn&#39;t want to click around the control panel
- their Pis are IPv6-only, so I&#39;d need to also set up the proxy
- - I wanted to declare the Pi and the endpoints for the proxy in the same place

Plus, I&#39;d never written a Terraform provider before, and I wanted to see what it was like.

## What it does

Terraform is a tool for writing your infrastructure as code, and a provider is a plugin that lets it work with different infrastructure providers.

For example you can write:

```hcl
terraform {
  required_version = &#34;&gt;= 1.11.0&#34;

  required_providers {
    mythicbeasts = {
      source = &#34;paultibbetts/mythicbeasts&#34;
    }
  }
}

resource &#34;mythicbeasts_pi&#34; &#34;pi&#34; {
	identifier   = &#34;web&#34;
	disk_size    = 10
	model        = 4
	memory       = 4096
	os_image     = &#34;rpi-bookworm-arm64&#34;
    ssh_key      = &#34;ssh-ed25519 ...&#34;
    wait_for_dns = true
}
```

then run `terraform apply`, and you would get a Raspberry Pi 4 from Mythic Beasts.

### Resources

The provider uses the Mythic Beasts APIs to configure the following resources:

- VPS
- Raspberry Pi
- Proxy endpoint

The Raspberry Pis from Mythic Beasts are on an IPv6-only network, so the Proxy endpoints are to allow users trying to access from an IPv4-only network.

### Data sources

Some of the settings for the resources require specific values, like the `os_image` to use, and data sources make it easy to get this info from the API.

For example, the `mythicbeasts_pi_operating_systems` data source can be used to get all valid `os_image` values for a Raspberry Pi 4:

```hcl
data &#34;mythicbeasts_pi_operating_systems&#34; &#34;four&#34; {
  model = 4
}
```

where you would inspect the data to choose the right value to use.

Alternatively you could use Terraform to find the right value for you, for example to use &#34;Bookworm&#34; for &#34;Arm64&#34;:

```hcl
data &#34;mythicbeasts_pi_operating_systems&#34; &#34;four&#34; {
  model = 4
}

locals {
  bookworm_arm64 = one([
    for image in data.mythicbeasts_pi_operating_systems.four.images :
    image.id
    if strcontains(image.id, &#34;bookworm&#34;) &amp;&amp;
    strcontains(image.id, &#34;arm64&#34;)
  ])
}

resource &#34;mythicbeasts_pi&#34; &#34;bookworm&#34; {
  model    = 4
  os_image = local.bookworm_arm64
  ...
}
```

where Terraform will find the image with both &#34;bookworm&#34; and &#34;arm64&#34; in the ID.

### Attributes

Using Terraform for your infrastructure not only lets you write it down as code, with all the [benefits that brings](https://infra.paultibbetts.uk/decisions/why-iac/), but you can use the attributes of one thing as inputs for another.

For example: the Pis from Mythic Beasts are on an IPv6-only network and need endpoints set up on the proxy to let users access them from IPv4-only networks.

To do this you can get the attribute from a Pi, like the IP address, and then use that as the input for the proxy endpoint resource:

```hcl
locals {
  domain = &#34;example.com&#34;
  subdomains = {
    apex  = &#34;@&#34;
    www   = &#34;www&#34;
  }
}

resource &#34;mythicbeasts_pi&#34; &#34;web&#34; {
	identifier   = &#34;web&#34;
	disk_size    = 10
	model        = 4
	memory       = 4096
	os_image     = &#34;rpi-bookworm-arm64&#34;
    ssh_key      = &#34;ssh-ed25519 ...&#34;
    wait_for_dns = true
}

resource &#34;mythicbeasts_proxy_endpoint&#34; &#34;endpoint&#34; {
  for_each = local.subdomains

  domain         = local.domain
  hostname       = each.value
  address        = mythicbeasts_pi.web.ip
  site           = &#34;all&#34;
  proxy_protocol = true
}
```

## How to use it

The provider is available on [the Terraform registry](https://registry.terraform.io/providers/paultibbetts/mythicbeasts/).

### Authentication

The Mythic Beasts APIs require an [API key](https://www.mythic-beasts.com/customer/api-users) for authentication.

When creating the key you must add permissions to work with the APIs you wish to use, such as:

- &#34;Virtual Server Provisioning&#34; for VPS
- &#34;Raspberry Pi provisioning&#34; for Pis
- &#34;IPv4 to IPv6 Proxy API&#34; for Proxy endpoints

### Proxy endpoint domain management

The domain used for proxy endpoints must be registered with the Mythic Beasts control panel.

This can be done by registering the domain using their [domain management](https://www.mythic-beasts.com/customer/domains) or by [adding it as a 3rd party domain](https://www.mythic-beasts.com/customer/3rdpartydomain).

### Installation

```hcl
terraform {
  required_version = &#34;&gt;= 1.11.0&#34;

  required_providers {
    mythicbeasts = {
      source = &#34;paultibbetts/mythicbeasts&#34;
    }
  }
}

provider &#34;mythicbeasts&#34; {
  keyid  = &#34;your-keyid&#34;
  secret = &#34;your-secret&#34;
}
```

Alternatively, credentials can be supplied via environment variables:

- `MYTHICBEASTS_KEYID`
- `MYTHICBEASTS_SECRET`

## Examples

Examples of each resource and data source can be found at [/examples](https://github.com/paultibbetts/terraform-provider-mythicbeasts/blob/main/examples).

These are also used to generate the [documentation hosted by the Terraform registry](https://registry.terraform.io/providers/paultibbetts/mythicbeasts/latest/docs).

## How it works

The provider uses the newer [Terraform Plugin Framework](https://github.com/hashicorp/terraform-plugin-framework).

For it to work with the Mythic Beasts APIs I had to create a Go client, which can be found [on GitHub](https://github.com/paultibbetts/mythicbeasts-client-go/). The client handles the APIs and means that the provider only needs to focus on Terraform itself.

The Mythic Beasts VPS API needs values that are only ever used when creating a VPS and so the provider uses the new [write-only](https://developer.hashicorp.com/terraform/language/manage-sensitive-data/write-only) arguments feature, which is only available in Terraform v1.11.0 and later. Write-only is normally used for sensitive values like passwords but the VPS API doesn&#39;t return every attribute so write-only is used for these values when creating the VPS and then they are forgotten.

## Support

To make it clear, this is an unofficial provider that is not endorsed by Mythic Beasts.

It&#39;s currently at version `v0.1` and I wouldn&#39;t consider it stable until it hits `v1.0`.

Right now it supports the APIs I need it to. Further features will be added as needed.

## In use

I use the provider to provision a Raspberry Pi 4 from Mythic Beasts and set up the proxy endpoints for my personal website.

The whole setup, with Terraform to provision the Pi and then Ansible to configure it, is documented at [infra.paultibbetts.uk](https://infra.paultibbetts.uk).

## What&#39;s next?

The provider works with the VPS, Pi, and Proxy APIs, as these are what I currently use or have used in the past.

Mythic Beasts also have a [DNS API](https://www.mythic-beasts.com/support/api/dnsv2) which lets you manage the DNS records for domains.

If I were to add this to the provider I could change the management of my domain from Cloudflare over to Mythic Beasts, which would improve my website&#39;s [sovereignty](/2026/02/19/moved-my-website-from-github-pages-to-a-raspberry-pi/).
</source:markdown></item><item>
      <title>Launched: infra.paultibbetts.uk A documentation site for the infrastructure that …</title>
      <link>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/15/2026-02-15-145458/</link>
      <pubDate>Sun, 15 Feb 2026 14:54:58 +0000</pubDate>
      <guid>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/15/2026-02-15-145458/</guid>
      <category>Ansible</category>
      <category>Terraform</category>
      <category>meta</category>
      <description>Launched: infra.paultibbetts.uk A documentation site for the infrastructure that runs paultibbetts.uk.</description>
      <content:encoded><![CDATA[<p>Launched: <a href="https://infra.paultibbetts.uk/">infra.paultibbetts.uk</a>
</p>
<p>A documentation site for the infrastructure that runs <code>paultibbetts.uk</code>.</p>]]></content:encoded><source:markdown>
Launched: [infra.paultibbetts.uk](https://infra.paultibbetts.uk/)

A documentation site for the infrastructure that runs `paultibbetts.uk`.
</source:markdown></item><item>
      <title>Published: paultibbetts/terraform-provider-mythicbeasts A Terraform provider for …</title>
      <link>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/09/2026-02-09-151500/</link>
      <pubDate>Mon, 09 Feb 2026 15:15:00 +0000</pubDate>
      <guid>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/09/2026-02-09-151500/</guid>
      <category>Terraform</category>
      <category>go</category>
      <category>code</category>
      <category>Mythic Beasts</category>
      <description>Published: paultibbetts/terraform-provider-mythicbeasts A Terraform provider for Mythic Beasts.</description>
      <content:encoded><![CDATA[<p>Published: <a href="https://github.com/paultibbetts/terraform-provider-mythicbeasts">paultibbetts/terraform-provider-mythicbeasts</a>
</p>
<p>A Terraform provider for Mythic Beasts.</p>]]></content:encoded><source:markdown>
Published: [paultibbetts/terraform-provider-mythicbeasts](https://github.com/paultibbetts/terraform-provider-mythicbeasts)

A Terraform provider for Mythic Beasts.
</source:markdown></item><item>
      <title>Using Terraform as the Inventory for Ansible</title>
      <link>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2025/06/13/using-terraform-as-the-inventory-for-ansible/</link>
      <pubDate>Fri, 13 Jun 2025 11:30:21 +0100</pubDate>
      <guid>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2025/06/13/using-terraform-as-the-inventory-for-ansible/</guid>
      <category>Ansible</category>
      <category>Terraform</category>
      <description>Terraform and Ansible are complementary tools with which you can do Infrastructure as Code. You would use Terraform to request machines from providers and then Ansible to configure them.
Using both of them together, with a dynamic inventory to link them, has been technically possible for years but never obvious enough for me to work out.
Until I found the Terraform provider.</description>
      <content:encoded><![CDATA[<p>Terraform and Ansible are complementary tools with which you can do Infrastructure as Code. You would use <a href="https://www.terraform.io/">Terraform</a>
 to request machines from providers and then <a href="https://docs.ansible.com/ansible/latest/index.html">Ansible</a>
 to configure them.</p>
<p>Using both of them together, with a dynamic inventory to link them, has been technically possible for years but never obvious enough for me to work out.</p>
<p>Until I found the Terraform provider.</p>
<h2 id="ansible-provider-for-terraform">Ansible provider for Terraform</h2>
<p>By using the <a href="https://registry.terraform.io/providers/ansible/ansible/latest">Ansible provider</a>
 you can teach Terraform what an Ansible inventory entry would look like next to the rest of its code.</p>
<p>You start by defining the provider:</p>
<pre><code class="language-terraform">terraform {
  required_providers {
    ansible = {
      source  = &#34;ansible/ansible&#34;
      version = &#34;1.3.0&#34;
    }
  }
}</code></pre>
<p>and then you can define the Ansible inventory entry right next to the resource:</p>
<pre><code class="language-terraform">resource &#34;proxmox_vm_qemu&#34; &#34;gitea&#34; {
  cores = 1
	...
}

resource &#34;ansible_host&#34; &#34;gitea&#34; {
  name   = proxmox_vm_qemu.gitea.ssh_host
  groups = [&#34;gitea&#34;]
  variables = {
    ansible_user = &#34;ansible&#34;
  }
}</code></pre>
<p>which means you don&rsquo;t need to hardcode IP addresses anywhere.</p>
<p>You would need to <code>terraform apply</code> this plan so that Terraform adds these resources to the state file so that Ansible can use them.</p>
<h2 id="terraform-plugin-for-ansible">Terraform plugin for Ansible</h2>
<p>On the Ansible side you use <a href="https://github.com/ansible-collections/cloud.terraform">a plugin</a>
 to tell it how to use Terraform as its inventory.</p>
<p>Add the following to your <code>requirements.yaml</code> file:</p>
<pre><code class="language-yaml">collections:
  - name: cloud.terraform
    version: 1.1.0</code></pre>
<p>and then install the collection using <code>ansible-galaxy collection install -r requirements.yaml</code>,</p>
<p>then create an <code>inventory.yaml</code> with the following content:</p>
<pre><code class="language-yaml">plugin: cloud.terraform.terraform_provider
# project_path: ../terraform # if your Terraform code is in a different directory
# state_file: mycustomstate.tfstate # if you wanted to define which state file</code></pre>
<p>and set it as the default inventory in <code>ansible.cfg</code>:</p>
<pre><code class="language-ini">[defaults]
inventory = inventory.yaml</code></pre>
<p>You can confirm the plugin works by doing:</p>
<pre><code class="language-sh">ansible-inventory --graph</code></pre>
<p>which should return something like the following:</p>
<pre><code class="language-sh">@all:
  |--@ungrouped:
  |--@gitea:
  |  |--192.168.1.211</code></pre>
<h2 id="heading">🎉</h2>
<p>What&rsquo;s good about this is now you can be hands-off with IP addresses.</p>
<p>Terraform can request a new machine, wait for it to receive an IP address and then make it available for Ansible to use, without you needing to do anything.</p>
<h3 id="remote-state">Remote state</h3>
<p>The Ansible plugin will default to using whichever backend you use for the Terraform state file, whether that&rsquo;s local or in an S3-compatible location.</p>
<p>This means Ansible is always running against the current infrastructure, which helps when colleagues and automations are updating things a <del>hundred</del> thousand times a day.</p>
<h2 id="in-conclusion">In Conclusion</h2>
<p>Using Terraform and Ansible together can cover all aspects of Infrastructure as Code.</p>
<p>The Ansible provider lets you keep all your resource code together in Terraform and then makes it available to Ansible, which uses a plugin to let it use the state file as its inventory.</p>]]></content:encoded><source:markdown>
Terraform and Ansible are complementary tools with which you can do Infrastructure as Code. You would use [Terraform](https://www.terraform.io/) to request machines from providers and then [Ansible](https://docs.ansible.com/ansible/latest/index.html) to configure them.

Using both of them together, with a dynamic inventory to link them, has been technically possible for years but never obvious enough for me to work out.

Until I found the Terraform provider.

&lt;!--more--&gt;

## Ansible provider for Terraform

By using the [Ansible provider](https://registry.terraform.io/providers/ansible/ansible/latest) you can teach Terraform what an Ansible inventory entry would look like next to the rest of its code.

You start by defining the provider:

```terraform
terraform {
  required_providers {
    ansible = {
      source  = &#34;ansible/ansible&#34;
      version = &#34;1.3.0&#34;
    }
  }
}
```

and then you can define the Ansible inventory entry right next to the resource:

```terraform
resource &#34;proxmox_vm_qemu&#34; &#34;gitea&#34; {
  cores = 1
	...
}

resource &#34;ansible_host&#34; &#34;gitea&#34; {
  name   = proxmox_vm_qemu.gitea.ssh_host
  groups = [&#34;gitea&#34;]
  variables = {
    ansible_user = &#34;ansible&#34;
  }
}
```

which means you don&#39;t need to hardcode IP addresses anywhere.

You would need to `terraform apply` this plan so that Terraform adds these resources to the state file so that Ansible can use them.

## Terraform plugin for Ansible

On the Ansible side you use [a plugin](https://github.com/ansible-collections/cloud.terraform) to tell it how to use Terraform as its inventory.

Add the following to your `requirements.yaml` file:

```yaml
collections:
  - name: cloud.terraform
    version: 1.1.0
```

and then install the collection using `ansible-galaxy collection install -r requirements.yaml`,

then create an `inventory.yaml` with the following content:

```yaml
plugin: cloud.terraform.terraform_provider
# project_path: ../terraform # if your Terraform code is in a different directory
# state_file: mycustomstate.tfstate # if you wanted to define which state file
```

and set it as the default inventory in `ansible.cfg`:

```ini
[defaults]
inventory = inventory.yaml
```

You can confirm the plugin works by doing:

```sh
ansible-inventory --graph
```

which should return something like the following:

```sh
@all:
  |--@ungrouped:
  |--@gitea:
  |  |--192.168.1.211
```

## 🎉

What&#39;s good about this is now you can be hands-off with IP addresses.

Terraform can request a new machine, wait for it to receive an IP address and then make it available for Ansible to use, without you needing to do anything.

### Remote state

The Ansible plugin will default to using whichever backend you use for the Terraform state file, whether that&#39;s local or in an S3-compatible location.

This means Ansible is always running against the current infrastructure, which helps when colleagues and automations are updating things a ~~hundred~~ thousand times a day.

## In Conclusion

Using Terraform and Ansible together can cover all aspects of Infrastructure as Code.

The Ansible provider lets you keep all your resource code together in Terraform and then makes it available to Ansible, which uses a plugin to let it use the state file as its inventory.
</source:markdown></item>
  </channel>
</rss>
