Skip to content

Middlewares

Usage

Middlewares can be used in several ways:

  • Entrypoint (ordered)
  • Middleware Compose (ordered) - reusable middlewares YAML files under config/middlewares
  • Docker labels (unordered)
  • Route files (unordered)

For unordered middlewares, you have to set priority manually when order matters

yaml
services:
  app:
    ...
    labels:
      proxy.aliases: myapp
      proxy.myapp.middlewares.redirectHTTP.priority: 1
      proxy.myapp.middlewares.cidrWhiteList.priority: 2
      proxy.myapp.middlewares.cidrWhiteList.allow: 127.0.0.1, 10.0.0.0/16

Middleware name and properties are case-insensitive and accept snake_case, PascalCase or camelCase

redirectHTTP, redirect_http and RedirectHttp are equivalent.

Syntax

Middleware Compose and Entrypoint Middleware

yaml
# middleware compose / entrypoint middleware syntax
<name>:
  - use: {middleware}
    {option1}: {value1}
    {option2}: {value2}
    ...

# middleware compose
# config/middlewares/whitelist.yml
myWhitelist:
  - use: CloudflareRealIP
  - use: CIDRWhitelist
    allow:
      - 127.0.0.1
      - 223.0.0.0/8

# config/config.yml
entrypoint:
  middlewares:
    - use: CloudflareRealIP
    - use: CIDRWhitelist
      allow:
        - 127.0.0.1
        - 223.0.0.0/8

Docker Labels and Route Files

yaml
# docker labels
proxy.#1.middlewares.{middlewareName}.{optionName}: { value }
proxy.#1.middlewares.{middlewareName}.{optionName2}: { value2 }

# docker labels (yaml style)
proxy.#1.middlewares.{middlewareName}: |
  {optionName}: {value}
  {optionName2}: {value2}

# route file
myapp:
  middlewares:
    { middlewareName }:
      { optionName }: { value }
      { optionName2 }: { value2 }

Reusing Middleware Compose Objects

yaml
# docker compose
services:
  app:
    labels:
      proxy.#1.middlewares.myWhitelist@file:

# route file
myapp:
  middlewares:
    myWhitelist@file:

# entrypoint in config.yml
entrypoint:
  middlewares:
    - use: myWhitelist@file

Examples

yaml
# config.yml
entrypoint:
  middlewares:
    - use: cidr_whitelist
      allow:
        - 127.0.0.1
        - 10.0.0.0/16

# docker labels (yaml style)
proxy.#1.middlewares.cidr_whitelist.allow: |
  - 127.0.0.1
  - 10.0.0.0/16

# single line comma separated
proxy.#1.middlewares.cidr_whitelist.allow: 127.0.0.1, 10.0.0.0/16

# route file
openai:
  host: https://api.openai.com/
  middlewares:
    cidr_whitelist:
      allow:
        - 127.0.0.1
        - 10.0.0.0/16
    modify_request:
      set_headers:
        Host: api.openai.com
  homepage:
    show: false

Available middlewares

OIDC

Name: oidc

OIDC uses the settings from .env file, with configurable overrides.

NOTE

DO NOT use this middleware on entrypoint

yaml
# config.yml
# DO NOT use this
entrypoint:
  middlewares:
    - use: oidc
OptionDescriptionDefaultRequired
allowed_usersOverride allowed usersGODOXY_OIDC_ALLOWED_USERSNo
allowed_groupsOverride allowed groupsGODOXY_OIDC_ALLOWED_GROUPSNo

hCaptcha

Name: hcaptcha

Protects against bots by solving a hCaptcha challenge.

OptionDescriptionDefaultRequired
site_keyhCaptcha site keyYes
secret_keyhCaptcha secret keyYes
session_expirySession expiry time24hNo

Redirect http

Name: redirect_http

Redirect http requests to https

Custom error pages

See Custom Error Pages

Real IP

Name: real_ip

NOTE

This middleware is used for resolving the correct client IP from real_ip.header (e.g. X-Real-IP)

This affects:

  • $remote_addr and $remote_host
  • IP in the access log
  • CIDRWhitelist Middleware

Recommended to use on entrypoint

OptionDescriptionDefaultRequired
headerReal IP headerX-Real-IPNo
fromList of trusted CIDRsYes
recursiveRecursive modetrueNo
Recursive modeDescription
trueChoose the first IP that does not match the from list
falseChoose the last IP that does not match the from list

Example:

  • X-Forwarded-For: 1.2.3.4, 192.168.0.123, 10.0.0.123
  • from: 192.168.0.0/16
