Repository navigation
Writing a Plugin: Caddyfile Loader
Join the Caddy Community Forum to chat with other Caddy developers!
You can customize how Caddy loads the Caddyfile. This is useful if you manage your server configuration with external tools or services and you want to get the Caddyfile from them dynamically. If you play your cards right, you can even have Caddy reload the Caddyfile when it changes upstream.
All you have to do is implement the caddy.Loader interface and register your plugin with a unique name.
Here's a skeleton:
import "github.com/mholt/caddy"
func init() {
caddy.RegisterCaddyfileLoader("myloader", caddy.LoaderFunc(myLoader))
}
func myLoader(serverType string) (caddy.Input, error) {
return nil, nil
}If your loader needs more state, you can implement the caddy.Loader interface directly using a struct, instead of using the wrapper type caddy.LoaderFunc like we did above. Simple loaders need only be standalone functions.
Your loader should return an error only if it is worth aborting and reporting to the user. In other words, do not return an error merely because there is no Caddyfile for your loader to load.
When Caddy starts, it iterates the different loaders, asking them for a Caddyfile. It always invokes all the loaders, but only one at most should return a value. This means that your loader must not return a caddy.Input value unless conditions are just right. For example: if certain environment variables are set, or a command line flag was used to fill in a value, those are specific conditions to agree on how the Caddyfile should be loaded.
Invoking Caddy with multiple ways to load the Caddyfile is confusing and will be treated as an error.
So if you want to write a Caddyfile loader to hook into etcd, for instance, make sure it only returns a Caddyfile if, say, environment variables to access etcd are set.
You can set a default Caddyfile loader for times when no other loader returns a Caddyfile. To do this, simply call caddy.SetDefaultCaddyfileLoader() instead of caddy.RegisterCaddyfileLoader(). Note that this will overwrite any previous, default loader.
If the default loader does not return any Caddyfile input, Caddy will ask the server type for a default input. If the server type does not specify a default input, a blank Caddyfile will be assumed.
A Caddyfile loader may be written so that Caddy reloads and applies the new Caddyfile when it changes. The implementation details vary widely, but you can cause Caddy to reload with the new Caddyfile like so:
(TODO)