vicarian 0.2.5

Vicarian is a reverse proxy server with ACME support
# Vicarian Configuration Documentation

Vicarian's configuration is defined in a [Corn](https://cornlang.dev) file, by
default in `/etc/vicarian/vicarian.corn`. This file defines how the proxy should
behave, including TLS settings, backend services, and routing.

## Basic Structure

A minimal Vicarian configuration file would look something like this:

```corn
{
    listen = {
        addrs = [
            "[::]"  // This covers IPv4 & IPv6
        ]
        insecure_port = 80 // Default
        tls_port = 443 // Default
    }

    vhosts = [
        {
            hostname = "example.com"

            tls = {
                acme = {
                    contact = "admin@example.com"
                    challenge.type = "http-01"
                }
            }

            backends = [
                {
                    context = "/"
                    url = "http://localhost:8080"
                }
                {
                    context = "/app2"
                    url = "https://localhost:8443"
                    trust = true
                }
                {
                    context = "/metrics"
                    url = "module://metrics"
                    auth_key = "secret_key"
                }
           ]
        }
    ]
}
```

## Configuration Fields

### listen (global)
- **Type**: Object
- **Optional**: Yes (uses default values if not specified)
- **Description**: Network listening configuration for the proxy.
- **Fields**:
  - addrs: The IP addresses to bind the server to (default: `"[::]"`), or
    interface name(s) prefixed with `if#`; e.g. `"if#eth0"`.
  - insecure_port: The HTTP port to listen on (default: 80)
  - tls_port: The HTTPS port to listen on (default: 443)

### vhosts
- **Type**: Array of objects
- **Required**: Yes
- **Description**: List of virtual hosts (domains) that this server will handle.

### hostname (within vhost)
- **Type**: String
- **Required**: Yes (within each vhost)
- **Description**: The primary hostname for this virtual host. Used for TLS certificate generation when using ACME.
- **Example**: `hostname = "example.com"`

### aliases (within vhost)
- **Type**: Array of strings
- **Default**: Empty array
- **Description**: Additional domain names that should be handled by this virtual host.
- **Example**: `aliases = ["www.example.com", "api.example.com"]`

### tls (within vhost)
- **Type**: Object
- **Required**: Yes (within each vhost)
- **Description**: TLS configuration for HTTPS connections for this virtual host.
- **Fields**:
  - acme: Configuration for ACME certificate provisioning
  - files: Configuration for using existing certificate files

### backends (within vhost)
- **Type**: Array of objects
- **Required**: Yes (within each vhost)
- **Description**: List of backend services that this virtual host will proxy requests to.
- **Fields**:
  - context: The URL path prefix this backend handles (default: "/")
  - url: The backend service URL
  - trust: Whether to skip certificate verification for TLS backends (default: false)
  - auth_key: If set, requires `Authorization: Bearer <key>` to access this backend. (optional)

## TLS Configuration

### TLS with Certificate Files

```corn
tls = {
  files = {
    keyfile = "/path/to/private.key"
    certfile = "/path/to/certificate.crt"
    reload = true
  }
}
```

**Fields**:
- keyfile: Path to the private key file (required)
- certfile: Path to the certificate file (required)
- reload: Whether to watch for changes and reload certificates (default: true)

### TLS with ACME HTTP provisioning

```corn
tls = {
  acme = {
    acme_provider = "letsencrypt"  // Default & only supported provider
    contact = "admin@example.com"
    challenge.type = "http-01"
    profile = "shortlived"  // or "tlsserver"
    directory = "/var/lib/vicarian/acme"  // Default
  }
}
```

**Fields**:
- acme_provider: ACME provider (default: "letsencrypt")
- contact: Email address for certificate notifications (required)
- challenge.type: Challenge type - "http-01" or "dns-01" (required)
- profile: Certificate profile - "shortlived" for short-lived certs, "tlsserver" for long-lived (default: "tlsserver")
- directory: Directory to store ACME account and certificate data (default: "/var/lib/vicarian/acme")

### TLS with ACME DNS provisioning

```corn
tls = {
  acme = {
    acme_provider = "letsencrypt"  // Default & only supported provider
    contact = "admin@example.com"
    challenge = {
      type = "dns-01"
      dns_provider = {
        name = "porkbun"
        key = $env_PORKBUN_KEY
        secret = $env_PORKBUN_SECRET
      }
    }
    profile = "tlsserver"
    wildcard = false
  }
}
```

**Fields**:
- acme_provider: ACME provider (default: "letsencrypt")
- contact: Email address for certificate notifications (required)
- challenge.type: Challenge type - must be "dns-01" for DNS challenges
- challenge.dns_provider: DNS provider configuration (required for DNS-01)
  - name: DNS provider name (e.g., "porkbun")
  - key: API key for the DNS provider
  - secret: API secret for the DNS provider
- profile: Certificate profile - "shortlived" or "tlsserver" (default: "tlsserver")
- wildcard: Whether to generate a wildcard certificate. (default: false)

## Backend Configuration

Each backend entry has the following fields:

### context
- **Type**: String
- **Default**: "/"
- **Description**: The URL path prefix that this backend will handle. For example, if `context = "/api"`, requests to `/api/endpoint` will be forwarded to the backend.

### url
- **Type**: String (URI)
- **Required**: Yes
- **Description**: The URL of the backend service to proxy requests to.

### trust
- **Type**: Boolean
- **Default**: false
- **Description**: Set to true if the backend uses a self-signed certificate or certificate that can't be verified by the system's CA store.

### auth_key
- **Type**: String
- **Default**: None
- **Description**: If set, Vicarian will require an `Authorization: Bearer <key>` header with the specified key to allow access to this backend.

## Special Backend Modules

Vicarian supports builtin backend modules that can be used in place of a standard URL. These are specified using the `module://` scheme.

### Metrics Module

The `metrics` module provides a Prometheus-compatible metrics endpoint.
See [METRICS.md](METRICS.md) for configuration details and available metrics.

```corn
backends = [
    {
        context = "/metrics"
        url = "module://metrics"
        auth_key = "secret_key" // Optional
    }
]
```

## Additional Configuration Options

### dev_mode (global)
- **Type**: Boolean
- **Default**: false
- **Description**: Enables development mode with relaxed security settings. This should not be used in production environments.

## Environment Variables

Configuration supports environment variable substitution using the `$env_VARIABLE_NAME` syntax. This allows sensitive information like API keys to be kept out of configuration files.

```corn
let {
    $env_PORKBUN_KEY = "fallback value"
    $env_PORKBUN_SECRET = "fallback value"

} in {
    // Configuration here can use $env_VARIABLE_NAME
}
```