Variable assignment?

Just a general query…

Here’s a typical Caddyfile block I might have set up for a reverse proxy.

site.com {
  ...
   reverse_proxy 10.1.1.1
}

There may be times when I might need to take the site offline for scheduled maintenance or there’s some other reason the site in down. I thought I would include the check shown.

site.com {
  ...
  @offline expression `{online} == "no"`
  handle @offline {
  # Do whatever e.g. respond/redir
  }
  reverse_proxy 10.1.1.1
}

What I’m unclear about, assuming it’s possible, is the syntax for setting up the online variable.
Under normal operating conditions online = "yes" and the added code will be skipped. Under abnormal conditions, I’d set online = "no" and the added code would be invoked after a caddy reload.

Is (non-environmental) variable assignment possible? If so, can you please explain the syntax? Or is there a better way to gracefully take a site offline and inform clients?

There is in JSON via the vars handler (and it’s how root works under the hood, which you can see if you caddy adapt), but not in the Caddyfile currently because its usecase is somewhat limited. The map directive is more equipped to do that generally.

Another way to do “variables” is via import args:

Maybe something like:

(maintenance) {
	@offline expression `"{args.0}" == "yes"`
	handle @offline {
		# whatever
	}
}

site.com {
	import maintenance no
	# import maintenance yes
}
1 Like

Yes, of course! I’d forgotten about that.

For anyone who’s interested, here are alternative solutions using the map directive.

site.com {
  ...
  map {labels.1} {online} {
   site yes # Set to no if offline
  }

  @offline expression `{online} == "no"`
  handle @offline {
  # Do whatever e.g. respond/redir
  }

  reverse_proxy 10.1.1.1
}

What I like about the above solution is that it works well with the following form of Caddy block:

www.site.com site.com {
  ...
}

However, it doesn’t work if dealing with local and international variations of the domain e.g.

www.site.com site.com,
www.site.com.au, site.com.au {
  ...
}

This version works better for the general case:

site.com {
  ...
  map {host} {online} {
   default yes # Set to no if offline
  }

  @offline expression `{online} == "no"`
  handle @offline {
  # Do whatever e.g. respond/redir
  }

  reverse_proxy 10.1.1.1
}

Interestingly, the map directive must be laid out as indicated in the documentation.
For instance, this won’t work:

map {host} {online} {default yes}

FWIW, the import args is, I think, a better solution overall when dealing with multiple domains.

You could probably do like:

map 1 {online} {
	...
}

I don’t think you actually need a placeholder to map over if you’re only going to use “default”

1 Like

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