Skip to content

Middlewares

yusing edited this page Feb 18, 2025 · 22 revisions

Middlewares

Behaviors

Middleware names are case-insensitive and accept both snake_case, PascalCase and camelCase, e.g. redirectHTTP, redirect_http and RedirectHttp are equivalent.

Middleware execution is does not follow label order, you have to set priority manually, e.g.

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

Usage

Middlewares can be used in the following ways:

  • entrypoint middlewares

  • docker labels

  • route files

  • middleware compose - declare reusable middlewares with YAML files under config/middlewares

    # syntax
    <name>:
      - use: <middleware>
        <option1>: <value1>
        <option2>: <value2>
        ...
    
    # config/middlewares/whitelist.yml
    myWhitelist:
      - use: CloudflareRealIP
      - use: CIDRWhitelist
        allow:
          - 127.0.0.1
          - 223.0.0.0/8
    
    # Add them in your route
    # docker compose
    services:
      app:
        labels:
          proxy.#1.middlewares.myWhitelist@file:
    # route file
    app:
      middlewares:
        myWhitelist@file:
    # entrypoint
    entrypoint:
      middlewares:
        myWhitelist@file:

Examples

# docker compose - full namespace
labels:
  proxy.server.middlewares.redirect_http:
  proxy.server.middlewares.cidr_whitelist.allow: 127.0.0.1, 10.0.0.0/16

# docker compose - inline yaml
labels:
  proxy.server.middlewares: |
    redirect_http:
    cidr_whitelist:
      allow:
        - 127.0.0.1
        - 10.0.0.0/16

# config.yml
entrypoint:
  middlewares:
    - use: 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

🔼Back to top

Available middlewares

OIDC

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

Note: Do not use this middleware on entrypoint if your OIDC provider is proxied by GoDoxy itself.

# docker labels
proxy.app1.middlewares.oidc:

# with overrides
proxy.app1.middlewares.oidc.allowed_groups: admin
proxy.app1.middlewares.oidc.allowed_users: user1, user2

# route file
app1:
  middlewares:
    oidc:

Redirect http

Redirect http requests to https

# docker labels
proxy.app1.middlewares.redirect_http:

# route file
app1:
  middlewares:
    redirect_http:

nginx equivalent:

server {
  listen 80;
  server_name domain.tld;
  return 301 https://$host$request_uri;
}

🔼Back to top

Custom error pages

Please check Custom Error Pages

# docker labels
proxy.app1.middlewares.custom_error_page:

# route file
app1:
  middlewares:
    custom_error_page:

nginx equivalent:

location / {
  try_files $uri $uri/ /error_pages/404.html =404;
}

🔼Back to top

Real IP

This middleware is used for setting $remote_addr, $remote_host from real_ip.header (i.e.) X-Real-IP. Doing so will also change the IP address in access log.

Custom

# docker labels
proxy.app1.middlewares.real_ip.header: X-Real-IP
proxy.app1.middlewares.real_ip.from: |
  - 127.0.0.1
  - 192.168.0.0/16
  - 10.0.0.0/8
proxy.app1.middlewares.real_ip.recursive: true
# route file
app1:
  middlewares:
    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:

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;
}

🔼Back to top

Cloudflare

This is a preset for Cloudflare Tunnels. It will skip all local IPs.

# docker labels
proxy.app1.middlewares.cloudflare_real_ip:

# route file
app1:
  middlewares:
    cloudflare_real_ip:

🔼Back to top

CIDR Whitelist

# docker labels
proxy.app1.middlewares.cidr_whitelist: |
  allow:
    - 10.0.0.0/8
    - 192.168.0.0/16
  status_code: 403
  message: "IP not allowed"

# route file
app1:
  middlewares:
    cidr_whitelist:
      allow:
        - 10.0.0.0/8
        - 192.168.0.0/16
      status_code: 403 # default
      message: "IP not allowed" # default

Rate Limiter

average: average number of requests per period burst: maximum number of requests allowed in a period periods: time period in format number[unit]

# docker labels
proxy.app1.middlewares.ratelimit: |
  average: 100
  burst: 100
  periods: 1s

