What is a Module?
A module is any Go type that implements theModule interface:
modules.go:54-60
Module Information
Each module must provide metadata about itself:modules.go:62-77
Module Namespaces
Module IDs follow a hierarchical naming convention:modules.go:79-98
Namespace structure:
<namespace>.<name>Top-level modules (apps) have no namespace, just a name like http or tls.Common Namespaces
Module Registration
Modules must be registered before Caddy can use them:modules.go:130-161
Example Registration
Module Lifecycle
When a module is loaded, it goes through several phases:1
Instantiation
Caddy calls
ModuleInfo.New() to create a new instance:context.go:369
2
Unmarshaling
The module’s configuration is unmarshaled into the instance:
context.go:382-387
3
Provisioning
If the module implements
Provisioner, its Provision() method is called:modules.go:288-298
context.go:418-430
4
Validation
If the module implements
Validator, its Validate() method is called:modules.go:300-307
context.go:433-444
5
Usage
The module is now ready to be used. It’s typically type-asserted to a specific interface expected by the host module.
6
Cleanup
When the config is unloaded, if the module implements
CleanerUpper, its Cleanup() method is called:modules.go:309-317
context.go:75-83
Loading Modules
Caddy provides theLoadModule method to load modules from configuration:
context.go:181
Supported Field Types
TheLoadModule method supports several raw module types:
json.RawMessage
json.RawMessage
For a single module:
[]json.RawMessage
[]json.RawMessage
For a list of modules:
map[string]json.RawMessage (ModuleMap)
map[string]json.RawMessage (ModuleMap)
For a map where keys are module names:
Struct Tags
Modules are configured using struct tags:modules.go:319-336
namespace- The module namespace to search (e.g.,http.handlers)
inline_key- The JSON key containing the module name (e.g.,handler)
When using
ModuleMap, the map key IS the module name, so inline_key is not needed.Creating Custom Modules
Here’s a complete example of a custom HTTP handler module:1
Define the Module
2
Implement Provisioner
3
Implement Validator
4
Implement Handler Interface
5
Add Interface Guards
Module Discovery
Caddy provides functions to discover registered modules:modules.go:195-242
Best Practices
1
Always Use Pointers
Module constructors should return pointers:
2
Validate Configuration
Implement
Validator to catch configuration errors early:3
Clean Up Resources
Implement
CleanerUpper if your module allocates resources:4
Use Context Logger
Get a properly-configured logger from the context:
5
Add Interface Guards
Use compile-time interface guards to catch mistakes: