Skip to content

Caddyfile Configuration

Complete Caddyfile configuration reference for the Productify Proxy.

Basic Structure

nginx
{
  # Global options block
  security {
    # OAuth2/OIDC configuration
  }
  productify {
    # Manager integration
  }
}

site.com {
  # Site-specific configuration
}

Global Options

nginx
{
  # Admin API
  admin off  # Disable admin API (production)
  # admin :2019  # Enable on port 2019

  # Email for Let's Encrypt
  email admin@example.com

  # Auto HTTPS
  auto_https on  # Enable automatic HTTPS
  # auto_https off  # Disable for local dev

  # Default SNI
  default_sni example.com

  # Grace period for config changes
  grace_period 10s
}

Security Configuration

OAuth2 Identity Provider

nginx
{
  security {
    oauth identity provider generic {
      delay_start 1
      retry_attempts 3
      retry_interval 2
      realm generic
      driver generic
      client_id ab098fe1-9bc0-4780-81c6-2ea17f49a3cb
      client_secret pU3ZrOyPTtd4A3ex16dBzBTlDrlxqfpU
      scopes openid email profile
      base_auth_url http://pocketid.localhost
      metadata_url http://pocketid.localhost/.well-known/openid-configuration
    }
  }
}

Authentication Portal

nginx
{
  security {
    authentication portal pocketportal {
      crypto default token lifetime 3600
      enable identity provider generic
      cookie insecure on  # Only for local dev!

      transform user {
        match realm generic
        action add role user
      }
    }
  }
}

Authorization Policy

nginx
{
  security {
    authorization policy pocketpolicy {
      set auth url /auth/oauth2/generic
      allow roles user
      validate bearer header
      inject headers with claims
      enable strip token
    }
  }
}

Productify Manager Integration

Configure the Productify plugin to communicate with the Manager API:

nginx
{
  productify {
    manager http://172.17.0.1:8080
    token supersecrettoken
    enable_access_log      # Enable detailed access logging
    enable_metrics         # Enable request count and response time metrics
    enable_size_metrics    # Enable request/response size metrics
  }
}

Configuration Options

OptionTypeRequiredDescription
managerstringYesURL of the Productify Manager API
tokenstringYesAuthentication token for Manager API
enable_access_logflagNoEnable structured access logging
enable_metricsflagNoEnable Prometheus metrics
enable_size_metricsflagNoEnable request/response size metrics

Monitoring Options:

  • enable_access_log: Logs every request with source IP, user, user agent, target system, method, path, and timestamp
  • enable_metrics: Exposes Prometheus metrics for request count and response time on :2112/metrics
  • enable_size_metrics: Adds request and response size metrics (requires enable_metrics)

See Monitoring & Logging for detailed information about metrics and logs.

Application Routing

Single Application

