Extending Caddy

Matt Holt edited this page Jun 28, 2017 · 15 revisions

Join the Caddy Community Forum to chat with other Caddy developers!

Caddy can be extended with plugins. Plugins add missing functionality to Caddy. They are "plugged in" at compile-time.

Almost everything in Caddy is a plugin. The HTTP server is a plugin. Caddy's advanced TLS features are plugins. Every single directive you type in the Caddyfile is a plugin.

Some plug into Caddy core, while others plug into a specific server type. Some plugins even plug into other plugins (for example, DNS providers plug into the tls plugin). Caddy ships with certain plugins by default: the HTTP server with its standard directives and the standard Caddyfile loaders.

There are different kinds of plugins you can write:

  • Server Types - A kind of server that Caddy can run (HTTP and DNS for example)
  • Directives - A directive for the Caddyfile
  • HTTP Middleware - A function that handles HTTP requests, usually invoked by a Caddyfile directive
  • Caddyfile Loader - Customize how the Caddyfile is loaded
  • DNS Provider - Make ACME's DNS challenge compatible with your DNS provider
  • Listener Middleware - Wrap a net.Listener with your own Listener to do something at the transport or protocol layer
  • Event Hook - Execute a function when the Caddy process emits certain events

The links above will show you how to write those kinds of plugins, but always refer to the godoc and the code base itself when you have questions!

5 Steps to Make a Caddy Plugin

Even though there are different kinds of plugins, the process of creating one is roughly the same for all.

1. Create a package and register your plugin.

Start a new Go package with an init function and register your plugin with Caddy or the server type or the other plugin that uses it. The registration function you use depends on the kind of plugin. A few are shown here:

import "github.com/mholt/caddy"

func init() {
	// register a "generic" plugin, like a directive or middleware
	caddy.RegisterPlugin("name", myPlugin)

	// register a plugin that can load the Caddyfile when Caddy starts
	caddy.RegisterCaddyfileLoader("name", myLoader)

	// register a plugin that implements an entire server type
	// for use with Caddy
	caddy.RegisterServerType("name", myServerType)

	// register a function that runs when Caddy emits events
	caddy.RegisterEventHook("eventName", myHookFn)

	// add a function that wraps listeners for the HTTP server
	// (it's more common for a directive to call this rather than a standalone plugin)
	httpserver.AddListenerMiddleware(myListenerMiddleware)

	// ... there are others. See the godoc.
}

Every plugin must have a name and, when applicable, the name must be unique for that server type.

2. Plug in your plugin.

To plug your plugin into Caddy, import it. This is usually done near the top of run.go:

import _ "your/plugin/package/path/here"

3. Test, test, test!

Write tests. Get good coverage where possible, and make sure your assertions test what you think they are testing! Use go vet and go test -race to ensure your plugin is as error-free as possible.

4. Add your plugin to the Caddy web site.

Make it easy for others to find and use your plugin! Follow these instructions to add your plugin to Caddy's download page.

5. Maintain your plugin.

People will use plugins that are useful, clearly documented, easy to use, and maintained by their owner.

And congratulations, you're a Caddy plugin author!

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.