# How Caddy is Integrated as a Reverse Proxy in agentsview

> Learn how agentsview integrates Caddy as a reverse proxy. Discover dynamic Caddyfile generation, validation, and child process management that tightly couples Caddy's lifecycle with the Go backend for seamless operation.

- Repository: [Kenn Software/agentsview](https://github.com/kenn-io/agentsview)
- Tags: how-to-guide
- Published: 2026-06-20

---

**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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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:

```bash
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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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`](https://github.com/kenn-io/agentsview/blob/main/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.