nginx
http://app.localhost {
  @auth {
    path /auth/*
  }

  route @auth {
    productify_before_auth with 123
    authenticate with pocketportal
  }

  route /* {
    authorize with pocketpolicy
    productify with 123
    reverse_proxy backend:8080
  }
}

Multiple Applications

nginx
http://app1.localhost {
  route /* {
    authorize with pocketpolicy
    productify with 100
    reverse_proxy app1:8080
  }
}

http://app2.localhost {
  route /* {
    authorize with pocketpolicy
    productify with 200
    reverse_proxy app2:8080
  }
}

Path-Based Routing

nginx
apps.productify.dev {
  route /app1/* {
    authorize with pocketpolicy
    productify with 100
    uri strip_prefix /app1
    reverse_proxy app1:8080
  }

  route /app2/* {
    authorize with pocketpolicy
    productify with 200
    uri strip_prefix /app2
    reverse_proxy app2:8080
  }
}

Manager Integration

nginx
manager.productify.dev {
  @auth {
    path /auth/*
  }

  route @auth {
    authenticate with pocketportal
  }

  route /* {
    authorize with pocketpolicy
    reverse_proxy manager:8080
  }
}

} }


## Load Balancing

### Round Robin

```nginx
app.example.com {
  reverse_proxy backend1:8080 backend2:8080 backend3:8080 {
    lb_policy round_robin
  }
}

Least Connections

nginx
app.example.com {
  reverse_proxy backend1:8080 backend2:8080 {
    lb_policy least_conn
  }
}

IP Hash

nginx
app.example.com {
  reverse_proxy backend1:8080 backend2:8080 {
    lb_policy ip_hash
  }
}

Health Checks

nginx
app.example.com {
  reverse_proxy backend1:8080 backend2:8080 {
    # Health check configuration
    health_uri /health
    health_interval 10s
    health_timeout 5s
    health_status 200

    # Fail threshold
    fail_duration 30s
    max_fails 3
    unhealthy_status 503
  }
}

TLS Configuration

Automatic HTTPS

nginx
{
  email admin@example.com
}

example.com {
  # Caddy automatically obtains and renews certificates
  reverse_proxy backend:8080
}

Custom Certificates

nginx
example.com {
  tls /path/to/cert.pem /path/to/key.pem
  reverse_proxy backend:8080
}

TLS Client Authentication

nginx
example.com {
  tls {
    client_auth {
      mode require_and_verify
      trusted_ca_cert_file /path/to/ca.pem
    }
  }
  reverse_proxy backend:8080
}

Authentication

Basic Auth

nginx
admin.example.com {
  basicauth {
    admin $2a$14$...  # bcrypt hash
  }
  reverse_proxy backend:8080
}

OAuth2 Authentication

nginx
app.example.com {
  @auth {
    path /auth/*
  }

  route @auth {
    authenticate with pocketportal
  }

  route /* {
    authorize with pocketpolicy
    reverse_proxy backend:8080
  }
}

Bearer Token Validation

nginx
api.example.com {
  route /api/* {
    # Policy validates bearer header
    authorize with pocketpolicy
    reverse_proxy backend:8080
  }
}

Headers

Security Headers

nginx
example.com {
  header {
    # Security headers
    Strict-Transport-Security "max-age=31536000; includeSubDomains"
    X-Content-Type-Options "nosniff"
    X-Frame-Options "DENY"
    X-XSS-Protection "1; mode=block"

    # Remove server header
    -Server
  }
  reverse_proxy backend:8080
}

CORS Headers

nginx
api.example.com {
  header {
    Access-Control-Allow-Origin "https://app.example.com"
    Access-Control-Allow-Methods "GET, POST, PUT, DELETE"
    Access-Control-Allow-Headers "Content-Type, Authorization"
  }
  reverse_proxy backend:8080
}

Logging

Access Logs

nginx
{
  log {
    output file /var/log/caddy/access.log {
      roll_size 100mb
      roll_keep 10
      roll_keep_for 30d
    }
    format json
    level info
  }
}

Per-Site Logging

nginx
example.com {
  log {
    output file /var/log/caddy/example.log
    format json
  }
  reverse_proxy backend:8080
}

Complete Example

nginx
{
  email admin@productify.dev
  admin off

  security {
    oauth identity provider generic {
      realm generic
      driver generic
      client_id ab098fe1-9bc0-4780-81c6-2ea17f49a3cb
      client_secret pU3ZrOyPTtd4A3ex16dBzBTlDrlxqfpU
      scopes openid email profile
      base_auth_url http://pocketid.localhost
      metadata_url http://pocketid.localhost/.well-known/openid-configuration
    }

    authentication portal pocketportal {
      crypto default token lifetime 3600
      enable identity provider generic
      cookie insecure on

      transform user {
        match realm generic
        action add role user
      }
    }

    authorization policy pocketpolicy {
      set auth url /auth/oauth2/generic
      allow roles user
      validate bearer header
      inject headers with claims
      enable strip token
    }
  }

  productify {
    manager http://172.17.0.1:8080
    token supersecrettoken
  }

  log {
    output file /var/log/caddy/access.log
    format json
  }
}

# Identity Provider
http://pocketid.localhost {
  reverse_proxy pocketid:1411
}

# Application with authentication
http://app.localhost {
  @auth {
    path /auth/*
  }

  route @auth {
    productify_before_auth with 123
    authenticate with pocketportal
  }

  route /* {
    authorize with pocketpolicy
    productify with 123
    file_server {
      root /usr/share/caddy
      browse
    }
  }

  log {
    output file /var/log/caddy/app.log
  }
}

# Manager UI/API
http://manager.localhost {
  @auth {
    path /auth/*
  }

  route @auth {
    authenticate with pocketportal
  }

  route /* {
    authorize with pocketpolicy
    reverse_proxy 172.17.0.1:8080
  }

  log {
    output file /var/log/caddy/manager.log
  }
}

See Also