Skip to content

Usage

MXProxy is configured through Docker labels. Each label defines a directive, which can contain a value, multiple entries, or additional configuration through subdirectives.

Directives

Basic syntax

The basic syntax is key: value.

labels:
  reverse_proxy: example.com -> 8080

This initializes the reverse_proxy directive with the value example.com -> 8080.

Multiple directives

You can initialize multiple instances of the same directive by using a multiline value:

labels:
  reverse_proxy: |
    example.com -> 8080
    api.example.com -> 8081

Each non-empty line initializes a separate reverse_proxy directive.

Subdirectives

Use key.sub: value to call a subdirective named sub on a previously initialized directive or group.

For example:

labels:
  reverse_proxy: example.com -> 8080
  reverse_proxy.headers: "> X-Managed-By mxproxy"

Here, headers is a subdirective of reverse_proxy. It configures an additional header rule for the reverse proxy.

A subdirective requires its parent directive or group to exist.

Named groups

You can assign a name to a group by using key/name: value.

For example:

labels:
  reverse_proxy/site: |
    example.com -> 8080
    api.example.com -> 8081

  reverse_proxy/site.headers: "> X-Managed-By site"

The site group contains both reverse proxies. The reverse_proxy/site.headers subdirective applies the header rule to both of them.

You can use any group name you like.

The default group

The regular key syntax works exactly like a named group, but uses the default group.

For example:

labels:
  reverse_proxy: |
    example.com -> 8080
    api.example.com -> 8081

  reverse_proxy.headers: "> X-Managed-By default"

  reverse_proxy/site: |
    docs.example.com -> 8082
    status.example.com -> 8083

  reverse_proxy/site.headers: "> X-Managed-By site"

The reverse_proxy.headers subdirective applies to the default group. The reverse_proxy/site.headers subdirective applies only to the site group.

The default group is separate from all named groups. They don't share directives or subdirective configuration with one another.

Environment variables

MXProxy supports environment-variable references throughout its configuration. This lets you use secrets and other environment-specific values without inserting their actual values into generated configuration files.

There are two ways to reference an environment variable.

Use $${VARIABLE}

When using Docker Compose labels, prefix the variable with an extra $:

labels:
  cloudflare: $${API_KEY}

Docker Compose preserves the variable reference instead of interpolating its value. MXProxy recognizes the reference and converts it into {env.API_KEY} in the generated Caddy configuration.

Use {env.VARIABLE} directly

You can also reference an environment variable directly:

labels:
  cloudflare: "{env.API_KEY}"

Both syntaxes have the same effect.

Make variables available to MXProxy

The variable must be available in the MXProxy container's environment, not just in the container carrying the label.

For example, if your .env file contains the API token, pass it to MXProxy using env_file:

services:
  mxproxy:
    image: malasaur/mxproxy:0.2
    env_file:
      - .env

  my-app:
    image: your-app-image
    networks: [mxproxy]
    labels:
      cloudflare: $${API_KEY}

The .env file alone does not automatically pass all its variables into the MXProxy container. The env_file entry does that.

Warning

Avoid using ${VARIABLE} directly in a label when the value is a secret.

Docker Compose interpolates ${VARIABLE} before MXProxy receives the label. MXProxy may then generate a Caddyfile containing the secret itself, rather than an environment-variable reference. This leaves the secret in generated configuration files instead of resolving it from the environment at runtime.

Use $${VARIABLE} or {env.VARIABLE} to preserve the reference.

Custom Caddyfiles

MXProxy also lets you provide custom Caddy configuration through the /custom directory. This is useful when you need configuration beyond the built-in directives.

Mount a directory from the host into /custom:

services:
  mxproxy:
    volumes:
      - ./custom:/custom

You can also mount individual files:

services:
  mxproxy:
    volumes:
      - /srv/Caddyfile:/custom/srv.caddy

MXProxy automatically imports files from this directory:

  • .caddy files are imported as regular Caddy configuration.
  • .global files are imported inside the global options block.

Example

Create custom/example.caddy:

example.com {
    reverse_proxy dockerhost:8080
}

This proxies requests to port 8080 on the Docker host.

For dockerhost to work, the MXProxy container must have this entry in its Compose configuration:

extra_hosts:
  - "dockerhost:host-gateway"

The default MXProxy Compose configuration already includes it.

Warning

dockerhost is not the same as localhost.

Inside the MXProxy container, localhost and 127.0.0.1 refer to the MXProxy container itself, not the Docker host.

A service running on the host must listen on an address reachable through the Docker host gateway.

Automatic reloads

MXProxy watches the /custom directory and reloads the proxy when a .caddy or .global file changes.

You can edit a mounted configuration file without restarting MXProxy:

$EDITOR custom/example.caddy

The reload occurs automatically once the file stops changing.

Note

MXProxy watches files inside the existing /custom mount. If you change the Docker Compose configuration itself, such as adding the mount for the first time, you still need to recreate the MXProxy container.