Automatically forward subdomain to port on localhost

1. Caddy version (caddy version):

v2.4.3

2. How I run Caddy:

as a homebrew service on macOS with:
brew services start caddy

a. System environment:

MacOS

b. Command:

/usr/local/opt/caddy/bin/caddy run --config /usr/local/etc/Caddyfile

c. Service/unit/compose file:

This is the default homebrew.caddy.service installed by brew install caddy:

[Unit]
Description=Homebrew generated unit for caddy

[Install]
WantedBy=multi-user.target

[Service]
Type=simple
ExecStart=/usr/local/opt/caddy/bin/caddy run --config /usr/local/etc/Caddyfile
Restart=always
StandardOutput=append:/usr/local/var/log/caddy.log
StandardError=append:/usr/local/var/log/caddy.log

d. My complete Caddyfile or JSON config:

3000.localhost {
    tls internal
    reverse_proxy localhost:3000
}

3001.localhost {
    tls internal
    reverse_proxy localhost:3001
}

3002.localhost {
    tls internal
    reverse_proxy localhost:3002
}

3020.localhost {
    tls internal
    reverse_proxy localhost:3020
}

4000.localhost {
    tls internal
    reverse_proxy localhost:4000
}

5000.localhost {
    tls internal
    reverse_proxy localhost:5000
}

6000.localhost {
    tls internal
    reverse_proxy localhost:6000
}

7000.localhost {
    tls internal
    reverse_proxy localhost:7000
}

8000.localhost {
    tls internal
    reverse_proxy localhost:8000
}

3. The problem I’m having:

I’m working with a microservices architecture and often have to spin up multiple front-ends running on different ports, the above config is working for me but I have to add a new config section for each new service I start on a different port, this is starting to get messy.

It would be cool if I could instead configure caddy to capture the subdomain and reverse proxy automaticaly to that port on localhost but I can’t figure out a way to do this in the Caddyfile.

4. Error messages and/or full log output:

None

5. What I already tried:

I’ve read through the docs but can’t figure out if what I’m trying is possble

6. Links to relevant resources:

Any help would be much appreciated.

Thanks
Rob

Maybe a snippet is what you’re after?

(sub2port) {
    {args.0}.localhost {
        tls internal
        reverse_proxy localhost:{args.0}
    }
}

import sub2port 3000
import sub2port 3001
...
2 Likes

That does clean things up quite a bit thanks.
would be great to not have to list out all the ports though

Maybe something like this:

:443 {
	tls internal {
		on_demand
	}

	@portLocalhost header_regexp port Host ^([0-9]+)\.localhost$
	handle @portLocalhost {
		reverse_proxy localhost:{re.port.1}
	}

	handle {
		respond "Bad hostname" 400
	}
}

But a config like this would only be appropriate for development/local use. I cannot recommend this kind of pattern for production. Using on_demand opens you up for abuse unless you configure Caddy with the ask option to limit the domains for which certificates are issued.

3 Likes

This works perfectly thanks so much .

I get this is a very stupid thing to do in prod but it makes spinning up local servers with tls so easy, thanks again

1 Like

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