Skip to content

Middlewares

yusing edited this page Feb 19, 2025 · 22 revisions

Middlewares

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

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

  • 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:
    ...
    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

Examples

Below uses myapp as an example, change it to the alias or container name you have set.

# docker compose - full namespace (see above)

# docker compose - inline yaml
labels:
  proxy.myapp.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.myapp.middlewares.oidc:

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

# route file
myapp:
  middlewares:
    oidc:

Redirect http

Redirect http requests to https

# docker labels
proxy.myapp.middlewares.redirect_http:

# route file
myapp:
  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.myapp.middlewares.custom_error_page:

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

# route file
myapp:
  middlewares:
    cloudflare_real_ip:

🔼Back to top

CIDR Whitelist

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

# route file
myapp:
  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.myapp.middlewares.ratelimit: |
  average: 100
  burst: 100
  periods: 1s

# route file
myapp:
  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.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

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.myapp.middlewares.request.set_headers: |
  X-Real-IP: $remote_host

🔼Back to top

Add headers

# 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

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.myapp.middlewares.modify_request.hide_headers: |
  X-Custom-Header1
  X-Custom-Header2

# route file
myapp:
  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.myapp.middlewares.hide_x_forwarded:

# route file
myapp:
  middlewares:
    hide_x_forwarded:

Set X-Forwarded-*

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

# docker labels
proxy.myapp.middlewares.set_x_forwarded:

# route file
myapp:
  middlewares:
    set_x_forwarded:

🔼Back to top

Middleware Compose

# 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
myapp:
  middlewares:
    myWhitelist@file:
# entrypoint
entrypoint:
  middlewares:
    myWhitelist@file:

🔼Back to top