<?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/2026/02/</link>
    <description>Posts by Paul Tibbetts published in February 2026</description>
    <generator>Hugo</generator>
    <language>en-gb</language>
    <atom:link href="https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/feed.xml" rel="self" type="application/rss+xml" /><item>
      <title>I Made an Ansible Role for Caddy</title>
      <link>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/24/i-made-an-ansible-role-for-caddy/</link>
      <pubDate>Tue, 24 Feb 2026 12:10:45 +0000</pubDate>
      <guid>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/24/i-made-an-ansible-role-for-caddy/</guid>
      <category>Ansible</category>
      <category>Caddy</category>
      <category>code</category>
      <description>paultibbetts/ansible-role-caddy is an Ansible role for Caddy web server that lets you install Caddy with plugins.
I use it for my personal site and in my homelab.
This is what it does and how to use it.</description>
      <content:encoded><![CDATA[<p><a href="https://github.com/paultibbetts/ansible-role-caddy">paultibbetts/ansible-role-caddy</a>
 is an Ansible role for Caddy web server that lets you install Caddy with plugins.</p>
<p>I use it for my personal site and in my homelab.</p>
<p>This is what it does and how to use it.</p>
<h2 id="what-it-does">What it does</h2>
<p>An Ansible role is like a plugin that extends Ansible with the ability to do something, and in this case it&rsquo;s to install and manage <a href="https://caddyserver.com/">Caddy</a>
.</p>
<p>Specifically it:</p>
<ul>
<li>installs Caddy</li>
<li>
<ul>
<li>defaults to using the <code>apt</code> package manager</li>
</ul>
</li>
<li>
<ul>
<li>or it can be given the URL to a specific binary</li>
</ul>
</li>
<li>
<ul>
<li>or it can be given a list of plugins</li>
</ul>
</li>
<li>can be used to manage Caddy</li>
<li>
<ul>
<li>or completely uninstall it</li>
</ul>
</li>
<li>can write the Caddyfile from a template</li>
</ul>
<h2 id="why-caddy">Why Caddy?</h2>
<p>I use Caddy because it manages TLS certificates automatically and, with a plugin, supports <a href="https://letsencrypt.org/docs/challenge-types/#dns-01-challenge">DNS-01 challenges</a>
.</p>
<p>DNS-01 is useful when services aren&rsquo;t reachable by Lets Encrypt, like in a homelab, so private networks can also have TLS.</p>
<h2 id="design-goals">Design goals</h2>
<p>The role was designed with the following in mind:</p>
<ul>
<li>idempotent and safe to re-run</li>
<li>Debian and Ubuntu</li>
<li>works on x86 and ARM</li>
<li>supports installing with plugins</li>
<li>can optionally write the Caddyfile</li>
</ul>
<p>There are already Ansible roles for Caddy, like the one listed in <a href="https://caddyserver.com/docs/install#ansible">the docs</a>
, but I needed a role that could install Caddy with plugins.</p>
<h2 id="how-to-use-it">How to use it</h2>
<p>The role is available on <a href="https://galaxy.ansible.com/ui/standalone/roles/paultibbetts/caddy/">Ansible Galaxy</a>
.</p>
<h3 id="install">Install</h3>
<p>You can install it by adding:</p>
<pre><code class="language-yaml">- name: paultibbetts.caddy
  version: 1.0.0</code></pre>
<p>to your <code>requirements.yml</code> file and then running:</p>
<pre><code class="language-sh">ansible-galaxy role install -r requirements.yml</code></pre>
<h3 id="variables">Variables</h3>
<p>The variables for the role, as well as the default settings, can all be overridden.</p>
<p>The most important ones are the install method, the plugins to include, and whether the role writes the Caddyfile for you.</p>
<pre><code class="language-yaml">caddy_install_method: apt</code></pre>
<p>The role defaults to installing Caddy via <code>apt</code>, the package manager for Debian/Ubuntu.</p>
<p>This means Caddy does not include any plugins but it does get updated when you run <code>apt upgrade</code>.</p>
<pre><code class="language-yaml">caddy_install_method: download</code></pre>
<p>Alternatively you can change the install method to <code>download</code>.</p>
<p>Now you can pass in the URL of a specific binary using:</p>
<pre><code class="language-yaml">caddy_download_url: &#34;&#34;</code></pre>
<p>Using this you could build a binary for Caddy (including plugins), host it, then pass that URL to the role and that specific binary will be installed.</p>
<p>This is currently the only way to install a specific version of Caddy that isn&rsquo;t &ldquo;latest&rdquo;.</p>
<p>If you want to install plugins for Caddy and don&rsquo;t want to build your own binary you can leave the download URL empty and pass in the plugins:</p>
<pre><code class="language-yaml">caddy_plugins:
  - github.com/caddy-dns/cloudflare</code></pre>
<p>and the role will generate a URL from the <a href="https://caddyserver.com/download">download page</a>
.</p>
<pre><code class="language-yaml">caddy_caddyfile_template: &#34;&#34; | &#34;{{ playbook_dir }}/templates/Caddyfile.j2&#34;</code></pre>
<p>The Caddyfile template variable lets you pass in a template of a Caddyfile for Caddy to use and it will be written to the appropriate place.</p>
<p>Letting the role write the Caddyfile means you can import the role, set its variables, and have all of Caddy configured by one thing - you don&rsquo;t need to write extra tasks after installation to get it up and running.</p>
<h3 id="examples">Examples</h3>
<p>The following examples show how the role can be used for a public website and for a private homelab reverse proxy.</p>
<p>In both instances Caddy acquires TLS certificates from Lets Encrypt, using Cloudflare to do DNS-01 challenges.</p>
<h4 id="example-personal-website">Example: Personal website</h4>
<p>The role can be used to setup Caddy to host a personal website.</p>
<pre><code class="language-yaml">- hosts: server
  become: true
  roles:
    - role: paultibbetts.caddy
      vars:
        caddy_caddyfile_template: &#34;{{ playbook_dir }}/templates/Caddyfile.j2&#34;
        caddy_install_method: download
        caddy_plugins:
          - github.com/caddy-dns/cloudflare
        caddy_manage_systemd_env_file: true
        caddy_systemd_env:
          CF_API_TOKEN: &#34;{{ vault_cf_api_token }}&#34;</code></pre>
<p>The <code>download</code> install method is used to install Caddy with the <a href="https://github.com/caddy-dns/cloudflare">Cloudflare plugin</a>
, the Cloudflare API token is passed to Caddy from Ansible vault, and a template is provided for the Caddyfile, which could look like:</p>
<pre><code class="language-Caddyfile">(cf_tls) {
    tls {
        dns cloudflare {env.CF_API_TOKEN}
    }
}

{% for site in web_sites %}
{{ site }} {
  import cf_tls
  root * {{ web_sites_root }}/{{ site }}/current
  file_server
  encode zstd gzip
  log
}
{% endfor %}</code></pre>
<p>This sets up Caddy to use Cloudflare to do DNS-01 challenges with Lets Encrypt to get a TLS certificate for each <code>site in web_sites</code>.</p>
<h4 id="example-homelab">Example: Homelab</h4>
<p>The role can also be used to setup Caddy in a private network, like a homelab.</p>
<pre><code class="language-yaml">- hosts: homelab
  become: true
  roles:
    - role: paultibbetts.caddy
      vars:
        caddy_caddyfile_template: &#34;{{ playbook_dir }}/templates/Caddyfile.j2&#34;
        caddy_install_method: download
        caddy_plugins:
          - github.com/caddy-dns/cloudflare
        caddy_manage_systemd_env_file: true
        caddy_systemd_env:
          CF_API_TOKEN: &#34;{{ vault_cf_api_token }}&#34;</code></pre>
<pre><code class="language-Caddyfile">{
        acme_dns cloudflare {env.CF_API_TOKEN}
}

service.homelab.example {
        reverse_proxy &lt;ip&gt;:&lt;port&gt;
}</code></pre>
<p>where the Cloudflare plugin is configured once and is then used to do DNS-01 challenges for any TLS certificates Caddy requests. Note this style has been deprecated and you should do it per host, like the earlier example for a personal website.</p>
<p>DNS-01 challenges are solved by writing a TXT record to prove domain ownership. This means Lets Encrypt is able to issue certificates for domains it can&rsquo;t reach, which makes DNS-01 ideal when Caddy is running in a homelab.</p>
<h2 id="molecule-scenarios">Molecule Scenarios</h2>
<p>Ansible Molecule is a way to run tests for an Ansible role.</p>
<p>The role includes molecule scenarios that test it works on x86 as well as Arm, because I use the role on a Raspberry Pi 4, as well as scenarios for the Cloudflare plugin and the Caddyfile templating.</p>
<h2 id="in-use">In use</h2>
<p>I use this role as part of the code that sets up the infrastructure for my website.</p>
<p>Terraform is used to provision the server, then Ansible is used to configure it, with this role setting up Caddy and the Caddyfile it uses.</p>
<p>The complete setup - Terraform, Ansible, Caddy, and the rest of the files - is documented at <a href="https://infra.paultibbetts.uk">infra.paultibbetts.uk</a>
, where I explain how it all fits together.</p>]]></content:encoded><source:markdown>
[paultibbetts/ansible-role-caddy](https://github.com/paultibbetts/ansible-role-caddy) is an Ansible role for Caddy web server that lets you install Caddy with plugins.

I use it for my personal site and in my homelab.

This is what it does and how to use it.

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

## What it does

An Ansible role is like a plugin that extends Ansible with the ability to do something, and in this case it&#39;s to install and manage [Caddy](https://caddyserver.com/).

Specifically it:

- installs Caddy
- - defaults to using the `apt` package manager
- - or it can be given the URL to a specific binary
- - or it can be given a list of plugins
- can be used to manage Caddy
- - or completely uninstall it
- can write the Caddyfile from a template

## Why Caddy?

I use Caddy because it manages TLS certificates automatically and, with a plugin, supports [DNS-01 challenges](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge).

DNS-01 is useful when services aren&#39;t reachable by Lets Encrypt, like in a homelab, so private networks can also have TLS.

## Design goals

The role was designed with the following in mind:

- idempotent and safe to re-run
- Debian and Ubuntu
- works on x86 and ARM
- supports installing with plugins
- can optionally write the Caddyfile

There are already Ansible roles for Caddy, like the one listed in [the docs](https://caddyserver.com/docs/install#ansible), but I needed a role that could install Caddy with plugins.

## How to use it

The role is available on [Ansible Galaxy](https://galaxy.ansible.com/ui/standalone/roles/paultibbetts/caddy/).

### Install

You can install it by adding:

```yaml
- name: paultibbetts.caddy
  version: 1.0.0
```

to your `requirements.yml` file and then running:

```sh
ansible-galaxy role install -r requirements.yml
```

### Variables

The variables for the role, as well as the default settings, can all be overridden.

The most important ones are the install method, the plugins to include, and whether the role writes the Caddyfile for you.

```yaml
caddy_install_method: apt
```

The role defaults to installing Caddy via `apt`, the package manager for Debian/Ubuntu.

This means Caddy does not include any plugins but it does get updated when you run `apt upgrade`.

```yaml
caddy_install_method: download
```

Alternatively you can change the install method to `download`.

Now you can pass in the URL of a specific binary using:

```yaml
caddy_download_url: &#34;&#34;
```

Using this you could build a binary for Caddy (including plugins), host it, then pass that URL to the role and that specific binary will be installed.

This is currently the only way to install a specific version of Caddy that isn&#39;t &#34;latest&#34;.

If you want to install plugins for Caddy and don&#39;t want to build your own binary you can leave the download URL empty and pass in the plugins:

```yaml
caddy_plugins:
  - github.com/caddy-dns/cloudflare
```

and the role will generate a URL from the [download page](https://caddyserver.com/download).

```yaml
caddy_caddyfile_template: &#34;&#34; | &#34;{{ playbook_dir }}/templates/Caddyfile.j2&#34;
```

The Caddyfile template variable lets you pass in a template of a Caddyfile for Caddy to use and it will be written to the appropriate place.

Letting the role write the Caddyfile means you can import the role, set its variables, and have all of Caddy configured by one thing - you don&#39;t need to write extra tasks after installation to get it up and running.

### Examples

The following examples show how the role can be used for a public website and for a private homelab reverse proxy.

In both instances Caddy acquires TLS certificates from Lets Encrypt, using Cloudflare to do DNS-01 challenges.

#### Example: Personal website

The role can be used to setup Caddy to host a personal website.

```yaml
- hosts: server
  become: true
  roles:
    - role: paultibbetts.caddy
      vars:
        caddy_caddyfile_template: &#34;{{ playbook_dir }}/templates/Caddyfile.j2&#34;
        caddy_install_method: download
        caddy_plugins:
          - github.com/caddy-dns/cloudflare
        caddy_manage_systemd_env_file: true
        caddy_systemd_env:
          CF_API_TOKEN: &#34;{{ vault_cf_api_token }}&#34;
```

The `download` install method is used to install Caddy with the [Cloudflare plugin](https://github.com/caddy-dns/cloudflare), the Cloudflare API token is passed to Caddy from Ansible vault, and a template is provided for the Caddyfile, which could look like:

```Caddyfile
(cf_tls) {
    tls {
        dns cloudflare {env.CF_API_TOKEN}
    }
}

{% for site in web_sites %}
{{ site }} {
  import cf_tls
  root * {{ web_sites_root }}/{{ site }}/current
  file_server
  encode zstd gzip
  log
}
{% endfor %}
```

This sets up Caddy to use Cloudflare to do DNS-01 challenges with Lets Encrypt to get a TLS certificate for each `site in web_sites`.

#### Example: Homelab

The role can also be used to setup Caddy in a private network, like a homelab.

```yaml
- hosts: homelab
  become: true
  roles:
    - role: paultibbetts.caddy
      vars:
        caddy_caddyfile_template: &#34;{{ playbook_dir }}/templates/Caddyfile.j2&#34;
        caddy_install_method: download
        caddy_plugins:
          - github.com/caddy-dns/cloudflare
        caddy_manage_systemd_env_file: true
        caddy_systemd_env:
          CF_API_TOKEN: &#34;{{ vault_cf_api_token }}&#34;
```

```Caddyfile
{
        acme_dns cloudflare {env.CF_API_TOKEN}
}

service.homelab.example {
        reverse_proxy &lt;ip&gt;:&lt;port&gt;
}
```

where the Cloudflare plugin is configured once and is then used to do DNS-01 challenges for any TLS certificates Caddy requests. Note this style has been deprecated and you should do it per host, like the earlier example for a personal website.

DNS-01 challenges are solved by writing a TXT record to prove domain ownership. This means Lets Encrypt is able to issue certificates for domains it can&#39;t reach, which makes DNS-01 ideal when Caddy is running in a homelab.

## Molecule Scenarios

Ansible Molecule is a way to run tests for an Ansible role.

The role includes molecule scenarios that test it works on x86 as well as Arm, because I use the role on a Raspberry Pi 4, as well as scenarios for the Cloudflare plugin and the Caddyfile templating.

## In use

I use this role as part of the code that sets up the infrastructure for my website.

Terraform is used to provision the server, then Ansible is used to configure it, with this role setting up Caddy and the Caddyfile it uses.

The complete setup - Terraform, Ansible, Caddy, and the rest of the files - is documented at [infra.paultibbetts.uk](https://infra.paultibbetts.uk), where I explain how it all fits together.
</source:markdown></item><item>
      <title>Moved My Website From GitHub Pages to a Raspberry Pi</title>
      <link>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/19/moved-my-website-from-github-pages-to-a-raspberry-pi/</link>
      <pubDate>Thu, 19 Feb 2026 17:40:37 +0000</pubDate>
      <guid>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/19/moved-my-website-from-github-pages-to-a-raspberry-pi/</guid>
      <category>GitHub Pages</category>
      <category>Raspberry Pi</category>
      <description>My site was hosted on GitHub Pages.
It was simple and free, but it didn’t really feel like it was mine.
I’ve fixed that with a Raspberry Pi.</description>
      <content:encoded><![CDATA[<p>My site was hosted on GitHub Pages.</p>
<p>It was simple and free, but it didn&rsquo;t really feel like it was mine.</p>
<p>I&rsquo;ve fixed that with a Raspberry Pi.</p>
<h2 id="why-leave-github-pages">Why leave GitHub Pages?</h2>
<p><a href="https://docs.github.com/en/pages">GitHub Pages</a>
 is excellent at what it does.</p>
<p>You upload the code for your site to GitHub and they will build and host it for you.<br>
All for free.</p>
<p>So why leave?</p>
<h3 id="independence">Independence</h3>
<p>GitHub is owned by Microsoft, one of the biggest companies on the planet.</p>
<p>I have no problem with Microsoft, or using their economies of scale to do something for free that would otherwise cost me money, but ultimately I didn&rsquo;t feel very indie hosting my site on something I didn&rsquo;t control.</p>
<h3 id="sovereignty">Sovereignty</h3>
<p>GitHub and Microsoft are companies based in the USA, and those of us in Europe are re-considering our dependence on US tech.</p>
<p>Moving has brought my website closer to home - physically, legally, and ethically.</p>
<h3 id="portability">Portability</h3>
<p>The work to move from GitHub Pages to <em>anything else</em> has also made it easier to move it all again to another provider, should I ever choose to do so.</p>
<p>I&rsquo;ve taken the script to build the site out of GitHub Actions and made it part of the code itself. This decouples the site from any specific CI platform and makes both hosting and deployment replaceable.</p>
<h2 id="what-it-now-runs-on">What it now runs on</h2>
<p>There&rsquo;s no good reason for using a Raspberry Pi for this, I just thought it would be cool.</p>
<p>It is some of the cheapest hosting I could find from a UK-based provider, but there are cheaper options and hosting in Europe works just the same and is even cheaper.</p>
<p>The Pi is from <a href="https://www.mythic-beasts.com/">Mythic Beasts</a>
, a UK company based in Cambridge. It lives in London and runs on <a href="https://www.mythic-beasts.com/article/environment">green energy</a>
.</p>
<p>I provision it with Terraform, which lets me write the Pi down as code, and then I configure it using Ansible, another tool that sets up the software it runs.</p>
<p>Ansible installs and manages Caddy, which is a web server that has been configured to serve my site.</p>
<p>Deployment is still handled by GitHub Actions but now it goes to the Pi instead of Pages.</p>
<p>From the outside it all works exactly the same, but now it&rsquo;s on hardware I control, with a setup that&rsquo;s more portable than it was before.</p>
<h2 id="under-the-hood">Under the hood</h2>
<p>To make this all possible I ended up writing more code than I set out to.</p>
<p>There wasn&rsquo;t a Terraform provider for Mythic Beasts, so <a href="https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/09/2026-02-09-151500/">I wrote one</a>
.</p>
<p>For that to work it needed a client to talk to their APIs, so <a href="https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/06/2026-02-06-130000/">I wrote that too</a>
.</p>
<p>And to set up Caddy using Ansible <a href="https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/03/2026-02-03-175500/">I wrote my own role</a>
. There were already others that did this but none of them did exactly what I wanted, so I made my own.</p>
<p>None of this was really required, I could have moved to the Pi without writing any code, but the change from a manual setup to an automated one - driven by code - has forced me to treat the infrastructure of my website as a real system, that can change and evolve over time.</p>
<h2 id="what-this-means">What this means</h2>
<p>As a result my setup is now reproducible, portable and more independent.</p>
<p>I can see all the parts that make up my infrastructure and swap them out for alternatives. I&rsquo;m not tied down to a provider I can replace with a few lines of code.</p>
<p>And ultimately, there&rsquo;s no difference to visitors of the site, who still get the same experience as before.</p>
<h2 id="what-comes-next">What comes next</h2>
<p>Through doing this I can see that I might also be able to move my domain from Cloudflare to Mythic Beasts, another win for sovereignty.</p>
<p>If I did that, and moved the code hosting away from GitHub, I&rsquo;d have a website that&rsquo;s fully independent.</p>
<p>But that&rsquo;s for another time.</p>
<p>Over the next few posts I&rsquo;ll go over:</p>
<ul>
<li>how to use the Ansible role</li>
<li>making a provider for Terraform</li>
<li>the code that ties it all together</li>
<li>the site that explains it all in-depth</li>
</ul>
<h2 id="now">Now</h2>
<p>For now this post marks that this site&rsquo;s no longer hosted by GitHub Pages.</p>
<p>It&rsquo;s on a tiny computer, closer to home, set up by my own code.</p>
<p>That feels a bit more mine.</p>]]></content:encoded><source:markdown>
My site was hosted on GitHub Pages.

It was simple and free, but it didn&#39;t really feel like it was mine.

I&#39;ve fixed that with a Raspberry Pi.

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

## Why leave GitHub Pages?

[GitHub Pages](https://docs.github.com/en/pages) is excellent at what it does.

You upload the code for your site to GitHub and they will build and host it for you.  
All for free.

So why leave?

### Independence

GitHub is owned by Microsoft, one of the biggest companies on the planet.

I have no problem with Microsoft, or using their economies of scale to do something for free that would otherwise cost me money, but ultimately I didn&#39;t feel very indie hosting my site on something I didn&#39;t control.

### Sovereignty

GitHub and Microsoft are companies based in the USA, and those of us in Europe are re-considering our dependence on US tech.

Moving has brought my website closer to home - physically, legally, and ethically.

### Portability

The work to move from GitHub Pages to _anything else_ has also made it easier to move it all again to another provider, should I ever choose to do so.

I&#39;ve taken the script to build the site out of GitHub Actions and made it part of the code itself. This decouples the site from any specific CI platform and makes both hosting and deployment replaceable.

## What it now runs on

There&#39;s no good reason for using a Raspberry Pi for this, I just thought it would be cool.

It is some of the cheapest hosting I could find from a UK-based provider, but there are cheaper options and hosting in Europe works just the same and is even cheaper.

The Pi is from [Mythic Beasts](https://www.mythic-beasts.com/), a UK company based in Cambridge. It lives in London and runs on [green energy](https://www.mythic-beasts.com/article/environment).

I provision it with Terraform, which lets me write the Pi down as code, and then I configure it using Ansible, another tool that sets up the software it runs.

Ansible installs and manages Caddy, which is a web server that has been configured to serve my site.

Deployment is still handled by GitHub Actions but now it goes to the Pi instead of Pages.

From the outside it all works exactly the same, but now it&#39;s on hardware I control, with a setup that&#39;s more portable than it was before.

## Under the hood

To make this all possible I ended up writing more code than I set out to.

There wasn&#39;t a Terraform provider for Mythic Beasts, so [I wrote one](/2026/02/09/2026-02-09-151500/).

For that to work it needed a client to talk to their APIs, so [I wrote that too](/2026/02/06/2026-02-06-130000/).

And to set up Caddy using Ansible [I wrote my own role](/2026/02/03/2026-02-03-175500/). There were already others that did this but none of them did exactly what I wanted, so I made my own.

None of this was really required, I could have moved to the Pi without writing any code, but the change from a manual setup to an automated one - driven by code - has forced me to treat the infrastructure of my website as a real system, that can change and evolve over time.

## What this means

As a result my setup is now reproducible, portable and more independent.

I can see all the parts that make up my infrastructure and swap them out for alternatives. I&#39;m not tied down to a provider I can replace with a few lines of code.

And ultimately, there&#39;s no difference to visitors of the site, who still get the same experience as before.

## What comes next

Through doing this I can see that I might also be able to move my domain from Cloudflare to Mythic Beasts, another win for sovereignty.

If I did that, and moved the code hosting away from GitHub, I&#39;d have a website that&#39;s fully independent.

But that&#39;s for another time.

Over the next few posts I&#39;ll go over:

- how to use the Ansible role
- making a provider for Terraform
- the code that ties it all together
- the site that explains it all in-depth

## Now

For now this post marks that this site&#39;s no longer hosted by GitHub Pages.

It&#39;s on a tiny computer, closer to home, set up by my own code.

That feels a bit more mine.
</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>Published: paultibbetts/mythic-beasts-client-go A client for the Mythic Beasts …</title>
      <link>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/06/2026-02-06-130000/</link>
      <pubDate>Fri, 06 Feb 2026 13:00:00 +0000</pubDate>
      <guid>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/06/2026-02-06-130000/</guid>
      <category>go</category>
      <category>code</category>
      <category>Mythic Beasts</category>
      <description>Published: paultibbetts/mythic-beasts-client-go A client for the Mythic Beasts APIs, written in Go.</description>
      <content:encoded><![CDATA[<p>Published: <a href="https://github.com/paultibbetts/mythicbeasts-client-go/">paultibbetts/mythic-beasts-client-go</a>
</p>
<p>A client for the Mythic Beasts APIs, written in Go.</p>]]></content:encoded><source:markdown>
Published: [paultibbetts/mythic-beasts-client-go](https://github.com/paultibbetts/mythicbeasts-client-go/)

A client for the Mythic Beasts APIs, written in Go.
</source:markdown></item><item>
      <title>Published: paultibbetts/ansible-role-caddy An Ansible role to install and …</title>
      <link>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/03/2026-02-03-175500/</link>
      <pubDate>Tue, 03 Feb 2026 17:55:00 +0000</pubDate>
      <guid>https://paultibbetts-uk-feat-cooks.preview.lab.paultibbetts.uk/2026/02/03/2026-02-03-175500/</guid>
      <category>Ansible</category>
      <category>code</category>
      <category>Caddy</category>
      <description>Published: paultibbetts/ansible-role-caddy An Ansible role to install and operate Caddy web server.</description>
      <content:encoded><![CDATA[<p>Published: <a href="https://github.com/paultibbetts/ansible-role-caddy">paultibbetts/ansible-role-caddy</a>
</p>
<p>An Ansible role to install and operate Caddy web server.</p>]]></content:encoded><source:markdown>
Published: [paultibbetts/ansible-role-caddy](https://github.com/paultibbetts/ansible-role-caddy)

An Ansible role to install and operate Caddy web server.
</source:markdown></item>
  </channel>
</rss>
