Skip to main content
Caddy’s configuration is built on a modular architecture with a clear hierarchy. Understanding this structure helps you effectively configure and extend Caddy.

Architecture Overview

Caddy configuration follows a hierarchical structure:

Root Configuration

From caddy.go:46-95, the top-level Config struct:
The Config struct contains both JSON-encodable fields (exported with json tags) and internal runtime fields (unexported). Only JSON fields are configurable.

Module System

Caddy’s extensibility comes from its module system. Every feature is a module.

Module Namespaces

Modules are organized into namespaces:
  • caddy.storage.* - Storage backends
  • caddy.logging.writers.* - Log writers
  • caddy.logging.encoders.* - Log encoders
  • http.handlers.* - HTTP handlers
  • http.matchers.* - Request matchers
  • tls.issuance.* - Certificate issuers
  • tls.cert_managers.* - Certificate managers

Module Specification

Modules can be specified in two ways:
The module field names the module, other fields are module-specific.

App Lifecycle

From caddy.go:98-101, apps implement the App interface:

Provisioning and Startup

The lifecycle follows this sequence (caddy.go:403-468):
  1. Provision Context - Create execution environment
  2. Load Modules - Instantiate all modules
  3. Provision Modules - Call Provision() on each module
  4. Validate - Verify configuration correctness
  5. Start Apps - Call Start() on each app in order
  6. Finish Setup - Configure admin endpoints, config loaders
If any app fails to start, all previously-started apps are stopped to prevent partial states.

Configuration Layers

Layer 1: Native JSON

The foundational layer - Caddy’s internal representation:

Layer 2: Config Adapters

Adapters transform other formats to JSON:
From caddyconfig/caddyfile/adapter.go:26-64:

Layer 3: Admin API

Dynamic runtime configuration via HTTP API:

Storage Architecture

Caddy stores persistent data like TLS certificates:
Default storage locations:

Context and Modules

From context.go, every module receives a Context:
Modules use context to:
  • Load other modules via ctx.LoadModule()
  • Access configuration via ctx.cfg
  • Register cleanup via ctx.OnCancel()

Module Interface

Configuration Flow

HTTP App Structure

The HTTP app is the most complex:

Route Matching

Routes are evaluated in order until a terminal route matches:
  1. Match - Request matches all matchers (AND logic)
  2. Handle - Handlers process the request
  3. Terminal - Stop route evaluation if true

TLS App Structure

Configuration Reloads

From caddy.go:159-264, config changes are atomic:
  1. Decode new configuration
  2. Provision new config (instantiate modules)
  3. Validate new config
  4. Start new apps
  5. Swap to new config
  6. Stop old apps
  7. Cleanup old modules
Config reloads are zero-downtime. The old config keeps running until the new config is fully started and validated.

Auto-Save and Resume

From caddy.go:362-384, Caddy can persist configs:
Resume saved config:

Events System

From caddy.go:1065-1156, Caddy emits events:
Built-in events:
  • started - Emitted when config starts successfully
  • stopping - Emitted when shutdown begins
The events system is experimental and subject to change.

Best Practices

Structure Your Config

  1. Separate concerns - Use multiple apps appropriately
  2. Modularize - Break large configs into smaller pieces
  3. Use adapters - Write in the format that makes sense for your use case
  4. Validate early - Check configs before deploying
  5. Monitor changes - Track config changes in version control

Performance Considerations

  • Route order matters - Place common routes first
  • Use terminal routes - Stop evaluation when match is found
  • Minimize matchers - Fewer matchers = faster matching
  • Leverage caching - Enable TLS session resumption, HTTP caching

Security Considerations

  • Disable admin when not needed - Reduce attack surface
  • Use enforce_origin - Prevent CSRF on admin API
  • Validate TLS configs - Ensure strong cipher suites
  • Protect storage - Secure certificate storage with proper permissions

Debugging Configuration

View Current Config

Trace Config Loading

Validate Before Loading

See Also