Can I use a variable for the value of certain directives?

1. The problem I’m having:

I have this somewhat odd case where I want to set the value of a directive (path) to a variable holding a long list of paths so that I can also respond on an endpoint using respond with body in order to output the same list (the data isn’t sensitive). I’m trying to avoid duplicating the list or setting up code generation.

It looks like the only directives that are set up to accept variables are the ones that accept strings.

2. Error messages and/or full log output:

Here’s an example. If I try to set a variable like this, in the format that I might otherwise set for path, it will error out.

vars example_paths /foo \
/bar/* \

Error: adapting config using caddyfile: parsing caddyfile tokens for ‘vars’: /path/to/routes.caddy:3 - Error during parsing: Wrong argument count or unexpected line ending after ‘/bar/*’

Likewise, if I assign a string, it will not process the routes properly (no error):

vars example_paths "/foo

Thanks in advance for any pointers, even if the answer is “Caddy can’t do that.”

3. Caddy version:


4. How I installed and ran Caddy:

It’s installed and ran locally via Homebrew.

a. System environment:

macOS Ventura 13.5.

b. Command:

caddy run --config Caddyfile.local

c. Service/unit/compose file:


d. My complete Caddy config:

This is a simple question about the capabilities of Caddy. I couldn’t include this even if I wanted to.

5. Links to relevant resources:


path is a request matcher, not a directive.

Make sure to read Caddyfile Concepts — Caddy Documentation if you haven’t already

That’s not valid syntax; we don’t have newline escaping for tokens

In the Caddyfile, we have the concept of “tokens”. A token is a single config value (usually a string). In the config, tokens are space separated, but if you use quotes you can have a token with spaces in its value.

The vars directive only takes one token as the value (currently, anyway). So passing it multiple tokens won’t work.

If you pass it a space (newlines are “whitespace” too) separated token, that’s still a single token, and when you use it later, the thing using the token won’t know the difference.

So basically if you later do a request matcher like @some-paths path {vars.example_paths}, the path matcher will try to match the entire token as a single path, (which will probably never match).

So essentially, no it’s not currently possible to match a list of paths like this with those mechanisms.

If you can completely fill out the help topic template (full config, logs) and explain specifically what you’re trying to do, I could probably suggest an alternative approach.

1 Like

Thanks, I appreciate the quick response. I knew those two syntaxes didn’t work, but it’s helpful to confirm it’s for the reason I suspected, and also that it’s not currently possible to do what I want. Perhaps it’s worthwhile to consider how to assign multiple tokens to a variable and assign a variable to a request matcher? Although I recognize it’s probably a niche use case.

In this particular case, I was looking for a way to easily share path information on demand, without duplication, between Caddy and one of the applications it proxies to. The idea is that the application could hit an endpoint on startup to load the same list of paths. (It has to do with how the application handles specific LLM-generated links—we need to dynamically set a different link target for specific paths.)

It’s easy enough to do it with duplication, but it sounds like it’s not easy to do DRY without some kind of templating setup / config generation. So that’s the route I’ll pursue. Thanks again!

You could write your own plugin that loads the list of paths to match dynamically (i.e. your own matcher plugin). See Extending Caddy — Caddy Documentation. You could call it dynamic_path or something and have it load the paths from somewhere and cache them for a few minutes, something like that.

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