Conradludgate/terraform-provider-caddy

Last week I got tired of how I configured my VPS. My nginx config got confusing and I had random servers running in tmux everywhere, and some left over docker containers I didn’t realise were running.

This leads me to this submission! I decided to reinstall the os and terraform the entire thing, and I opted to use caddy for my routing. I couldn’t find a terraform provider for caddy already, but I did find the admin API, so I decided to write my own.

I really like how it came out and it works really well.

resource "caddy_server" "https" {
  name = "https"
  listen = [":443"]
  
  route {
    match {
      host = ["first.example.com"]
    }
    handle {
      static_response {
        body = "hello world"
      }
    }
  }

  route {
    match {
      host = ["second.example.com"]
    }
    handle {
      static_response {
        body = "goodbye world"
      }
    }
  }
}

On my own server, I combine this with the docker terraform provider with a config like this

resource "caddy_server" "https" {
  name   = "https"
  listen = [":443"]

  routes = [
    data.caddy_server_route.echo.id,
    // more routes defined elsewhere ...
  ]
}

data "caddy_server_route" "echo" {
  match {
    host = ["echo.example.com"]
  }

  handle {
    reverse_proxy {
      upstream {
        dial = "localhost:8080"
      }
    }
  }
}

resource "docker_container" "echo" {
  name  = "echo-server"
  image = docker_image.echo.latest

  ports {
    internal = 80
    external = 8080
  }
}

resource "docker_image" "echo" {
  name = "mendhak/http-https-echo"
}

I hope someone else finds this interesting or useful. The provider is definitely still in beta, and the documentation is a bit sparse, but I intend to keep adding more docs/features as I get the time. This is also my first time with caddy, feedback appreciated :slight_smile:

4 Likes

This is something I was literally going to start planning on coding this afternoon.

I’ll start reviewing this week, thank you very much for the contributions!!!

2 Likes

Apologies from taking this project away from you, but I’ll happily help you get set up if you have any issues, as well as accepting PRs you may want to contribute

No need to apologize! I had not even started coding the project yet, so looking forward to collaborating. :slight_smile:

1 Like

I see you intend to you Caddy with Consul for certificate storage. I haven’t yet implemented storage configuration options in the terraform provider, although it won’t be too hard. I was thinking for a while about what to do with regards to non-standard caddy configurations. I think that it’s OK to have the terraform schema contain the non-standard definitions. Caddy will just error if I try to load an invalid config (for example if I tried to configure consul without the module built into my caddy server - will need testing to see how it reacts exactly though). The non-standard schema definitions will just be documented non-standard, like how caddy represents non standard json configs: JSON Config Structure - Caddy Documentation

For some background into how the provider is configured if you want to add your own resources/config changes:
terraform-provider-caddy/resource_server.go at main · conradludgate/terraform-provider-caddy · GitHub Defines the schema, which resembles the JSON closely config

terraform-provider-caddy/resource_server.go at main · conradludgate/terraform-provider-caddy · GitHub the resource data into a Caddy JSON compatible struct

terraform-provider-caddy/server.go at main · conradludgate/terraform-provider-caddy · GitHub Takes that struct and sends it to the Caddy admin endpoint

Conrad and myself had some back and forth over email and this is where we are. :grinning:

Thank you!!

1 Like

This topic was automatically closed after 14 days. New replies are no longer allowed.