1. Caddy version:
2.6.2
2. How I installed, and run Caddy:
a. System environment:
pacman -Suy caddy
Manjaro Linux 22.0.4 x86
b. Command:
caddy run
c. Service/unit/compose file:
n/a
d. My complete Caddy config:
{
auto_https off
}
http://localhost:2000 {
reverse_proxy localhost:8080
}
http://customer1.localhost:2000 {
forward_auth localhost:8080 {
uri /init
}
reverse_proxy localhost:40943
}
(note that all the localhost stuff and disabling of https is because I’m developing still)
3. The problem I’m having:
Each customer of ours has their own subdomain. Customers can onboard themselves. The service running at port 8080 handles that. That same service also handle auth (via a HTTP header, irrelevant now).
What I want to do is that the service running at 8080 adds new site blocks. This is actually pretty straightforward. I just make a HTTP POST request to the relevant config endpoint. Something like this:
curl -H 'Content-Type: application/json' -v -d @new_domain.json localhost:2019/config/apps/http/servers/srv0/routes
The question is about the JSON document needing to be POST’ed. A site block with merely one reverse_proxy
in it translates to a relatively simple JSON document. (I ‘converted’ the initial Caddyfile into JSON by starting Caddy with that file and making a GET request to the config endpoint of Caddy.)
But as soon as the forward_auth
directive comes into play the JSON document balloons:
$ curl -v localhost:2019/config/apps/http/servers/srv0|jq
{
"automatic_https": {
"disable": true,
"skip": [
"subdomain.localhost",
"localhost"
]
},
"listen": [
":2000"
],
"routes": [
{
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handle_response": [
{
"match": {
"status_code": [
2
]
},
"routes": [
{
"handle": [
{
"handler": "headers",
"request": {}
}
]
}
]
}
],
"handler": "reverse_proxy",
"headers": {
"request": {
"set": {
"X-Forwarded-Method": [
"{http.request.method}"
],
"X-Forwarded-Uri": [
"{http.request.uri}"
]
}
}
},
"rewrite": {
"method": "GET",
"uri": "/init"
},
"upstreams": [
{
"dial": "localhost:8080"
}
]
},
{
"handler": "reverse_proxy",
"upstreams": [
{
"dial": "localhost:40943"
}
]
}
]
}
]
}
],
"match": [
{
"host": [
"subdomain.localhost"
]
}
],
"terminal": true
},
{
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handler": "reverse_proxy",
"upstreams": [
{
"dial": "localhost:8080"
}
]
}
]
}
]
}
],
"match": [
{
"host": [
"localhost"
]
}
],
"terminal": true
}
]
}
4. Error messages and/or full log output:
n/a
5. What I already tried:
My issue with this is that my service is written in Go. I already had a ton of struct
s and now it becomes unwieldy to say the least (for example, the Handler
sometimes has this and that field, other times not).
Before I bite the bullet, I wondered if there is a Better Way.
For example: since my service is written in Go and Caddy is too I figured I could reuse the parsing logic and structs from Caddy! But that doesn’t seem to be exposed. Or perhaps I could just POST Caddyfile snippets, but only the /load
endpoint is able to consume Caddyfiles.
6. Links to relevant resources:
See text