Skip to content

v2.2.0

Choose a tag to compare

@gsmlg gsmlg released this 21 Jan 10:42
· 32 commits to main since this release

External Mode Implementation

This release introduces External Mode for managing Caddy instances that are started and controlled externally (e.g., via systemd, launchd, or other process managers).

New Features

Mode-Based Architecture

  • :embedded mode (default) - Caddy binary managed by this application
  • :external mode - Caddy managed externally, communicate via Admin API

Transport Abstraction

  • Support for both Unix domain sockets and TCP connections
  • URL parsing: unix:///path/to/sock and http://host:port
  • Seamless protocol switching without duplicating connection logic

External Server GenServer

  • Periodic health checks via Admin API
  • Execute system commands (start/stop/restart/status)
  • Automatic configuration push on first healthy check
  • Telemetry events for observability
  • Status change tracking and logging

Configuration Example

```elixir

External mode with systemd

config :caddy, mode: :external
config :caddy, admin_url: "http://localhost:2019"
config :caddy, health_interval: 30_000
config :caddy, commands: [
start: "systemctl start caddy",
stop: "systemctl stop caddy",
restart: "systemctl restart caddy",
status: "systemctl is-active caddy"
]
```

API Additions

Configuration Module

  • Config.mode() - Get operating mode
  • Config.external_mode?() - Check if external mode
  • Config.admin_url() - Get Admin API URL
  • Config.commands() - Get system commands
  • Config.command(name) - Get specific command
  • Config.health_interval() - Get health check interval

Server Module

  • Server.check_status() - Check server status
  • Server.execute_command(cmd) - Execute lifecycle command
  • Caddy.Server.External.* - External mode GenServer API

Telemetry

  • New external mode events: :init, :health_check, :command_executed, :config_pushed, :status_changed, :terminate
  • Telemetry.emit_external_event(type, measurements, metadata)

Breaking Changes

None - backward compatible with existing embedded mode (default).

Migration

No changes needed for existing users. To use external mode, simply set configuration:

```elixir
config :caddy, mode: :external
config :caddy, admin_url: "http://localhost:2019"
```

Testing

All 181 existing tests pass. Added comprehensive test coverage for:

  • Transport URL parsing and connection
  • External server health checks
  • Command execution

Commits Included

  • feat(config): add external mode configuration accessors
  • feat(admin): add Transport abstraction for Unix and TCP
  • refactor(admin): use Transport abstraction in Request module
  • refactor(server): extract embedded mode to Caddy.Server.Embedded
  • feat(server): add external mode GenServer
  • refactor(server): add mode-based delegation to Caddy.Server
  • test: add tests for Transport and External server modules