How to remotely configure Caddy 2

1. Caddy version (caddy version):


2. How I run Caddy:

a. System environment:

AWS EC2 T2 Micro, Amazon Linux 2, Docker 19.03

b. Command:

docker build -t caddy .

docker run --name caddyserver -v $PWD/Caddyfile:/etc/caddy/Caddyfile -v $PWD/caddy.json:/etc/caddy/caddy.json -p 80:80 -p 443:443 -p 2020:2020 --rm caddy

c. Service/unit/compose file:

FROM caddy:2-alpine

RUN apk --no-cache add curl

EXPOSE 80 443 2020

d. My complete Caddyfile or JSON config:

	admin localhost:2020
} {
	redir permanent
} {

	rewrite *{uri}

3. The problem I’m having:

I would like to remotely configure my Caddy server using something like

I tried adding the following block, but it didn’t solve my problem: {
  reverse_proxy localhost:2020

Then I tried setting the admin endpoint to, but running Caddy failed.

The port 2020 is already exposed in my AWS EC2 security group.

I am not sure if what I’m doing is possible. If it is, I’d really appreciate it if I can get any sort of help : )

4. Error messages and/or full log output:

Connecting to or EC2_IP:2020 in Insomnia resulted in Error: Couldn't connect to server.

Using curl returns connection refused.

5. What I already tried:

oops, I already described this in 3)

6. Links to relevant resources:

A similar implementation to what I’m trying to do is GitHub Pages. They used to run on Nginx and reload the config every 30 min (Rearchitecting GitHub Pages | The GitHub Blog). I’d like to do the same thing, except, instead of reloading the config using a cron job, I can update it remotely.

PS. thank you for the awesome work :slight_smile:

Setting the admin endpoint to localhost:2020 will only allow connections from within the container. Instead, you could set it to :2020 which should allow connections from any IP.

FYI, there’s a Caddy v2 git plugin that might do what you need if you’re trying to implement a site that automatically updates:

Thank you @francislavoie, I saw you comment on a similar issue and using :2020 actually worked!

Just one more thing, how do I assign only to that endpoint? So that you can’t use say

1 Like

Currently there’s no way to do that from the Caddyfile. Instead you’ll need to use the JSON config to lock it down further:

You can set enforce_origin to true, and provide a list of allowed origins.

You can convert your Caddyfile config to JSON using caddy adapt --config /path/to/Caddyfile.

1 Like

Actually, if you can bind to then it will enforce the Host header to match admin.go - caddyserver/caddy - Sourcegraph

In other words, it should “just work” assuming you can bind to that interface. (Depends on your system and local DNS resolution.)

1 Like

Thank you @francislavoie! The JSON config is totally okay for me, so this solved :slight_smile:

@matt How does binding work in this case? I tried this config, but it is clearly wrong (since it doesn’t work)

:2020 {

I got:

run: loading initial config: loading new config: http app module: start: tcp: listening on []:2020: listen tcp: lookup no such host

Thank you!

The listen address for the admin endpoint is the socket the admin endpoint binds to.

Oh, so you meant changing the global config part like so?


Yep! That will bind to that interface only and restrict the Host header to that value.

1 Like

When running Caddy using the docker command

docker build -t caddy .

docker run --network host --name caddyserver -v $PWD/Caddyfile:/etc/caddy/Caddyfile  -p 80:80 -p 443:443 -p 2020:2020 --rm caddy

I get:

run: loading initial config: loading new config: starting caddy administration endpoint: listen tcp EC2_PUBLIC_IP4:2020: bind: cannot assign requested address

I’m not sure if this part is related to Caddy. If it’s not, please feel free to skip it :slight_smile:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.