Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/fuomag9/caddy-proxy-manager/llms.txt

Use this file to discover all available pages before exploring further.

Caddy Proxy Manager runs as a Docker Compose stack that bundles Caddy Server, the dashboard, and optional analytics and geo-IP services. This guide walks you through cloning the repository, configuring your environment, starting the stack, and creating your first proxy host with automatic HTTPS.

Prerequisites

Before you begin, make sure you have:
  • Docker Engine 24+ and Docker Compose v2 installed (docker compose version should show v2.x)
  • Ports 80 and 443 available on the host (required for Let’s Encrypt HTTP-01 challenge and HTTPS traffic)
  • Port 3000 available for the dashboard
  • A domain name with a DNS A record pointing to your server if you want automatic HTTPS certificates

Deploy with Docker Compose

1

Clone and configure

Clone the repository and copy the example environment file:
git clone https://github.com/fuomag9/caddy-proxy-manager.git
cd caddy-proxy-manager
cp .env.example .env
Open .env and set the following required variables:
VariableDescription
SESSION_SECRET32-character random string used to encrypt sessions
ADMIN_USERNAMEUsername for the initial admin account
ADMIN_PASSWORDPassword for the initial admin account (12+ chars, mixed case, numbers, special chars)
BASE_URLPublic URL where users access the dashboard (e.g. https://caddy-manager.example.com)
Generate a secure SESSION_SECRET with:
openssl rand -base64 32
A minimal production .env looks like:
SESSION_SECRET=<output from openssl>
ADMIN_USERNAME=admin
ADMIN_PASSWORD=YourStr0ng-P@ssw0rd123!
BASE_URL=https://caddy-manager.example.com
Set SESSION_SECRET and ADMIN_PASSWORD to strong, unique values before starting the stack. The application requires a 32-character minimum session secret and a 12-character minimum password with mixed case, numbers, and special characters in production.
Restrict file permissions on .env to prevent other users from reading your credentials:
chmod 600 .env
2

Start the stack

Start all services in detached mode:
docker compose up -d
Docker will pull the required images and start the web, caddy, docker-socket-proxy, and l4-port-manager containers. Wait for the health checks to pass — this takes about 40 seconds on first start.Check that all containers are running:
docker compose ps
Access the dashboard at http://localhost:3000/login (or your BASE_URL if set).
To also start the ClickHouse analytics database, set COMPOSE_PROFILES=clickhouse in your .env and add CLICKHOUSE_PASSWORD before running docker compose up -d. See Enable analytics below.
3

Log in

Open http://localhost:3000/login in your browser. Enter the ADMIN_USERNAME and ADMIN_PASSWORD values you set in .env.On first login, CPM creates the admin account from those environment variables. Subsequent changes to the credentials in .env do not update the stored account — use the User Management page to change the password after the initial setup.
4

Create your first proxy host

  1. In the sidebar, click Proxy Hosts.
  2. Click Add Proxy Host.
  3. Fill in the Domain field with your public hostname (e.g. app.example.com).
  4. Set the Upstream URL to your backend service (e.g. http://192.168.1.10:8080).
  5. Under SSL, enable Automatic HTTPS — Caddy will obtain a Let’s Encrypt certificate for the domain automatically.
  6. Click Save.
CPM sends the configuration to Caddy’s Admin API. Caddy begins the ACME challenge immediately and serves HTTPS traffic once the certificate is issued, typically within a few seconds.
Automatic HTTPS requires that the domain resolves to your server’s public IP and that port 80 is reachable from the internet so Let’s Encrypt can complete the HTTP-01 challenge.

Enable analytics (optional)

Analytics requires the ClickHouse service, which is activated via the clickhouse Docker Compose profile. Add the following to your .env:
COMPOSE_PROFILES=clickhouse
CLICKHOUSE_PASSWORD=your-clickhouse-password   # openssl rand -base64 32
Then restart the stack:
docker compose up -d
ClickHouse starts automatically and CPM connects to it. Traffic events and WAF events are stored with a 90-day TTL. The Analytics page in the dashboard shows live charts and event logs once data starts flowing. To disable analytics, remove clickhouse from COMPOSE_PROFILES (or leave the variable empty) and omit CLICKHOUSE_PASSWORD.

Enable geo IP updates (optional)

Geo blocking requires MaxMind GeoLite2 databases. The bundled geoipupdate service downloads and refreshes them automatically every 72 hours.
  1. Register for a free MaxMind account at maxmind.com.
  2. Generate a license key with GeoLite2-Country and GeoLite2-ASN edition permissions.
  3. Add the following to your .env:
    GEOIPUPDATE_ACCOUNT_ID=your-account-id
    GEOIPUPDATE_LICENSE_KEY=your-license-key
    
  4. Add geoipupdate to COMPOSE_PROFILES:
    # Enable both analytics and geo IP updates
    COMPOSE_PROFILES=clickhouse,geoipupdate
    
  5. Restart the stack:
    docker compose up -d
    
The databases are stored in the geoip-data Docker volume and are shared between the web and caddy containers. Geo blocking rules become available immediately after the first download completes.

What’s next

Configuration

Full reference for every environment variable and Docker Compose volume in the stack.

Proxy hosts

Configure load balancing, custom headers, location rules, and health checks.

Certificates

Set up DNS-01 challenge, import custom certificates, and issue mTLS client certs.

Web Application Firewall

Enable OWASP CRS protection, suppress rules, and write custom SecLang directives.

Build docs developers (and LLMs) love