# route file
app1:
  middlewares:
    ratelimit:
      average: 100
      burst: 100
      periods: 1s

🔼Back to top

Modify request or response

In docker compose, you need double dollar signs $$ like $$req_method since single $ is treated as environment variables.

Supported variables

  • $req_method: request http method
  • $req_scheme: request URL scheme (http/https)
  • $req_host: request host without port
  • $req_port: request port
  • $req_addr: request host with port (if present)
  • $req_path: request URL path
  • $req_query: raw query string
  • $req_url: full request URL
  • $req_uri: request URI (encoded path?query)
  • $req_content_type: request Content-Type header
  • $req_content_length: length of request body (if present)
  • $remote_addr: client's remote address (may changed by middlewares like RealIP and CloudflareRealIP)
  • $remote_host: client's remote ip parse from $remote_addr
  • $remote_port: client's remote port parse from $remote_addr (may be empty)
  • $resp_content_type: response Content-Type header
  • $resp_content_length: length response body
  • $status_code: response status code
  • $upstream_name: upstream server name (alias)
  • $upstream_scheme: upstream server scheme
  • $upstream_host: upstream server host
  • $upstream_port: upstream server port
  • $upstream_addr: upstream server address with port (if present)
  • $upstream_url: full 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

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

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

nginx equivalent:

location / {
  add_header X-Custom-Header1 value1, value2;
  add_header X-Custom-Header2 value3;
}

Example use case (set X-Real-IP from remote IP):

# docker labels
proxy.app1.middlewares.request.set_headers: |
  X-Real-IP: $remote_host

🔼Back to top

Add headers

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

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

nginx equivalent:

location / {
  more_set_headers "X-Custom-Header1: value1, value2";
  more_set_headers "X-Custom-Header2: value3";
}

🔼Back to top

Hide headers

# docker labels
proxy.app1.middlewares.modify_request.hide_headers: |
  X-Custom-Header1
  X-Custom-Header2

# route file
app1:
  middlewares:
    modify_request:
      hide_headers:
        - X-Custom-Header1
        - X-Custom-Header2

nginx equivalent:

location / {
  more_clear_headers "X-Custom-Header1";
  more_clear_headers "X-Custom-Header2";
}

🔼Back to top

X-Forwarded-* Headers

Hide X-Forwarded-*

Remove Forwarded and X-Forwarded-* headers before request

# docker labels
proxy.app1.middlewares.hide_x_forwarded:

# route file
app1:
  middlewares:
    hide_x_forwarded:

Set X-Forwarded-*

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

# docker labels
proxy.app1.middlewares.set_x_forwarded:

# route file
app1:
  middlewares:
    set_x_forwarded:

🔼Back to top

Forward Authorization header (experimental)

Fields:

  • address: authentication provider URL (required)
  • trust_forward_header: whether to trust X-Forwarded-* headers from upstream proxies (default: false)
  • auth_response_headers: list of headers to copy from auth response (default: empty)
  • add_auth_cookies_to_response: list of cookies to add to response (default: empty)
# docker labels
proxy.app1.middlewares.forward_auth: |
  address: https://auth.example.com
  trust_forward_header: true
  auth_response_headers:
    - X-Auth-Token
    - X-Auth-User
  add_auth_cookies_to_response:
    - uid
    - session_id

# route file
app1:
  middlewares:
    forward_authorization:
      address: https://auth.example.com
      trust_forward_header: true
      auth_response_headers:
        - X-Auth-Token
        - X-Auth-User
      add_auth_cookies_to_response:
        - uid
        - session_id

Traefik equivalent:

traefik.http.middlewares.authentik.forwardauth.address: https://auth.example.com
traefik.http.middlewares.authentik.forwardauth.trustForwardHeader: true
traefik.http.middlewares.authentik.forwardauth.authResponseHeaders: X-Auth-Token, X-Auth-User
traefik.http.middlewares.authentik.forwardauth.addAuthCookiesToResponse: uid, session_id

🔼Back to top

Clone this wiki locally