Recursive modeResult
true1.2.3.4
false10.0.0.123
yaml
# entrypoint
entrypoint:
  middlewares:
    - use: real_ip
      header: X-Real-IP
      from:
        - 127.0.0.1
        - 192.168.0.0/16
        - 10.0.0.0/8
      recursive: true

nginx equivalent:

nginx
location / {
  set_real_ip_from 127.0.0.1;
  set_real_ip_from 192.168.0.0/16;
  set_real_ip_from 10.0.0.0/8;

  real_ip_header    X-Real-IP;
  real_ip_recursive on;
}

Cloudflare Real IP

Name: cloudflare_real_ip

NOTE

This middleware requires no additional configuration.

It is a preset of Real IP for Cloudflare Proxy/Tunnels. It will skip all local IPs.

Preset Values

OptionDescription
headerCF-Connecting-IP
fromList of Cloudflare IPs from (updated hourly)
recursivetrue

Trusted IPs:

CIDR Whitelist

Name: cidr_whitelist

See Request Level Access Control

Rate Limiter

Name: rate_limit

OptionDescriptionDefaultRequired
averageAverage requests per periodYes
burstMaximum number of requests allowed in a periodYes
periodsTime period in format number[unit]1sNo

Modify request or response

Names:

  • modify_request or request
  • modify_response or response
OptionDescriptionDefaultRequired
set_headersSet headersNo
add_headersAdd headersNo
hide_headersHide headersNo
add_prefixAdd prefix to pathNo

Supported variables

NOTE

To use variables, add $ ($$ for docker compose) before the variable name.

Single $ in docker compose is treated as environment variables.

VariableDescription
req_methodrequest http method
req_schemerequest URL scheme (http/https)
req_hostrequest host without port
req_portrequest port
req_addrrequest host with port (if present)
req_pathrequest URL path
req_queryraw query string
req_urlfull request URL
req_urirequest URI (encoded path?query)
req_content_typerequest Content Type header
req_content_lengthlength of request body (if present)
remote_addrclient's remote address (may changed by middlewares like RealIP and CloudflareRealIP)
remote_hostclient's remote ip parse from remote_addr
remote_portclient's remote port parse from remote_addr (may be empty)
resp_content_typeresponse Content Type header
resp_content_lengthlength response body
status_coderesponse status code
upstream_nameupstream server name (alias)
upstream_schemeupstream server scheme
upstream_hostupstream server host
upstream_portupstream server port
upstream_addrupstream server address with port (if present)
upstream_urlfull upstream server URL
header(name)get request header by name
resp_header(name)get response header by name
arg(name)get URL query parameter by name

Set headers

yaml
# docker labels
proxy.myapp.middlewares.request.set_headers: |
  X-Custom-Header1: value1, value2
  X-Real-IP: $$remote_host

# route file
myapp:
  middlewares:
    request:
      set_headers:
        X-Custom-Header1: value1, value2
        X-Real-IP: $remote_host

Add headers

yaml
# docker labels
proxy.myapp.middlewares.request.add_headers: |
  X-Custom-Header1: value1, value2
  X-Custom-Header2: value3

# route file
myapp:
  middlewares:
    request:
      add_headers:
        X-Custom-Header1: value1, value2
        X-Custom-Header2: value3

Hide headers

yaml
# docker labels
proxy.myapp.middlewares.request.hide_headers: |
  X-Custom-Header1
  X-Custom-Header2

# route file
myapp:
  middlewares:
    request:
      hide_headers:
        - X-Custom-Header1
        - X-Custom-Header2
nginx equivalents
nginx
location / {
  add_header X-Custom-Header1 value1, value2;
  more_set_headers "X-Custom-Header1: value1, value2";
  more_set_headers "X-Custom-Header2: value3";
  more_clear_headers "X-Custom-Header1";
  more_clear_headers "X-Custom-Header2";
}

X-Forwarded Headers

Hide X-Forwarded Headers

Name: hide_x_forwarded

Remove Forwarded and X-Forwarded-* headers before request

yaml
# docker labels
proxy.myapp.middlewares.hide_x_forwarded:

# route file
myapp:
  middlewares:
    hide_x_forwarded:

Set X-Forwarded Headers

Name: set_x_forwarded

Replace existing X-Forwarded-* headers with GoDoxy provided headers

yaml
# docker labels
proxy.myapp.middlewares.set_x_forwarded:

# route file
myapp:
  middlewares:
    set_x_forwarded:

Released under the MIT License.