How Caddy is Integrated as a Reverse Proxy in agentsview

agentsview embeds Caddy as a managed reverse proxy by dynamically generating a Caddyfile, validating the configuration, and spawning Caddy as a child process that forwards public traffic to an internal Go backend, with both lifecycles tightly coupled for automatic shutdown coordination.

The kenn-io/agentsview repository implements a sophisticated reverse proxy integration using the Caddy web server. When you enable managed proxy mode, the application programmatically orchestrates Caddy to handle TLS termination and public traffic forwarding while keeping the Go server bound to a local loopback address. This architecture ensures secure, automated HTTPS management without requiring manual Caddy configuration files.

Configuration and Validation

Detecting Proxy Mode

In cmd/agentsview/serve_runtime.go (lines 90-94), the serve runtime checks cfg.Proxy.Mode to determine whether to invoke the managed Caddy workflow. When this value equals "caddy", the application calls startManagedCaddy to begin the proxy initialization sequence.

Validating the Configuration

Before generating any configuration files, validateServeConfig in cmd/agentsview/managed_caddy.go (lines 65-71) performs strict validation. It confirms the binary path exists at cfg.Proxy.Bin, verifies the bind host is restricted to loopback addresses (unless AllowedSubnets is explicitly configured), and ensures TLS certificate paths are provided when HTTPS is enabled.

Dynamic Caddyfile Generation

Building the Reverse Proxy Configuration

The buildManagedCaddyfile function (lines 71-80 in managed_caddy.go) constructs a minimal Caddyfile programmatically. This configuration disables the admin API, sets up the public listener, and configures the reverse_proxy directive to point to the agentsview backend address (e.g., 127.0.0.1:8080). Optional TLS parameters are included when certificate paths are specified.

Writing and Validating the Caddyfile

The generated configuration is written to <data-dir>/managed-caddy/caddy/Caddyfile (lines 96-100). Before launching the process, agentsview executes caddy validate --config <path> --adapter caddyfile (lines 103-119) to catch syntax errors. If validation fails, startup aborts immediately with a descriptive error, preventing misconfigured proxy instances from launching.

Process Lifecycle and Monitoring

Spawning the Caddy Process

Once validation passes, agentsview uses exec.CommandContext to spawn the Caddy process with caddy run --config <path> --adapter caddyfile (lines 121-131 in managed_caddy.go). The process stdout and stderr are attached to the parent’s stderr for unified logging. This occurs after the Go server starts listening on its loopback port.

Windows-Specific Process Guarding

For Windows deployments, the newCaddyGuard function (lines 136-144) creates a job object that automatically terminates the Caddy process if the parent agentsview process exits unexpectedly. On Linux and macOS, this function is a no-op, relying instead on standard process group signaling for cleanup.

Readiness and Shutdown Coordination

The runtime implements bidirectional health monitoring. After starting both services, waitForLocalPort in serve_runtime.go (lines 75-83) probes the backend port to confirm the Go server is ready, then waits for the Caddy public bind port. If either process exits unexpectedly, the shutdown logic in lines 124-150 triggers caddy.Stop() and srv.Shutdown to prevent orphaned proxy processes.

Practical Usage Example

To deploy with the managed Caddy reverse proxy, specify the proxy mode and certificate paths via CLI flags:

agentsview serve \
  --proxy-mode=caddy \
  --proxy-bin=/usr/local/bin/caddy \
  --public-url=https://myhost.example.com \
  --proxy-bind-host=127.0.0.1 \
  --proxy-tls-cert=/path/to/cert.pem \
  --proxy-tls-key=/path/to/key.pem

This workflow:

  1. Binds the agentsview Go server to 127.0.0.1:8080 (or similar loopback port).
  2. Generates a Caddyfile directing Caddy to listen on https://myhost.example.com with the provided TLS certificates.
  3. Configures the reverse_proxy directive to forward all traffic to the internal loopback address.
  4. Monitors both processes, ensuring Caddy terminates automatically if the application shuts down.

Summary

  • Configuration-driven activation: The integration activates when cfg.Proxy.Mode is set to "caddy", triggering validation in managed_caddy.go.
  • Programmatic Caddyfile generation: agentsview builds and validates a temporary Caddyfile at runtime, storing it in <data-dir>/managed-caddy/caddy/.
  • Child process management: Caddy runs as a managed subprocess with exec.CommandContext, with Windows-specific job object guarding to prevent orphans.
  • Lifecycle coupling: Bidirectional monitoring ensures both the Go server and Caddy proxy shut down together if either fails, implemented in serve_runtime.go.

Frequently Asked Questions

What triggers the managed Caddy reverse proxy integration to start?

The integration activates when the configuration field cfg.Proxy.Mode equals "caddy", detected in cmd/agentsview/serve_runtime.go (lines 90-94). This triggers the startManagedCaddy function, which validates settings, generates the Caddyfile, and spawns the process.

Where does agentsview store the generated Caddyfile?

agentsview writes the generated Caddyfile to <data-dir>/managed-caddy/caddy/Caddyfile, as implemented in cmd/agentsview/managed_caddy.go (lines 96-100). The data directory path depends on your operating system and agentsview configuration.

How does agentsview prevent configuration errors from crashing the proxy?

Before starting Caddy, agentsview runs caddy validate --config <path> --adapter caddyfile (lines 103-119 in managed_caddy.go). If the generated Caddyfile contains syntax errors or invalid directives, the validation fails and agentsview aborts startup with an error message, preventing the launch of a misconfigured proxy.

What happens if the Caddy process crashes while agentsview is running?

The serve runtime in cmd/agentsview/serve_runtime.go (lines 124-150) monitors both processes. If Caddy exits unexpectedly, the shutdown coordinator triggers srv.Shutdown to stop the Go server cleanly, ensuring no orphaned backend remains accessible without the proxy layer.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →