Stretchyfile - A stretchy Caddyfile flavour

Hi everyone! I recently migrated my infrastructure to Caddy. I love the simplicity of the config. But while migrating, I realised how large my Caddyfile had become.

I decided to make Stretchyfile. Its goal is to improve how variables work in Caddy. I’ve open-sourced it, so hopefully others can use it if they find it useful.

Here is an example of how it can simplify your config:

This is an example scenario that I feel will apply to many people.

  • Using 2 mirror domains that are identical
  • Using port 80 and 443
  • Need subdomains to point to same server

Here is how I had it in my Caddyfile:

example.com:80, example.com:443, *.example.com:80, *.example.com:443, example.org:80, example.org:443, *.example.org:80, *.example.org:443 {
    respond "Hello, world!"
}

At least for me, this is very hard to keep track of, especially considering I primarily edit my Caddyfile using CLI, and not a code editor. I sometimes missed a combination of port and domain for example.

Here is how you can implement the same rules with Stretchyfile:

$domains = example.com,example.org,*.example.com,*.example.org
$ports = 80,443

${domains}:{ports} {
    respond "Hello, world!"
}

There are many combinations you can do. For example, if you have many domains or subdomains, maybe specifying the subdomains for each domain is too much for you. You can do this instead:

$domains = example.com,example.org
$domains = {domains},*.{domains}
$ports = 80,443

${domains}:{ports} {
    respond "Hello, world!"
}

I hope some of you find this useful. Please let me know what you think. More examples and documentation are available on GitHub.

It’s worth noting, I have tested this for my use-cases. If you like the idea of Stretchyfile, but it doesn’t work for your use-case, feel free to improve on it and send a PR. It’s only 80 lines of Python.

2 Likes

You don’t need to specify both 80 and 443. Your config can be simplified to:

example.com, *.example.com,
example.org, *.example.org {
	respond "Hello, world!"
}

Caddy defaults to port 443, and automatically adds HTTP->HTTPS redirect routes on port 80.

Good to know. Though, port 80 and 443 were just examples.

Yeah, I’m just mentioning it in case you built this due to a misunderstand of how the Caddyfile works. IMO that kind of tooling is not necessary, the Caddyfile already allows you to reduce duplication with snippets with arguments as well.

My main purpose for this was to allow mapping to multiple domains. For example certain ISPs in specific countries block access to my site, so I maintain multiple mirror domains. It’s annoying having to update my server configuration each time I get a new domain. I’d much rather go:

$domains = domain1.com,domain2.com

${domains} {
    # Config
}

From my understanding, Caddy doesn’t support this, unless I’m mistaken?

This is also very useful for automated server configuration changes. Although this one is VERY niche, it’s a lot easier to find the line starting with $domains = and append a new domain, than to insert it wherever domains are specified.

1 Like
(config) {
	# directives go here
}

domain1.com, domain2.com {
	import config
}

domain3.com, domain4.com {
	import config
}

And in addition to that, you can pass arguments to import which get expanded in the snippet with {args[0]} and such.

You could also do:

(site) {
	{args[:]} {
		# some directives here
	}
}

import site domain1.com domain2.com
import site domain3.com domain4.com
1 Like

Very cool! Love to see people making Caddy into exactly what they want it to be :grinning: Thanks for sharing!!